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