// Don't test printing code to thoroughly because it will change a lot void test_print_functions() { char* output_ptr = NULL; size_t output_len = 0; FILE* output = NULL; node_p module = node_alloc(NT_MODULE); module->module.filename = str_from_c("tokenizer_test.c/test_print_functions"); module->module.source = str_from_c("x = \n1 + y\n\"next\nline\""); tokenize(module->module.source, &module->tokens, stderr); st_check_int(module->tokens.len, 12); output = open_memstream(&output_ptr, &output_len); token_print(output, &module->tokens.ptr[10], TP_SOURCE); fclose(output); st_check_str(output_ptr, "\"next\nline\""); output = open_memstream(&output_ptr, &output_len); token_print(output, &module->tokens.ptr[10], TP_DUMP); fclose(output); st_check_not_null( strstr(output_ptr, "\"next\nline\"") ); output = open_memstream(&output_ptr, &output_len); token_print(output, &module->tokens.ptr[10], TP_INLINE_DUMP); fclose(output); st_check_not_null( strstr(output_ptr, "\"next\\nline\"") ); }
void cook_search_list(const opcode_context_ty *ocp, string_list_ty *slp) { string_ty *s; id_ty *idp; /* * make sure the variable exists */ trace(("cook_search_list()\n{\n")); idp = opcode_context_id_search(ocp, id_search_list); if (!idp) { string_list_constructor(slp); s = str_from_c("."); string_list_append(slp, s); str_free(s); opcode_context_id_assign ( (opcode_context_ty *)ocp, id_search_list, id_variable_new(slp), 0 ); string_list_destructor(slp); } /* * extract its string value */ id_variable_query(idp, slp); /* * make sure the search list isn't empty * make sure the search list has "." as the first element */ if ( !slp->nstrings || slp->string[0]->str_length != 1 || slp->string[0]->str_text[0] != '.' ) { s = str_from_c("."); string_list_prepend(slp, s); str_free(s); opcode_context_id_assign ( (opcode_context_ty *)ocp, id_search_list, id_variable_new(slp), 0 ); } trace(("}\n")); }
bool get_subdirectories( std::vector<std::string> &list, const std::string &path ) { #ifdef SFML_SYSTEM_WINDOWS std::string temp = path + "*"; struct _finddata_t t; intptr_t srch = _findfirst( temp.c_str(), &t ); if ( srch < 0 ) return false; do { std::string what; str_from_c( what, t.name ); if ( ( what.compare( "." ) == 0 ) || ( what.compare( ".." ) == 0 ) ) continue; if ( t.attrib & _A_SUBDIR ) list.push_back( what ); } while ( _findnext( srch, &t ) == 0 ); _findclose( srch ); #else DIR *dir; struct dirent *ent; if ( (dir = opendir( path.c_str() )) == NULL ) return false; while ((ent = readdir( dir )) != NULL ) { std::string name; str_from_c( name, ent->d_name ); if (( name.compare( "." ) == 0 ) || ( name.compare( ".." ) == 0 )) continue; struct stat st; stat( (path + name).c_str(), &st ); if ( S_ISDIR( st.st_mode ) ) list.push_back( name ); } closedir( dir ); #endif return true; }
static blob_list_ty * ifndef(blob_list_ty *blp, string_list_ty *ref) { blob_ty *arg; blob_list_ty *result; blob_ty *bp; arg = blp->list[0]; result = ifdef(blp, ref); bp = blob_alloc(str_from_c("[not"), arg->file_name, arg->line_number); blob_list_prepend(result, bp); bp = blob_alloc(str_from_c("]"), arg->file_name, arg->line_number); blob_list_append(result, bp); return result; }
void str_initialize(void) { str_hash_ty j; hash_modulus = 1 << 8; /* MUST be a power of 2 */ hash_mask = hash_modulus - 1; hash_load = 0; hash_table = mem_alloc(hash_modulus * sizeof(string_ty *)); for (j = 0; j < hash_modulus; ++j) hash_table[j] = 0; str_true = str_from_c("1"); str_false = str_from_c(""); }
stmt_ty * stmt_if_alloc(blob_list_ty *condition, stmt_ty *then_clause, stmt_ty *else_clause) { stmt_if_ty *result; blob_list_ty *c2; table_ty *tp; trace(("stmt_if_alloc()\n{\n")); result = (stmt_if_ty *)stmt_alloc(&method); assert(condition->length >= 1); for (tp = table; tp < ENDOF(table); ++tp) { if (!tp->fast) tp->fast = str_from_c(tp->name); if (str_equal(condition->list[0]->text, tp->fast)) break; } assert(tp < ENDOF(table)); if (tp >= ENDOF(table)) tp = &table[0]; c2 = tp->rewrite(condition, &result->ref); blob_list_free(condition); result->condition = c2; result->then_clause = then_clause; result->else_clause = else_clause; stmt_variable_merge((stmt_ty *)result, then_clause); if (else_clause) stmt_variable_merge((stmt_ty *)result, else_clause); trace(("}\n")); return (stmt_ty *)result; }
void fp_find_flush(void) { static string_ty *dot; fp_subdir_ty *sdp; if (!option_test(OPTION_FINGERPRINT_WRITE)) { trace(("no fp write\n")); return; } /* * Write out all of the known subdirectories, except dot. */ trace(("fp_find_flush()\n{\n")); need_to_write_dot = 0; if (subdir_stp) symtab_walk(subdir_stp, subdir_walk, 0); /* * Do dot last, so we catch all of the `cache_in_dot's. */ if (!dot) dot = str_from_c("."); sdp = fp_find_subdir(dot, 0); if (need_to_write_dot) sdp->dirty = 1; fp_subdir_write(sdp, &need_to_write_dot); trace(("}\n")); }
void lex_open(char *s) { trace(("lex_open()\n{\n")); assert(!input); blob_error_notify(notify); if (s) { string_ty *filename; filename = str_from_c(s); input = input_file_text_open(filename); str_free(filename); } else { input = input_file_text_open((string_ty *) 0); } line_number = 1; bol = 1; first = 1; colon_special = 1; error_count = 0; trace(("}\n")); }
void fp_tweak(void) { static string_ty *dot; if (!dot) dot = str_from_c("."); fp_subdir_tweak(fp_find_subdir(dot, 1)); }
std::string clean_path( const std::string &path, bool add_trailing_slash ) { std::string retval = path; if ( retval.empty() ) return retval; #ifdef SFML_SYSTEM_WINDOWS // substitute systemroot leading %SYSTEMROOT% if (( retval.size() >= 12 ) && ( retval.compare( 0, 12, "%SYSTEMROOT%" ) == 0 )) { std::string sysroot; str_from_c( sysroot, getenv( "SystemRoot" ) ); retval.replace( 0, 12, sysroot ); } else if (( retval.size() >= 14 ) && ( retval.compare( 0, 14, "%PROGRAMFILES%" ) == 0 )) { std::string pf; str_from_c( pf, getenv( "ProgramFiles" ) ); retval.replace( 0, 14, pf ); } #endif // substitute home dir for leading ~ if (( retval.size() >= 1 ) && ( retval.compare( 0, 1, "~" ) == 0 )) retval.replace( 0, 1, get_home_dir() ); // substitute home dir for leading $HOME if (( retval.size() >= 5 ) && ( retval.compare( 0, 5, "$HOME" ) == 0 )) retval.replace( 0, 5, get_home_dir() ); if (( add_trailing_slash ) #ifdef SFML_SYSTEM_WINDOWS && (retval[retval.size()-1] != '\\') #endif && (retval[retval.size()-1] != '/') && (directory_exists(retval)) ) retval += '/'; return retval; }
int main(int argc, char **argv) { string_ty *s; string_list_ty sl; size_t j; arglex_init(argc, argv, argtab); str_initialize(); switch (arglex()) { case arglex_token_help: help((char *)0, usage); exit(0); case arglex_token_version: version(); exit(0); default: break; } string_list_constructor(&sl); while (arglex_token != arglex_token_eoln) { switch (arglex_token) { default: generic_argument(usage); continue; case arglex_token_warning: warning++; break; case arglex_token_string: s = str_from_c(arglex_value.alv_string); string_list_append_unique(&sl, s); str_free(s); break; } arglex(); } if (!sl.nstrings) { error_intl(0, i18n("no files named")); usage(); } for (j = 0; j < sl.nstrings; ++j) file_check(sl.string[j]); exit(0); return 0; }
static int interpret(string_list_ty *result, const string_list_ty *arg, const expr_position_ty *pp, const struct opcode_context_ty *ocp) { string_ty *s; size_t j; struct passwd *pw; trace(("home\n")); (void)ocp; if (arg->nstrings < 2) { const char *cp; cp = home_directory(); assert(cp); s = str_from_c(cp); string_list_append(result, s); str_free(s); return 0; } for (j = 1; j < arg->nstrings; ++j) { s = arg->string[j]; pw = getpwnam(s->str_text); if (!pw) { sub_context_ty *scp; scp = sub_context_new(); sub_var_set_string(scp, "Name", s); error_with_position(pp, scp, i18n("user \"$name\" unknown")); sub_context_delete(scp); return -1; } s = str_from_c(pw->pw_dir); string_list_append(result, s); str_free(s); } return 0; }
fp_subdir_ty * fp_find_subdir(string_ty *dirname, int ok_to_read) { fp_subdir_ty *sdp; /* * Most of the time, we have already polled this one before, * so do a quick lookup and see. */ trace(("fp_find_subdir(dirname = \"%s\")\n{\n", dirname->str_text)); if (!subdir_stp) { static string_ty *dot; subdir_stp = symtab_alloc(10); subdir_stp->reap = subdir_reap; /* * Read dot (the current directory) immediately. * This primes the cache with all the things that were * found to be read-only on previous runs. */ if (!dot) dot = str_from_c("."); sdp = fp_subdir_new(dot); symtab_assign(subdir_stp, dot, sdp); fp_subdir_read(sdp); } sdp = symtab_query(subdir_stp, dirname); if (!sdp) { /* * It's a new one, we must allocate it. */ sdp = fp_subdir_new(dirname); symtab_assign(subdir_stp, dirname, sdp); } if (ok_to_read && sdp->need_to_read) { /* * Read in the cache file from the directory, * if it exists. This causes a number of * fp_find_update calls (see below), one for * each entry. */ fp_subdir_read(sdp); } trace(("return %08lX;\n", (long)sdp)); trace(("}\n")); return sdp; }
static void set_command_line_goals(void) { string_ty *name; opcode_context_ty *ocp; name = str_from_c("command-line-goals"); ocp = opcode_context_new(0, 0); opcode_context_id_assign(ocp, name, id_variable_new(&option.o_target), 0); opcode_context_delete(ocp); str_free(name); }
void builtin_initialize(void) { builtin_ty **fpp; string_ty *s; for (fpp = func; fpp < ENDOF(func); ++fpp) { s = str_from_c((*fpp)->name); symtab_assign(id_global_stp(), s, id_builtin_new(*fpp)); str_free(s); } }
graph_walk_status_ty graph_walk(graph_ty *gp) { int nproc; string_ty *key; string_ty *s; id_ty *idp; string_list_ty wl; opcode_context_ty *ocp; /* * see if the jobs variable is set */ key = str_from_c("parallel_jobs"); ocp = opcode_context_new(0, 0); idp = opcode_context_id_search(ocp, key); /* * extract the number of jobs */ nproc = 1; if (idp) { id_variable_query(idp, &wl); if (wl.nstrings == 1) { nproc = atoi(wl.string[0]->str_text); if (nproc < 1) nproc = 1; } string_list_destructor(&wl); } /* * Set the jobs variable to precisely reflect what we are going * to do, should the recipes use it in some way. */ string_list_constructor(&wl); s = str_format("%d", nproc); string_list_append(&wl, s); str_free(s); opcode_context_id_assign(ocp, key, id_variable_new(&wl), 0); string_list_destructor(&wl); str_free(key); opcode_context_delete(ocp); /* * walk the graph */ return graph_walk_inner(gp, graph_recipe_run, nproc); }
static blob_list_ty * ifdef(blob_list_ty *blp, string_list_ty *ref) { blob_ty *bp; blob_list_ty *result; size_t j; bp = blp->list[0]; result = blob_list_alloc(); blob_list_append ( result, blob_alloc(str_from_c("[defined"), bp->file_name, bp->line_number) ); for (j = 1; j < blp->length; ++j) variable_rename(blp->list[j], result, ref, VAREN_QUOTE_SPACES); blob_list_append ( result, blob_alloc(str_from_c("]"), bp->file_name, bp->line_number) ); return result; }
static void subdir_walk(symtab_ty *stp, string_ty *key, void *data, void *aux) { fp_subdir_ty *sdp; static string_ty *dot; trace(("subdir_walk(key = \"%s\")\n{\n", key->str_text)); (void)stp; (void)key; (void)aux; if (!dot) dot = str_from_c("."); sdp = data; if (!str_equal(sdp->path, dot)) fp_subdir_write(sdp, &need_to_write_dot); trace(("}\n")); }
string_ty * str_field(string_ty *s, int sep, int fldnum) { char *cp; char *ep; cp = s->str_text; while (fldnum > 0) { ep = strchr(cp, sep); if (!ep) return 0; cp = ep + 1; --fldnum; } ep = strchr(cp, sep); if (ep) return str_n_from_c(cp, ep - cp); return str_from_c(cp); }
static int echo_command(string_list_ty *wlp) { static string_ty *echo; string_ty *tmp; char *cp; if (!echo) echo = str_from_c("echo"); if (wlp->nstrings < 1 || !str_equal(wlp->string[0], echo)) return 0; tmp = wl2str(wlp, 0, wlp->nstrings - 1, (char *)0); for (cp = tmp->str_text; *cp; ++cp) { if (strchr("^|>", *cp)) { str_free(tmp); return 0; } } str_free(tmp); return 1; }
static int mtime_interpret(string_list_ty *result, const string_list_ty *args, const struct expr_position_ty *pp, const struct opcode_context_ty *ocp) { size_t j; trace(("mtime\n")); (void)pp; assert(result); assert(args); assert(args->nstrings); for (j = 1; j < args->nstrings; j++) { time_t mtime; long depth; depth = 32767; mtime = cook_mtime_newest(ocp, args->string[j], &depth, depth); if (mtime < 0) return -1; if (mtime == 0) string_list_append(result, str_false); else { struct tm *tm; char buffer[1000]; string_ty *s; tm = localtime(&mtime); strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", tm); s = str_from_c(buffer); string_list_append(result, s); str_free(s); } } return 0; }
void test_samples() { for(size_t i = 0; i < sizeof(samples) / sizeof(samples[0]); i++) { char* code = samples[i].code; //printf("test: %s\n", code); token_list_t tokens = { 0 }; tokenize(str_from_c(code), &tokens, stderr); st_check_int(tokens.len, samples[i].tokens_len); for(size_t j = 0; j < samples[i].tokens_len; j++) { token_p actual_token = &tokens.ptr[j]; token_p expected_token = &samples[i].tokens_ptr[j]; st_check_msg(actual_token->type == expected_token->type, "got %s, expected %s", token_type_name(actual_token->type), token_type_name(expected_token->type)); st_check_int(actual_token->source.len, expected_token->source.len); st_check_strn(actual_token->source.ptr, expected_token->source.ptr, expected_token->source.len); if (actual_token->type == T_INT) { st_check(actual_token->int_val == expected_token->int_val); } else if (actual_token->type == T_ERROR) { // Check that an error message is present, exact content doesn't matter, will change anyway st_check(actual_token->str_val.len > 0); st_check_not_null(actual_token->str_val.ptr); } else if (expected_token->str_val.ptr != NULL) { st_check_int(actual_token->str_val.len, expected_token->str_val.len); st_check_strn(actual_token->str_val.ptr, expected_token->str_val.ptr, expected_token->str_val.len); } else { st_check_null(actual_token->str_val.ptr); st_check_int(actual_token->str_val.len, 0); } } for(size_t j = 0; j < tokens.len; j++) token_cleanup(&tokens.ptr[j]); list_destroy(&tokens); } }
static int reserved(string_ty *s) { typedef struct table_ty table_ty; struct table_ty { char *name; int token; }; static table_ty table[] = { { "override", OVERRIDE }, { "include", INCLUDE2 }, { "-include", INCLUDE3 }, { ".include", INCLUDE }, { "vpath", VPATH }, { "VPATH", VPATH2 }, { "ifdef", IF }, { "ifndef", IF }, { "ifeq", IF }, { "ifneq", IF }, { "else", ELSE }, { "endif", ENDIF }, { "endef", ENDDEF }, { "define", DEFINE }, { "export", EXPORT }, { "unexport", UNEXPORT }, }; static symtab_ty *symtab; int *data; string_ty *name; char *cp; if (!symtab) { table_ty *tp; symtab = symtab_alloc(SIZEOF(table)); for (tp = table; tp < ENDOF(table); ++tp) { name = str_from_c(tp->name); symtab_assign(symtab, name, &tp->token); str_free(name); } } cp = strchr(s->str_text, '('); if (cp) { name = str_n_from_c(s->str_text, cp - s->str_text); data = symtab_query(symtab, name); str_free(name); } else data = symtab_query(symtab, s); if (data) return *data; return 0; }
static opcode_status_ty execute(const opcode_ty *op, opcode_context_ty *icp) { opcode_status_ty status; const opcode_setenv_append_ty *this; string_list_ty *name; string_list_ty *value; string_ty *s; char *tmp; trace(("opcode_setenv_append::execute()\n{\n")); status = opcode_status_success; this = (const opcode_setenv_append_ty *)op; value = opcode_context_string_list_pop(icp); name = opcode_context_string_list_pop(icp); switch (name->nstrings) { case 0: error_with_position ( &this->pos, 0, i18n("lefthand side of assignment is empty") ); status = opcode_status_error; break; case 1: /* * If the environment variable is already set, prepend * its existing value to the value list the user gave us. */ tmp = getenv(name->string[0]->str_text); if (tmp) { string_ty *tmp2; tmp2 = str_from_c(tmp); string_list_prepend(value, tmp2); str_free(tmp2); } s = wl2str(value, 0, value->nstrings, " "); env_set(name->string[0]->str_text, s->str_text); str_free(s); break; default: error_with_position ( &this->pos, 0, i18n("lefthand side of assignment is more than one word") ); status = opcode_status_error; break; } string_list_delete(name); string_list_delete(value); trace(("return %s;\n", opcode_status_name(status))); trace(("}\n")); return status; }
bool get_basename_from_extension( std::vector<std::string> &list, const std::string &path, const std::string &extension, bool strip_extension ) { #ifdef SFML_SYSTEM_WINDOWS std::string temp = path + "*" + extension; struct _finddata_t t; intptr_t srch = _findfirst( temp.c_str(), &t ); if ( srch < 0 ) return false; do { std::string what; str_from_c( what, t.name ); // I don't know why but the search filespec we are using // "path/*.ext"seems to also match "path/*.ext*"... so we // do the tail comparison below on purpose to catch this... #else DIR *dir; struct dirent *ent; if ( (dir = opendir( path.c_str() )) == NULL ) return false; while ((ent = readdir( dir )) != NULL ) { std::string what; str_from_c( what, ent->d_name ); #endif if ( ( what.compare( "." ) == 0 ) || ( what.compare( ".." ) == 0 ) ) continue; if ( tail_compare( what, extension ) ) { if ( strip_extension && ( what.size() > extension.size() )) { std::string bname = what.substr( 0, what.size() - extension.size() ); // don't add duplicates if we are stripping extension // example: if there is both foo.zip and foo.7z // if ( list.empty() || ( bname.compare( list.back() ) != 0 )) list.push_back( bname ); } else list.push_back( what ); } #ifdef SFML_SYSTEM_WINDOWS } while ( _findnext( srch, &t ) == 0 ); _findclose( srch ); #else } closedir( dir ); #endif std::sort( list.begin(), list.end() ); return !(list.empty()); }
int main(int argc, char **argv) { int retval; /* * Some versions of cron(8) and at(1) set SIGCHLD to SIG_IGN. * This is kinda dumb, because it breaks assumprions made in * libc (like pclose, for instance). It also blows away most * of Cook's process handling. We explicitly set the SIGCHLD * signal handling to SIG_DFL to make sure this signal does what * we expect no matter how we are invoked. */ #ifdef SIGCHLD signal(SIGCHLD, SIG_DFL); #else signal(SIGCLD, SIG_DFL); #endif /* * initialize things * (order is critical here) */ progname_set(argv[0]); str_initialize(); id_initialize(); lex_initialize(); /* * parse the COOK environment variable */ arglex_init_from_env(argv[0], argtab); argparse(OPTION_LEVEL_ENVIRONMENT); /* * parse the command line */ arglex_init(argc, argv, argtab); argparse(OPTION_LEVEL_COMMAND_LINE); option_tidy_up(); log_open(); /* * turn on progress stars if they asked for them */ if (option_test(OPTION_STAR)) star_enable(); /* * If we were asked to update the fingerprints, do it here. * We don't actually ant to read in the cookbook. */ if (option.fingerprint_update) { fp_tweak(); quit(0); } /* * read in the cook book * * If there are #include-cooked directives, * we may need to do it more than once. */ if (!option.o_book) fatal_intl(0, i18n("no book found")); for (;;) { int status; size_t j; builtin_initialize(); /* * instanciate the command line variable assignments */ for (j = 0; j < option.o_vardef.nstrings; ++j) { char *s; char *cp; string_ty *name; string_ty *value; string_list_ty wl; opcode_context_ty *ocp; s = option.o_vardef.string[j]->str_text; cp = strchr(s, '='); assert(cp); if (!cp) continue; name = str_n_from_c(s, cp - s); value = str_from_c(cp + 1); str2wl(&wl, value, (char *)0, 0); str_free(value); ocp = opcode_context_new(0, 0); opcode_context_id_assign(ocp, name, id_variable_new(&wl), 0); opcode_context_delete(ocp); str_free(name); string_list_destructor(&wl); } set_command_line_goals(); parse(option.o_book); status = cook_auto_required(); if (status < 0) quit(1); if (!status) break; id_reset(); cook_reset(); } /* * work out what to cook. * If no targets have been given, use the first explicit recipe. */ set_command_line_goals(); if (!option.o_target.nstrings) cook_find_default(&option.o_target); assert(option.o_target.nstrings); /* * cook the target */ if (option.pairs) retval = cook_pairs(&option.o_target); else if (option.script) retval = cook_script(&option.o_target); else if (option.web) retval = cook_web(&option.o_target); else retval = cook(&option.o_target); #ifdef DEBUG fflush_slowly_report(); #endif quit(retval); /*NOTREACHED*/ return 0; }
static void argparse(option_level_ty level) { option_number_ty type; string_ty *s; sub_context_ty *scp; int fingerprint_update; type = -1; fingerprint_update = 0; switch (arglex()) { case arglex_token_help: if (level != OPTION_LEVEL_COMMAND_LINE) { not_in_env: scp = sub_context_new(); sub_var_set(scp, "Name", "%s", arglex_value.alv_string); fatal_intl(scp, i18n("may not use $name in environment variable")); /* NOTREACHED */ } help((char *)0, usage); quit(0); case arglex_token_version: if (level != OPTION_LEVEL_COMMAND_LINE) goto not_in_env; version(); quit(0); default: break; } while (arglex_token != arglex_token_eoln) { switch (arglex_token) { default: generic_argument(usage); continue; case arglex_token_include: if (arglex() != arglex_token_string) { arg_needs_string(arglex_token_include, usage); /* NOTREACHED */ } s = str_from_c(arglex_value.alv_string); string_list_append_unique(&option.o_search_path, s); str_free(s); break; case arglex_token_reason: type = OPTION_REASON; normal_on: if (option_already(type, level)) { too_many: arg_duplicate_cur(usage); /* NOTREACHED */ } option_set(type, level, 1); break; case arglex_token_reason_not: type = OPTION_REASON; normal_off: if (option_already(type, level)) goto too_many; option_set(type, level, 0); break; case arglex_token_cascade: type = OPTION_CASCADE; goto normal_on; case arglex_token_cascade_not: type = OPTION_CASCADE; goto normal_off; case arglex_token_disassemble: type = OPTION_DISASSEMBLE; goto normal_on; case arglex_token_disassemble_not: type = OPTION_DISASSEMBLE; goto normal_off; case arglex_token_tty: type = OPTION_TERMINAL; goto normal_on; case arglex_token_tty_not: type = OPTION_TERMINAL; goto normal_off; case arglex_token_precious: type = OPTION_PRECIOUS; goto normal_on; case arglex_token_precious_not: type = OPTION_PRECIOUS; goto normal_off; case arglex_token_log: if (option_already(OPTION_LOGGING, level)) goto too_many; option_set(OPTION_LOGGING, level, 1); if (arglex() != arglex_token_string) continue; if (option.o_logfile) str_free(option.o_logfile); option.o_logfile = str_from_c(arglex_value.alv_string); break; case arglex_token_log_not: type = OPTION_LOGGING; goto normal_off; case arglex_token_book: if (option_already(OPTION_BOOK, level)) goto too_many; option_set(OPTION_BOOK, level, 1); if (arglex() != arglex_token_string) continue; if (option.o_book) str_free(option.o_book); option.o_book = str_from_c(arglex_value.alv_string); break; case arglex_token_book_not: type = OPTION_BOOK; goto normal_off; case arglex_token_include_cooked: type = OPTION_INCLUDE_COOKED; goto normal_on; case arglex_token_include_cooked_not: type = OPTION_INCLUDE_COOKED; goto normal_off; case arglex_token_include_cooked_warning: type = OPTION_INCLUDE_COOKED_WARNING; goto normal_on; case arglex_token_include_cooked_warning_not: type = OPTION_INCLUDE_COOKED_WARNING; goto normal_off; case arglex_token_silent: type = OPTION_SILENT; goto normal_on; case arglex_token_silent_not: type = OPTION_SILENT; goto normal_off; case arglex_token_tell_position: type = OPTION_TELL_POSITION; goto normal_on; case arglex_token_tell_position_not: type = OPTION_TELL_POSITION; goto normal_off; case arglex_token_metering: type = OPTION_METER; goto normal_on; case arglex_token_metering_not: type = OPTION_METER; goto normal_off; case arglex_token_touch: type = OPTION_TOUCH; goto normal_on; case arglex_token_touch_not: type = OPTION_TOUCH; goto normal_off; case arglex_token_action: type = OPTION_ACTION; goto normal_on; case arglex_token_action_not: type = OPTION_ACTION; goto normal_off; case arglex_token_persevere: type = OPTION_PERSEVERE; goto normal_on; case arglex_token_persevere_not: type = OPTION_PERSEVERE; goto normal_off; case arglex_token_errok: type = OPTION_ERROK; goto normal_on; case arglex_token_errok_not: type = OPTION_ERROK; goto normal_off; case arglex_token_force: type = OPTION_FORCE; goto normal_on; case arglex_token_force_not: type = OPTION_FORCE; goto normal_off; case arglex_token_fingerprint: type = OPTION_FINGERPRINT; goto normal_on; case arglex_token_fingerprint_not: type = OPTION_FINGERPRINT; goto normal_off; case arglex_token_fingerprint_update: if (level != OPTION_LEVEL_COMMAND_LINE) goto not_in_env; if (option.fingerprint_update) goto too_many; option.fingerprint_update++; break; case arglex_token_pairs: if (level != OPTION_LEVEL_COMMAND_LINE) goto not_in_env; if (option.pairs) goto too_many; option.pairs++; break; case arglex_token_script: if (level != OPTION_LEVEL_COMMAND_LINE) goto not_in_env; if (option.script) goto too_many; option.script++; break; case arglex_token_web: if (level != OPTION_LEVEL_COMMAND_LINE) goto not_in_env; if (option.web) goto too_many; option.web++; break; case arglex_token_string: if (level != OPTION_LEVEL_COMMAND_LINE) { if (strchr(arglex_value.alv_string, '=')) { fatal_intl ( 0, i18n("may not assign variables in environment variable") ); } else { fatal_intl ( 0, i18n("may not name targets in environment variable") ); } } else { char *cp; cp = strchr(arglex_value.alv_string, '='); if (!cp) { s = str_from_c(arglex_value.alv_string); string_list_append(&option.o_target, s); str_free(s); } else { s = str_from_c(arglex_value.alv_string); string_list_append(&option.o_vardef, s); str_free(s); } } break; case arglex_token_star: type = OPTION_STAR; goto normal_on; case arglex_token_star_not: type = OPTION_STAR; goto normal_off; case arglex_token_strip_dot: type = OPTION_STRIP_DOT; goto normal_on; case arglex_token_strip_dot_not: type = OPTION_STRIP_DOT; goto normal_off; case arglex_token_update: type = OPTION_UPDATE; goto normal_on; case arglex_token_update_not: type = OPTION_UPDATE; goto normal_off; case arglex_token_parallel: if (arglex() != arglex_token_number) { s = str_from_c("parallel_jobs=4"); string_list_append(&option.o_vardef, s); str_free(s); continue; } s = str_format("parallel_jobs=%d", (int)arglex_value.alv_number); string_list_append(&option.o_vardef, s); str_free(s); break; case arglex_token_parallel_not: s = str_from_c("parallel_jobs=1"); string_list_append(&option.o_vardef, s); str_free(s); break; case arglex_token_shallow: type = OPTION_SHALLOW; goto normal_on; case arglex_token_shallow_not: type = OPTION_SHALLOW; goto normal_off; } arglex(); } }
arglex_token_ty arglex(void) { arglex_table_ty *tp; int j; arglex_table_ty *hit[20]; int nhit; char *arg; static char *pushback[3]; static int pushback_depth; trace(("arglex()\n{\n")); if (pushback_depth) { /* * the second half of a "-foo=bar" style argument. */ arg = pushback[--pushback_depth]; } else { if (argc <= 0) { arglex_token = arglex_token_eoln; arg = ""; goto done; } arg = argv[0]; argc--; argv++; /* * See if it looks like a GNU "-foo=bar" option. * Split it at the '=' to make it something the * rest of the code understands. */ if (arg[0] == '-' && arg[1] != '=') { char *eqp; eqp = strchr(arg, '='); if (eqp) { pushback[pushback_depth++] = eqp + 1; *eqp = 0; } } /* * Turn the GNU-style leading "--" * into "-" if necessary. */ if (arg[0] == '-' && arg[1] == '-' && arg[2] && !is_a_number(arg + 1)) ++arg; } /* * see if it is a number */ if (is_a_number(arg)) { arglex_token = arglex_token_number; goto done; } /* * scan the tables to see what it matches */ nhit = 0; partial = 0; for (tp = table; tp < ENDOF(table); tp++) { if (arglex_compare(tp->name, arg)) hit[nhit++] = tp; } if (utable) { for (tp = utable; tp->name; tp++) { if (arglex_compare(tp->name, arg)) hit[nhit++] = tp; } } /* * deal with unknown or ambiguous options */ switch (nhit) { case 0: /* * not found in the tables */ if (*arg == '-') arglex_token = arglex_token_option; else arglex_token = arglex_token_string; break; case 1: if (partial) pushback[pushback_depth++] = (char *)partial; arg = hit[0]->name; arglex_token = hit[0]->token; break; default: { string_ty *s1; string_ty *s2; sub_context_ty *scp; s1 = str_from_c(hit[0]->name); for (j = 1; j < nhit; ++j) { s2 = str_format("%s, %s", s1->str_text, hit[j]->name); str_free(s1); s1 = s2; } scp = sub_context_new(); sub_var_set_charstar(scp, "Name", arg); sub_var_set_string(scp, "Guess", s1); fatal_intl(scp, i18n("option \"$name\" ambiguous ($guess)")); /* NOTREACHED */ } } /* * here for all exits */ done: arglex_value.alv_string = arg; trace(("return %d; /* \"%s\" */\n", arglex_token, arg)); trace(("}\n")); return arglex_token; }
static blob_list_ty * ifeq(blob_list_ty *blp, string_list_ty *ref) { blob_ty *arg; blob_ty *bp; blob_list_ty *result; string_ty *s; string_ty *s2; char *cp; size_t j; /* * allocate the result list */ trace(("ifeq()\n{\n")); result = blob_list_alloc(); /* * make sure we were given enough arguments */ if (blp->length < 2) { arg = blp->list[0]; blob_list_append ( result, blob_alloc(str_from_c("0"), arg->file_name, arg->line_number) ); trace(("}\n")); return result; } /* * turn the list of arguments into a single string */ arg = blp->list[1]; s = str_copy(blp->list[1]->text); for (j = 2; j < blp->length; ++j) { s2 = str_format("%s %s", s->str_text, blp->list[j]->text->str_text); str_free(s); s = s2; } bp = blob_alloc(s, arg->file_name, arg->line_number); /* * rename the variables * and reform to be a single string, again. */ variable_rename(bp, result, ref, VAREN_NO_QUOQUO); blob_free(bp); s = result->length ? str_copy(result->list[0]->text) : str_from_c("0"); for (j = 1; j < result->length; ++j) { s2 = str_format("%s %s", s->str_text, result->list[j]->text->str_text); str_free(s); s = s2; } blob_list_free(result); /* * construct the result */ result = blob_list_alloc(); switch (s->str_text[0]) { case '(': /* * ifeq (xxx,yyy) */ if (s->str_length < 3) goto useless; cp = strchr(s->str_text, ','); if (cp == 0 || s->str_text[s->str_length - 1] != ')') goto useless; blob_list_append ( result, blob_alloc(str_from_c("[in"), arg->file_name, arg->line_number) ); s2 = str_n_from_c(s->str_text + 1, cp - s->str_text - 1); if (s2->str_length == 0) s2 = str_from_c("\"\""); bp = blob_alloc(s2, arg->file_name, arg->line_number); blob_list_append(result, bp); s2 = str_n_from_c(cp + 1, s->str_text + s->str_length - cp - 2); if (s2->str_length == 0) s2 = str_from_c("\"\""); bp = blob_alloc(s2, arg->file_name, arg->line_number); blob_list_append(result, bp); blob_list_append ( result, blob_alloc(str_from_c("]"), arg->file_name, arg->line_number) ); break; case '\'': case '"': /* * ifeq "xxx" "yyy" */ if (s->str_length < 5) goto useless; cp = strchr(s->str_text + 1, s->str_text[0]); if ( !cp || cp[1] != ' ' || cp[2] != s->str_text[0] || s->str_text[s->str_length - 1] != s->str_text[0] ) goto useless; blob_list_append ( result, blob_alloc(str_from_c("[in"), arg->file_name, arg->line_number) ); s2 = str_n_from_c(s->str_text + 1, cp - s->str_text - 1); if (s2->str_length == 0) s2 = str_from_c("\"\""); bp = blob_alloc(s2, arg->file_name, arg->line_number); blob_list_append(result, bp); s2 = str_n_from_c(cp + 3, s->str_text + s->str_length - cp - 4); if (s2->str_length == 0) s2 = str_from_c("\"\""); bp = blob_alloc(s2, arg->file_name, arg->line_number); blob_list_append(result, bp); blob_list_append ( result, blob_alloc(str_from_c("]"), arg->file_name, arg->line_number) ); break; default: /* * We were given some useless thing, just rename the * variables and copy it through. */ useless: bp = blob_alloc(str_copy(s), arg->file_name, arg->line_number); blob_list_append(result, bp); break; } str_free(s); trace(("}\n")); return result; }
string_ty * flatten(string_ty *filename) { string_list_ty sl; static string_ty *root; static string_ty *dot; static string_ty *dotdot; size_t pos; size_t start; size_t j; string_ty *s; /* * Create some things we are going to need. */ if (!root) { root = str_from_c(""); dot = str_from_c("."); dotdot = str_from_c(".."); } /* * leading slash is special */ pos = 0; string_list_constructor(&sl); if (filename->str_text[0] == '/') { ++pos; string_list_append(&sl, root); } /* * Break it into slash-separaed words. */ for (;;) { while (pos < filename->str_length && filename->str_text[pos] == '/') ++pos; if (pos >= filename->str_length) break; start = pos; for (;;) { ++pos; if (pos >= filename->str_length || filename->str_text[pos] == '/') break; } /* * remember each word (except ".") */ s = str_n_from_c(filename->str_text + start, pos - start); if (!str_equal(s, dot)) string_list_append(&sl, s); str_free(s); } /* * Try as hard as possible to chuck out redundant stuff. */ for (;;) { int changed = 0; /* * "/.." -> "/" */ if ( sl.nstrings >= 2 && str_equal(sl.string[0], root) && str_equal(sl.string[1], dotdot) ) { string_list_remove_nth(&sl, 1); ++changed; } /* * "name/.." -> "" */ for (j = 0; j + 1 < sl.nstrings; ++j) { if (str_equal(sl.string[j], root)) continue; if (str_equal(sl.string[j], dotdot)) continue; if (!str_equal(sl.string[j + 1], dotdot)) continue; string_list_remove_nth(&sl, j); string_list_remove_nth(&sl, j); ++changed; --j; } /* * loop if anything changed, * bail if we can't find more to do */ if (!changed) break; } /* * reassemble the "cleaned" path */ s = wl2str_respect_empty(&sl, 0, sl.nstrings, "/", 1); string_list_destructor(&sl); return s; }