relocatable-driver.after (2138B)
1 /* Find the invoked compiler without relying on /proc or a shell wrapper. 2 An argv[0] containing a slash is already usable. Otherwise search PATH 3 with open(2); access(2) is intentionally unavailable in mes-libc. */ 4 static int tcc_find_self(char *buf, int size, const char *argv0) 5 { 6 const char *path, *p, *q; 7 int n, fd, valid; 8 9 if (strchr(argv0, '/')) { 10 snprintf(buf, size, "%s", argv0); 11 return 1; 12 } 13 path = getenv("PATH"); 14 if (!path) 15 return 0; 16 p = path; 17 for (;;) { 18 q = p; 19 while (*q && *q != ':') 20 ++q; 21 n = q - p; 22 valid = 0; 23 if (n == 0) { 24 if (strlen(argv0) + 3 <= size) { 25 strcpy(buf, "./"); 26 strcat(buf, argv0); 27 valid = 1; 28 } 29 } else if (n + strlen(argv0) + 2 <= size) { 30 memcpy(buf, p, n); 31 buf[n] = '/'; 32 strcpy(buf + n + 1, argv0); 33 valid = 1; 34 } 35 if (valid) { 36 fd = open(buf, 0); 37 if (fd >= 0) { 38 close(fd); 39 return 1; 40 } 41 } 42 if (!*q) 43 break; 44 p = q + 1; 45 } 46 return 0; 47 } 48 49 /* The installed layout is PREFIX/bin/tcc + PREFIX/lib/tcc. Keep the 50 unnormalized "bin/.." component: it is valid on every runtime in the 51 bootstrap and avoids requiring realpath(3) or readlink(2). */ 52 static void tcc_set_self_lib_path(TCCState *s, const char *argv0) 53 { 54 char executable[1024], lib_path[1024], *base; 55 56 if (!tcc_find_self(executable, sizeof(executable), argv0)) 57 return; 58 base = tcc_basename(executable); 59 if (base > executable) 60 base[-1] = 0; 61 else 62 strcpy(executable, "."); 63 snprintf(lib_path, sizeof(lib_path), "%s/../lib/tcc", executable); 64 tcc_set_lib_path(s, lib_path); 65 } 66 67 int main(int argc, char **argv) 68 { 69 TCCState *s; 70 int ret, opt, n = 0; 71 unsigned start_time = 0; 72 const char *first_file; 73 const char *argv0 = argv[0]; 74 75 redo: 76 s = tcc_new(); 77 tcc_set_self_lib_path(s, argv0); 78 opt = tcc_parse_args(s, &argc, &argv, 1);