xref: /plan9/sys/src/cmd/pcc.c (revision 4d44ba9b9ee4246ddbd96c7fcaf0918ab92ab35a)
1 #include <u.h>
2 #include <libc.h>
3 
4 
5 typedef struct Objtype {
6 	char	*name;
7 	char	*cc;
8 	char	*ld;
9 	char	*o;
10 	char	*oname;
11 } Objtype;
12 
13 Objtype objtype[] = {
14 	{"68020",	"2c", "2l", "2", "2.out"},
15 	{"arm",		"5c", "5l", "5", "5.out"},
16 	{"amd64",	"6c", "6l", "6", "6.out"},
17 	{"alpha",	"7c", "7l", "7", "7.out"},
18 	{"386",		"8c", "8l", "8", "8.out"},
19 	{"sparc",	"kc", "kl", "k", "k.out"},
20 	{"mips",	"vc", "vl", "v", "v.out"},
21 	{"power",	"qc", "ql", "q", "q.out"},
22 };
23 
24 enum {
25 	Nobjs = (sizeof objtype)/(sizeof objtype[0]),
26 	Maxlist = 500,
27 };
28 
29 typedef struct List {
30 	char	*strings[Maxlist];
31 	int	n;
32 } List;
33 
34 List	srcs, objs, cpp, cc, ld, ldargs;
35 int	cflag, vflag, Eflag, Pflag;
36 char	*allos = "2478kqv";
37 
38 void	append(List *, char *);
39 char	*changeext(char *, char *);
40 void	doexec(char *, List *);
41 void	dopipe(char *, List *, char *, List *);
42 void	fatal(char *);
43 Objtype	*findoty(void);
44 void	printlist(List *);
45 
46 void
47 main(int argc, char *argv[])
48 {
49 	Objtype *ot;
50 	char *s, *suf, *ccpath;
51 	char *oname;
52 	int i, cppn, ccn, oflag;
53 
54 	oflag = 0;
55 	ot = findoty();
56 	oname = ot->oname;
57 	append(&cpp, "cpp");
58 	append(&cpp, "-D__STDC__=1");	/* ANSI says so */
59 	append(&cpp, "-N");		/* turn off standard includes */
60 	append(&cc, ot->cc);
61 	append(&ld, ot->ld);
62 	while(argc > 0) {
63 		ARGBEGIN {
64 		case '+':
65 			append(&cpp, smprint("-%c", ARGC()));
66 			break;
67 		case 'c':
68 			cflag = 1;
69 			break;
70 		case 'l':
71 			append(&objs, smprint("/%s/lib/ape/lib%s.a", ot->name, ARGF()));
72 			break;
73 		case 'o':
74 			oflag = 1;
75 			oname = ARGF();
76 			if(!oname)
77 				fatal("no -o argument");
78 			break;
79 		case 'w':
80 		case 'B':
81 		case 'F':
82 		case 'N':
83 		case 'S':
84 		case 'T':
85 		case 'V':
86 			append(&cc, smprint("-%c", ARGC()));
87 			break;
88 		case 's':
89 			append(&cc, smprint("-s%s", ARGF()));
90 			break;
91 		case 'D':
92 		case 'I':
93 		case 'U':
94 			append(&cpp, smprint("-%c%s", ARGC(), ARGF()));
95 			break;
96 		case 'v':
97 			vflag = 1;
98 			append(&ldargs, "-v");
99 			break;
100 		case 'P':
101 			Pflag = 1;
102 			cflag = 1;
103 			break;
104 		case 'E':
105 			Eflag = 1;
106 			cflag = 1;
107 			break;
108 		case 'p':
109 			append(&ldargs, "-p");
110 			break;
111 		case 'a':
112 			/* hacky look inside ARGBEGIN insides, to see if we have -aa */
113 			if(*_args == 'a') {
114 				append(&cc, "-aa");
115 				_args++;
116 			} else
117 				append(&cc, "-a");
118 			cflag = 1;
119 			break;
120 		default:
121 			fprint(2, "pcc: flag -%c ignored\n", ARGC());
122 			break;
123 		} ARGEND
124 		if(argc > 0) {
125 			s = argv[0];
126 			suf = utfrrune(s, '.');
127 			if(suf) {
128 				suf++;
129 				if(strcmp(suf, "c") == 0) {
130 					append(&srcs, s);
131 					append(&objs, changeext(s, ot->o));
132 				} else if(strcmp(suf, ot->o) == 0 ||
133 					  strcmp(suf, "a") == 0 ||
134 					  (suf[0] == 'a' && strcmp(suf+1, ot->o) == 0)) {
135 					append(&objs, s);
136 				} else if(utfrune(allos, suf[0]) != 0) {
137 					fprint(2, "pcc: argument %s ignored: wrong architecture\n",
138 						s);
139 				}
140 			}
141 		}
142 	}
143 	if(objs.n == 0)
144 		fatal("no files to compile or load");
145 	ccpath = smprint("/bin/%s", ot->cc);
146 	append(&cpp, smprint("-I/%s/include/ape", ot->name));
147 	append(&cpp, "-I/sys/include/ape");
148 	cppn = cpp.n;
149 	ccn = cc.n;
150 	for(i = 0; i < srcs.n; i++) {
151 		append(&cpp, srcs.strings[i]);
152 		if(Pflag)
153 			append(&cpp, changeext(objs.strings[i], "i"));
154 		if(Eflag || Pflag)
155 			doexec("/bin/cpp", &cpp);
156 		else {
157 			append(&cc, "-o");
158 			if(oflag && cflag)
159 				append(&cc, oname);
160 			else
161 				append(&cc, changeext(srcs.strings[i], ot->o));
162 			dopipe("/bin/cpp", &cpp, ccpath, &cc);
163 		}
164 		cpp.n = cppn;
165 		cc.n = ccn;
166 	}
167 	if(!cflag) {
168 		append(&ld, "-o");
169 		append(&ld, oname);
170 		for(i = 0; i < ldargs.n; i++)
171 			append(&ld, ldargs.strings[i]);
172 		for(i = 0; i < objs.n; i++)
173 			append(&ld, objs.strings[i]);
174 		append(&ld, smprint("/%s/lib/ape/libap.a", ot->name));
175 		doexec(smprint("/bin/%s", ot->ld), &ld);
176 		if(objs.n == 1){
177 			/* prevent removal of a library */
178 			if(strstr(objs.strings[0], ".a") == 0)
179 				remove(objs.strings[0]);
180 		}
181 	}
182 
183 	exits(0);
184 }
185 
186 void
187 append(List *l, char *s)
188 {
189 	if(l->n >= Maxlist-1)
190 		fatal("too many arguments");
191 	l->strings[l->n++] = s;
192 	l->strings[l->n] = 0;
193 }
194 
195 void
196 doexec(char *c, List *a)
197 {
198 	Waitmsg *w;
199 
200 	if(vflag) {
201 		printlist(a);
202 		fprint(2, "\n");
203 	}
204 	switch(fork()) {
205 	case -1:
206 		fatal("fork failed");
207 	case 0:
208 		exec(c, a->strings);
209 		fatal("exec failed");
210 	}
211 	w = wait();
212 	if(w == nil)
213 		fatal("wait failed");
214 	if(w->msg[0])
215 		fatal(smprint("%s: %s", a->strings[0], w->msg));
216 	free(w);
217 }
218 
219 void
220 dopipe(char *c1, List *a1, char *c2, List *a2)
221 {
222 	Waitmsg *w;
223 	int pid1, got;
224 	int fd[2];
225 
226 	if(vflag) {
227 		printlist(a1);
228 		fprint(2, " | ");
229 		printlist(a2);
230 		fprint(2, "\n");
231 	}
232 	if(pipe(fd) < 0)
233 		fatal("pipe failed");
234 	switch((pid1 = fork())) {
235 	case -1:
236 		fatal("fork failed");
237 	case 0:
238 		dup(fd[0], 0);
239 		close(fd[0]);
240 		close(fd[1]);
241 		exec(c2, a2->strings);
242 		fatal("exec failed");
243 	}
244 	switch(fork()) {
245 	case -1:
246 		fatal("fork failed");
247 	case 0:
248 		close(0);
249 		dup(fd[1], 1);
250 		close(fd[0]);
251 		close(fd[1]);
252 		exec(c1, a1->strings);
253 		fatal("exec failed");
254 	}
255 	close(fd[0]);
256 	close(fd[1]);
257 	for(got = 0; got < 2; got++) {
258 		w = wait();
259 		if(w == nil)
260 			fatal("wait failed");
261 		if(w->msg[0])
262 			fatal(smprint("%s: %s",
263 			   (w->pid == pid1) ? a1->strings[0] : a2->strings[0], w->msg));
264 		free(w);
265 	}
266 }
267 
268 Objtype *
269 findoty(void)
270 {
271 	char *o;
272 	Objtype *oty;
273 
274 	o = getenv("objtype");
275 	if(!o)
276 		fatal("no $objtype in environment");
277 	for(oty = objtype; oty < &objtype[Nobjs]; oty++)
278 		if(strcmp(o, oty->name) == 0)
279 			return oty;
280 	fatal("unknown $objtype");
281 	return 0;			/* shut compiler up */
282 }
283 
284 void
285 fatal(char *msg)
286 {
287 	fprint(2, "pcc: %s\n", msg);
288 	exits(msg);
289 }
290 
291 /* src ends in .something; return copy of basename with .ext added */
292 char *
293 changeext(char *src, char *ext)
294 {
295 	char *b, *e, *ans;
296 
297 	b = utfrrune(src, '/');
298 	if(b)
299 		b++;
300 	else
301 		b = src;
302 	e = utfrrune(src, '.');
303 	if(!e)
304 		return 0;
305 	*e = 0;
306 	ans = smprint("%s.%s", b, ext);
307 	*e = '.';
308 	return ans;
309 }
310 
311 void
312 printlist(List *l)
313 {
314 	int i;
315 
316 	for(i = 0; i < l->n; i++) {
317 		fprint(2, "%s", l->strings[i]);
318 		if(i < l->n - 1)
319 			fprint(2, " ");
320 	}
321 }
322