Example #1
0
/* 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);
	}
}
Example #2
0
static void detect_swig()
{
	char *basename = str_basename(orig_args->argv[0]);
	if (strstr(basename, "swig") || getenv("CCACHE_SWIG")) {
		swig = 1;
	}
	free(basename);
}
Example #3
0
/*
  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;
}
Example #4
0
File: sln.c Project: rsenn/dirlist
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);
}
Example #5
0
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;
}
Example #6
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);
}
Example #7
0
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);
}
Example #8
0
/* 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);
}