/* find the real compiler. We just search the PATH to find a executable of the same name that isn't a link to ourselves */ static void find_compiler(int argc, char **argv) { char *base; char *path; orig_args = args_init(argc, argv); base = str_basename(argv[0]); /* we might be being invoked like "ccache gcc -c foo.c" */ if (strcmp(base, MYNAME) == 0) { args_remove_first(orig_args); free(base); if (strchr(argv[1],'/')) { /* a full path was given */ return; } base = str_basename(argv[1]); } /* support user override of the compiler */ if ((path=getenv("CCACHE_CC"))) { base = strdup(path); } orig_args->argv[0] = find_executable(base, MYNAME); /* can't find the compiler! */ if (!orig_args->argv[0]) { stats_update(STATS_COMPILER); perror(base); exit(1); } }
static void detect_swig() { char *basename = str_basename(orig_args->argv[0]); if (strstr(basename, "swig") || getenv("CCACHE_SWIG")) { swig = 1; } free(basename); }
/* find an executable by name in $PATH. Exclude any that are links to exclude_name */ char *find_executable(const char *name, const char *exclude_name) { char *path; char *tok; struct stat st1, st2; if (*name == '/') { return x_strdup(name); } path = getenv("F90CACHE_PATH"); if (!path) { path = getenv("PATH"); } if (!path) { fc_log("no PATH variable!?\n"); return NULL; } path = x_strdup(path); /* search the path looking for the first compiler of the right name that isn't us */ for (tok=strtok(path,":"); tok; tok = strtok(NULL, ":")) { char *fname; x_asprintf(&fname, "%s/%s", tok, name); /* look for a normal executable file */ if (access(fname, X_OK) == 0 && lstat(fname, &st1) == 0 && stat(fname, &st2) == 0 && S_ISREG(st2.st_mode)) { /* if its a symlink then ensure it doesn't point at something called exclude_name */ if (S_ISLNK(st1.st_mode)) { char *buf = x_realpath(fname); if (buf) { char *p = str_basename(buf); if (strcmp(p, exclude_name) == 0) { /* its a link to "f90cache" ! */ free(p); free(buf); continue; } free(buf); free(p); } } /* found it! */ free(path); return fname; } free(fname); } return NULL; }
void usage(char* av0) { buffer_putm_internal(buffer_1, "Usage: ", str_basename(av0), " [OPTIONS] <FILE.list | TARGET LINK>\n", "\n", "Options:\n", "\n", " -h, --help Show this help\n", " -v, --verbose Be verbose\n", "\n", 0); buffer_flush(buffer_1); }
int main(int argc, char* argv[]) { int optarg; for(optarg = 1; optarg < argc; ++optarg) { char *dll, *filename, *dll_name; size_t dllsz; uint32 i, *name_rvas, nexp, num_entries; pe_data_directory *datadir; pe_export_directory* expdata; pe32_opt_header* opt_hdr_32; pe_type type; filename = argv[optarg]; dll = mmap_read(filename, &dllsz); if(dll == NULL) return 1; dll_name = str_basename(filename); opt_hdr_32 = pe_header_opt(dll); type = uint16_get(&opt_hdr_32->magic); datadir = pe_get_datadir(dll, &num_entries); if(num_entries < 1) /* no exports */ return 1; expdata = pe_rva2ptr(dll, uint32_get(&datadir->virtual_address)); nexp = uint32_get(&expdata->number_of_names); name_rvas = pe_rva2ptr(dll, uint32_get(&expdata->address_of_names)); buffer_puts(buffer_1, "EXPORTS\n"); (void)dll_name; /* buffer_putm_3(buffer_1, "LIBRARY ", dll_name, "\n"); */ for(i = 0; i < nexp; i++) { buffer_putm_3(buffer_1, " ", pe_rva2ptr(dll, uint32_get(&name_rvas[i])), " @ "); buffer_putulong(buffer_1, 1 + i); buffer_putnlflush(buffer_1); } mmap_unmap(dll, dllsz); } return 0; }
void usage(char* av0) { buffer_putm_internal(buffer_1, "Usage: ", str_basename(av0), " [OPTIONS] [FILES...]\n" "\n" "Options:\n" "\n" " -h, --help Show this help\n" " -s, --single-quote Use ' as quote\n" " -d, --double-quote Use \" as quote\n" " -o, --one-line One-line\n" " -c, --compact Compact\n" " -l, --indent NUM Indent level\n" "\n", 0); buffer_flush(buffer_1); }
void usage(char* argv0) { buffer_putm_internal(buffer_1, "Usage: ", str_basename(argv0), " [-o output] [infile or stdin]\n\n", " -1 ... -9 compression level; default is 3\n", "\n", "Options\n", " -h, --help show this help\n", " -l, --list long list\n", " -n, --numeric numeric user/group\n", " -r, --relative relative path\n", " -o, --output FILE write output to FILE\n", " -x, --exclude PATTERN exclude entries matching PATTERN\n", " -t, --time-style FORMAT format time according to FORMAT\n", " -m, --min-size BYTES minimum file size\n", " -L, --dereference dereference symlinks\n", 0); buffer_putnlflush(buffer_1); }
/* find the hash for a command. The hash includes all argument lists, plus the output from running the compiler with -E */ static void find_hash(ARGS *args) { int i; char *path_stdout, *path_stderr; char *hash_dir; char *s; struct stat st; int status; int nlevels = 2; char *input_base; char *tmp; if ((s = getenv("CCACHE_NLEVELS"))) { nlevels = atoi(s); if (nlevels < 1) nlevels = 1; if (nlevels > 8) nlevels = 8; } hash_start(); /* when we are doing the unifying tricks we need to include the input file name in the hash to get the warnings right */ if (enable_unify) { hash_string(input_file); } /* we have to hash the extension, as a .i file isn't treated the same by the compiler as a .ii file */ hash_string(i_extension); /* first the arguments */ for (i=1;i<args->argc;i++) { /* some arguments don't contribute to the hash. The theory is that these arguments will change the output of -E if they are going to have any effect at all, or they only affect linking */ if (i < args->argc-1) { if (strcmp(args->argv[i], "-I") == 0 || strcmp(args->argv[i], "-include") == 0 || strcmp(args->argv[i], "-L") == 0 || strcmp(args->argv[i], "-D") == 0 || strcmp(args->argv[i], "-idirafter") == 0 || strcmp(args->argv[i], "-isystem") == 0) { i++; continue; } } if (strncmp(args->argv[i], "-I", 2) == 0 || strncmp(args->argv[i], "-L", 2) == 0 || strncmp(args->argv[i], "-D", 2) == 0 || strncmp(args->argv[i], "-idirafter", 10) == 0 || strncmp(args->argv[i], "-isystem", 8) == 0) { continue; } if (strncmp(args->argv[i], "--specs=", 8) == 0 && stat(args->argv[i]+8, &st) == 0) { /* if given a explicit specs file, then hash that file, but don't include the path to it in the hash */ hash_file(args->argv[i]+8); continue; } /* all other arguments are included in the hash */ hash_string(args->argv[i]); } /* the compiler driver size and date. This is a simple minded way to try and detect compiler upgrades. It is not 100% reliable */ if (stat(args->argv[0], &st) != 0) { cc_log("Couldn't stat the compiler!? (argv[0]='%s')\n", args->argv[0]); stats_update(STATS_COMPILER); failed(); } /* also include the hash of the compiler name - as some compilers use hard links and behave differently depending on the real name */ if (st.st_nlink > 1) { hash_string(str_basename(args->argv[0])); } hash_int(st.st_size); hash_int(st.st_mtime); /* possibly hash the current working directory */ if (getenv("CCACHE_HASHDIR")) { char *cwd = gnu_getcwd(); if (cwd) { hash_string(cwd); free(cwd); } } /* ~/hello.c -> tmp.hello.123.i limit the basename to 10 characters in order to cope with filesystem with small maximum filename length limits */ input_base = str_basename(input_file); tmp = strchr(input_base, '.'); if (tmp != NULL) { *tmp = 0; } if (strlen(input_base) > 10) { input_base[10] = 0; } /* now the run */ x_asprintf(&path_stdout, "%s/%s.tmp.%s.%s", temp_dir, input_base, tmp_string(), i_extension); x_asprintf(&path_stderr, "%s/tmp.cpp_stderr.%s", temp_dir, tmp_string()); if (!direct_i_file) { /* run cpp on the input file to obtain the .i */ args_add(args, "-E"); args_add(args, input_file); status = execute(args->argv, path_stdout, path_stderr); args_pop(args, 2); } else { /* we are compiling a .i or .ii file - that means we can skip the cpp stage and directly form the correct i_tmpfile */ path_stdout = input_file; if (create_empty_file(path_stderr) != 0) { stats_update(STATS_ERROR); cc_log("failed to create empty stderr file\n"); failed(); } status = 0; } if (status != 0) { if (!direct_i_file) { unlink(path_stdout); } unlink(path_stderr); cc_log("the preprocessor gave %d\n", status); stats_update(STATS_PREPROCESSOR); failed(); } /* if the compilation is with -g then we have to include the whole of the preprocessor output, which means we are sensitive to line number information. Otherwise we can discard line number info, which makes us less sensitive to reformatting changes Note! I have now disabled the unification code by default as it gives the wrong line numbers for warnings. Pity. */ if (!enable_unify) { hash_file(path_stdout); } else { if (unify_hash(path_stdout) != 0) { stats_update(STATS_ERROR); failed(); } } hash_file(path_stderr); i_tmpfile = path_stdout; if (!getenv("CCACHE_CPP2")) { /* if we are using the CPP trick then we need to remember this stderr data and output it just before the main stderr from the compiler pass */ cpp_stderr = path_stderr; } else { unlink(path_stderr); free(path_stderr); } /* we use a N level subdir for the cache path to reduce the impact on filesystems which are slow for large directories */ s = hash_result(); x_asprintf(&hash_dir, "%s/%c", cache_dir, s[0]); x_asprintf(&stats_file, "%s/stats", hash_dir); for (i=1; i<nlevels; i++) { char *p; if (create_dir(hash_dir) != 0) { cc_log("failed to create %s\n", hash_dir); failed(); } x_asprintf(&p, "%s/%c", hash_dir, s[i]); free(hash_dir); hash_dir = p; } if (create_dir(hash_dir) != 0) { cc_log("failed to create %s\n", hash_dir); failed(); } x_asprintf(&hashname, "%s/%s", hash_dir, s+nlevels); free(hash_dir); }