neatrun: compiling and linking with the same command
[neatcc_make.git] / neatrun / neatcc.c
blob5b543a39114a32c43194fd5b9232d9307bb78df9
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <string.h>
4 #include <sys/wait.h>
6 #define MAXARGS 512
7 #define LDOPTS "lLsgmpe" /* neatld options */
8 #define CCOPTS "cIEDW" /* neatcc options */
9 #define AROPTS "IDOlLome" /* options with an argument */
11 static void die(char *msg)
13 write(2, msg, strlen(msg));
14 exit(1);
17 int main(int argc, char *argv[], char *envp[])
19 char *ccargs[MAXARGS]; /* neatcc options */
20 char *ldargs[MAXARGS]; /* neatld options */
21 int opt[MAXARGS]; /* opt[i] is one if argv[i] is an option */
22 int optarg[MAXARGS]; /* argv[i + 1] is an argument of argv[i] */
23 int ccargc = 0; /* number of neatcc options */
24 int ldargc = 0; /* number of neatld options */
25 int nold = 0; /* compile only */
26 int i;
27 if (argc < 2)
28 die("neatcc: ncc/nld wrapper\n");
29 /* looking for options that prevent linking + initialize opt[] and optarg[] */
30 for (i = 1; i < argc; i++) {
31 opt[i] = argv[i][0] == '-' ? argv[i][1] : 0;
32 optarg[i] = opt[i] > 0 && strchr(AROPTS, opt[i]) && !argv[i][2];
33 nold = nold || opt[i] == 'c' || opt[i] == 'E';
35 /* initialize compiler options */
36 ccargs[ccargc++] = NCC;
37 ccargs[ccargc++] = "-Dfloat=long";
38 ccargs[ccargc++] = "-Ddouble=long";
39 ccargs[ccargc++] = "-D__extension__=";
40 ccargs[ccargc++] = "-I" NLC;
41 for (i = 1; i < argc; i += 1 + optarg[i]) {
42 if (opt[i] && strchr(CCOPTS, opt[i]) || (nold && opt[i] == 'o')) {
43 ccargs[ccargc++] = argv[i];
44 if (optarg[i])
45 ccargs[ccargc++] = argv[i + 1];
48 /* invoke neatcc for every .c file */
49 for (i = 1; i < argc; i += 1 + optarg[i]) {
50 char *arg = argv[i];
51 char *end = strchr(arg, '\0');
52 if (!opt[i] && arg + 2 < end && end[-2] == '.' && end[-1] == 'c') {
53 int st;
54 ccargs[ccargc] = arg;
55 ccargs[ccargc + 1] = NULL;
56 if (fork() == 0) {
57 execve(ccargs[0], ccargs, envp);
58 die("neatcc: could not find ncc\n");
59 return 1;
61 if (wait(&st) < 0 || WEXITSTATUS(st))
62 return 1;
63 end[-1] = 'o'; /* for linker */
66 /* invoke neatld */
67 if (!nold) {
68 ldargs[ldargc++] = NLD;
69 for (i = 1; i < argc; i += 1 + optarg[i]) {
70 if (!opt[i] || !strchr(CCOPTS, opt[i])) {
71 ldargs[ldargc++] = argv[i];
72 if (optarg[i])
73 ldargs[ldargc++] = argv[i + 1];
76 ldargs[ldargc++] = NLC "/start.o";
77 ldargs[ldargc++] = NLC "/libc.a";
78 ldargs[ldargc] = NULL;
79 execve(ldargs[0], ldargs, envp);
80 die("neatcc: could not find nld\n");
82 return 0;