xref: /plan9-contrib/sys/src/9k/mk/parse (revision 45e6af3b6d7025ef7184352bb3f6852edd8de07e)
1BEGIN{
2	oargc = 0;
3	for(argc = 1; argc < ARGC; argc++){
4		if(ARGV[argc] !~ /^-.+/ || ARGV[argc] ~ /--/)
5			break;
6		if(ARGV[argc] != "-D")
7			oargv[ARGV[argc]] = oargc++;
8		else
9			DEBUG = 1;
10		ARGV[argc] = "";
11	}
12
13	objtype = ENVIRON["objtype"];
14
15	while(getline > 0){
16		if(/^[ \t]*$/ || /^#/)
17			continue;
18
19		if(/^[^ \t]/){
20			#section[$1] = 0;
21			tag = $1;
22		}
23		if(!tag)
24			continue;
25		sub(/^[ \t]*/, "");
26		line[tag, section[tag]++] = $0;
27	}
28
29	o = "";
30	if(!oargc || ("-mkdevlist" in oargv)){
31		s = mkdevlist();
32		if(!("-mkdevlist" in oargv) || (oargc > 1))
33			s = "DEVS=" s;
34		o = o s "\n";
35	}
36	if((!oargc || ("-mkmach" in oargv)) && (objtype in section)){
37		s = mkmach();
38		if(!("-mkmach" in oargv) || (oargc > 1))
39			s = "MACH=" s;
40		o = o s "\n";
41	}
42	if((!oargc || ("-mklib" in oargv)) && ("lib" in section)){
43		s = mklib();
44		if(!("-mklib" in oargv) || (oargc > 1))
45			s = "LIB=" s;
46		o = o s "\n";
47	}
48	if((!oargc || ("-mkport" in oargv)) && ("port" in section)){
49		s = mkport();
50		if(!("-mkport" in oargv) || (oargc > 1))
51			s = "PORT=" s;
52		o = o s "\n";
53	}
54	if((!oargc || ("-mklinux" in oargv)) && ("linux" in section)){
55		s = mklinux();
56		if(!("-mklinux" in oargv) || (oargc > 1))
57			s = "LINUX=" s;
58		o = o s "\n";
59	}
60	if("dbgflg" in section){
61		for(i = 1; i < section["dbgflg"]; i++){
62			n = split(line["dbgflg", i], a);
63			if(n < 2 || n > 4 || a[2] !~ /'[a-zA-Z]'/)
64				continue;
65			if(n > 2 && a[3] !~ /'[a-zA-Z]'/)
66				continue;
67			if(n == 4 && (a[4] < 1 || a[4] >= 128))
68				continue;
69			dbgc[a[1]] = a[2];
70			if(n == 4)
71				dbgflg[a[3]] = a[4];
72			else if(n == 3)
73				dbgflg[a[3]] = 1;
74		}
75	}
76	if((!oargc || ("-mkrules" in oargv)) && ("dir" in section)){
77		o = o mkrules(".", exists, a, c, "-I.");
78		for(i = 1; i < section["dir"]; i++){
79			n = split(line["dir", i], a);
80			dir = "../" a[1];
81			if(n == 1)
82				a[2] = "-I.";
83			s = a[2];
84			o = o mkrules(dir, exists, a, c, s);
85			l = listolate(a, "|");
86			if(l != ""){
87				o = o "^(" l ")\\.$O:R:	" dir "/\\1.s\n";
88				o = o "\t$AS $AFLAGS " s " " dir "/$stem1.s\n";
89			}
90			l = listolate(c, "|");
91			if(l != ""){
92				o = o "^(" l ")\\.$O:R:	" dir "/\\1.c\n";
93				o = o "\t$CC $CFLAGS " s " " dir "/$stem1.c\n";
94			}
95		}
96	}
97	if((!oargc || ("-mkrootrules" in oargv)) && ("rootdir" in section)){
98		mkrootrules(name, cname, src);
99		s = ARGV[argc] ".root.s:D:";
100		for(i = 1; i < section["rootdir"]; i++)
101			s = s " " src[i];
102		s = s "\n\t../mk/mkrootall\\\n";
103		for(i = 1; i < section["rootdir"]; i++)
104			s = s "\t\t" name[i] " " cname[i] " " src[i] "\\\n";
105		s = s "\t>$target\n";
106		if(section["rootdir"] > 1)
107			o = o s;
108	}
109	if((!oargc || ("-mkrrrules" in oargv)) && ("rr" in section)){
110		n = split(line["rr", 0], a);
111		if(n == 1)
112			a[2] = ARGV[argc] ".proto";
113		s = "$CONF.rr:\t../mk/mkrr $CONF " a[2] "\n";
114		s = s "\t../mk/mkrr $CONF " a[2] "\n";
115		for(i = 1; i < section["rr"]; i++)
116			s = s "$CONF.rr:\t" line["rr", i] "\n";
117		o = o s;
118	}
119	if("-mkdevc" in oargv)
120		o = o mkdevc();
121	if("-mkerrstr" in oargv)
122		o = o mkerrstr();
123	if("-mksystab" in oargv)
124		o = o mksystab();
125	if("-mkbootconf" in oargv)
126		o = o mkbootconf();
127
128	#
129	# to do:
130	#	bootmkfile
131	#	mkrootall (can it be done at all?)
132	#
133	printf o;
134
135	exit 0;
136}
137
138function mkbootconf(				a, n, s, t, u, c, d, p, r){
139	s = "#include <u.h>\n";
140	s = s "#include <libc.h>\n\n";
141	s = s "#include \"../boot/boot.h\"\n\n";
142	s = s "Method method[] = {\n";
143
144	c = "0";
145	d = "#S/sdC0/";
146	p = "boot";
147	r = "/root";
148
149	for(i = 0; i < section["boot"]; i++){		# NOTE: start at 0
150		n = split(line["boot", i], a);
151		if(a[1] == "boot"){
152			if(a[2] == "cpu"){
153				c = "1";
154				if(n == 4 && a[3] == "boot")
155					d = a[4];
156			}
157			else if(a[2] == "rootdir" && n == 3)
158				r = a[3];
159			else if(a[2] ~ /^(bboot|dosboot|romboot)$/){
160				c = "1";
161				p = a[2];
162			}
163			else if(a[2] == "boot" && n == 3)
164				d = a[3];
165			continue;
166		}
167		s = s "\t{ \"" a[1] "\", config" a[1] ", connect" a[1] ", ";
168		t = "nil";
169		if(n > 1){
170			u = line["boot", i];
171			if(sub(/^[_A-Za-z][_A-Za-z0-9]*[ \t]*/, "", u)){
172				if(match(u, /^".*"$/))
173					u = substr(u, RSTART+1, RLENGTH-2);
174				t = "\"" u "\"";
175			}
176		}
177		s = s t ", },\n";
178	}
179	s = s "\t{ nil },\n};\n\n";
180	s = s "int cpuflag = " c ";\n";
181	s = s "char* rootdir = \"" r "\";\n";
182	s = s "char* bootdisk = \"" d "\";\n";
183	s = s "extern void " p "(int, char**);\n\n";
184	s = s "void\nmain(int argc, char **argv)\n";
185	s = s "{\n\t" p "(argc, argv);\n}\n"
186
187	t = "int (*cfs)(int) = 0;\n";
188	for(i = 1; i < section["rootdir"]; i++){
189		if($1 !~ /\/bin\/cfs$/)
190			continue;
191		t = "int (*cfs)(int) = cache;\n";
192		break;
193	}
194	s = s t;
195
196	return s;
197}
198
199function mksystab(					a, i, f, n, s, t){
200	s = "#include \"u.h\"\n";
201	s = s "#include \"../port/lib.h\"\n";
202	s = s "#include \"mem.h\"\n";
203	s = s "#include \"dat.h\"\n";
204	s = s "#include \"fns.h\"\n\n";
205	s = s "#include \"/sys/src/libc/9syscall/sys.h\"\n\n";
206
207	t = "";
208	while(getline < "/sys/src/libc/9syscall/sys.h"){
209		if($1 != "#define" || NF != 3)
210			continue;
211
212		f = "sys" tolower($2);
213		if($2 == "SYSR1")
214			f = "sysr1";
215		if($2 == "RENDEZVOUS")
216			n = "Rendez";
217		else if($2 == "BRK_")
218			n = "Brk";
219		else
220			n = substr($2, 1, 1) tolower(substr($2, 2));
221
222		s = s "extern void " f "(Ar0*, va_list);\n";
223		t = t "\t[" $2 "]\t";
224		if(length($2) < 6)
225			t = t "\t";
226		t = t "{ \"" n "\", " f ", ";
227		#
228		# The following should really be defined properly in the
229		# manual and code, but changing Plan 9 now is too awkward.
230		# It will matter more when sizeof(long) != sizeof(int).
231		#
232		# if($2 ~ "^(FVERSION|STAT|FSTAT|WSTAT|FWSTAT|AWAIT)$")
233		#	t = t "{ .u = 0 } },\n";
234		#
235		# if($2 ~ "^(BIND|_MOUNT|MOUNT)$")
236		#	t = t "{ .l = -1 } },\n";
237		#
238		# The "^(...)$" are to ensure only exact matches are made.
239		#
240		if($2 ~ "^(EXEC|SEGBRK|SEGATTACH|RENDEZVOUS)$")
241			t = t "{ .v = (void*)-1 } },\n";
242		else if($2 ~ "^(ALARM|_READ|_WRITE|PREAD|PWRITE)$")
243			t = t "{ .l = -1 } },\n";
244		else if($2 ~ "(NSEC)")
245			t = t "{ .vl = -1LL } },\n";
246		else
247			t = t "{ .i = -1 } },\n";
248	}
249	if("syscall" in section){
250		for(i = 1; i < section["syscall"]; i++){
251			if(split(line["syscall", i], a) != 8)
252				continue;
253			if(line["syscall", i] !~ /#define.*{ \.[ilpuv] = .* }$/)
254				continue;
255
256			f = "sys" tolower(a[2]);
257			n = substr(a[2], 1, 1) tolower(substr(a[2], 2));
258
259			s = s "\nSyscall " f ";\n";
260			t = t a[1] " " a[2] "\t" a[3] "\n\t[" a[2] "]\t";
261			if(length(a[2]) < 6)
262				t = t "\t";
263			split(line["syscall", i], a, "{");
264			t = t "{ \"" n "\", " f ", {" a[2] " },\n";
265		}
266	}
267	s = s "struct {\n\tchar*\tn;\n\tvoid (*f)(Ar0*, va_list);\n\tAr0\tr;\n}";
268	s = s " systab[] = {\n" t "};\n\nint nsyscall = nelem(systab);\n";
269
270	return s;
271}
272
273function mkerrstr(					a, s){
274	FS="[ \t;]+";
275	while(getline < "../port/error.h"){
276		split($0, a, /\/\* | \*\//);
277		s = s $2 " " $3 " = \"" a[2] "\";\n";
278	}
279	FS=" ";
280
281	return s;
282}
283
284function mkdevc(		a, d, i, m, n, s, t, u, name, cname){
285	s = "#include \"u.h\"\n";
286	s = s "#include \"../port/lib.h\"\n";
287	s = s "#include \"mem.h\"\n";
288	s = s "#include \"dat.h\"\n";
289	s = s "#include \"fns.h\"\n";
290	s = s "#include \"../port/error.h\"\n\n";
291	s = s "#include \"io.h\"\n\n";
292
293	t = "";
294	for(i = 1; i < section["dev"]; i++){
295		split(line["dev", i], a);
296		s = s "extern Dev " a[1] "devtab;\n";
297		t = t "\t&" a[1] "devtab,\n";
298		d[a[1]]++;
299	}
300	s = s "Dev* devtab[] = {\n" t "\tnil,\n};\n\n";
301
302	if(!("acpi" in d))
303		s = s "int\nacpiinit(void)\n{\n\treturn -1;\n}\n\n";
304
305	mkrootrules(name, cname, m);
306	t = "";
307	for(i = 1; i < section["rootdir"]; i++){
308		s = s "extern uchar " cname[i] "code[];\n";
309		s = s "extern usize " cname[i] "len;\n";
310		t = t "\taddbootfile(\"" name[i] "\", " cname[i] "code, " cname[i] "len);\n";
311	}
312	for(i = 1; i < section["link"]; i++){
313		split(line["link", i], a);
314		s = s "extern void " a[1] "link(void);\n";
315		t = t "\t" a[1] "link();\n";
316	}
317	s = s "void\nlinks(void)\n{\n" t "}\n\n";
318
319	if("ip" in d && "ip" in section){
320		t = "";
321		s = s "#include \"../ip/ip.h\"\n";
322		for(i = 1; i < section["ip"]; i++){
323			split(line["ip", i], a);
324			s = s "extern void " a[1] "init(Fs*);\n";
325			t = t "\t" a[1] "init,\n";
326		}
327		s = s "void (*ipprotoinit[])(Fs*) = {\n" t "\tnil,\n};\n\n";
328	}
329
330	if("sd" in d && "sd" in section){
331		t = "";
332		s = s "#include \"../port/sd.h\"\n";
333		for(i = 1; i < section["sd"]; i++){
334			split(line["sd", i], a);
335			s = s "extern SDifc " a[1] "ifc;\n";
336			t = t  "\t&" a[1] "ifc,\n";
337		}
338		s = s "SDifc* sdifc[] = {\n" t "\tnil,\n};\n\n";
339	}
340
341	if("uart" in d && "uart" in section){
342		t = "";
343		for(i = 1; i < section["uart"]; i++){
344			split(line["uart", i], a);
345			a[1] = substr(a[1], 5, length(a[1])-4) "physuart";
346			s = s "extern PhysUart " a[1] ";\n";
347			t = t  "\t&" a[1] ",\n";
348		}
349		s = s "PhysUart* physuart[] = {\n" t "\tnil,\n};\n\n";
350	}
351
352	if("vga" in d && "vga" in section){
353		s = s "#define	Image	IMAGE\n"
354		s = s "#include <draw.h>\n"
355		s = s "#include <memdraw.h>\n"
356		s = s "#include <cursor.h>\n"
357		s = s "#include \"screen.h\"\n"
358
359		t = "";
360		for(i = 1; i < section["vga"]; i++){
361			split(line["vga", i], a);
362			s = s "extern VGAdev " a[1]"dev;\n";
363			t = t  "\t&" a[1] "dev,\n";
364		}
365		s = s "VGAdev *vgadev[] = {\n" t "\tnil,\n};\n\n"
366
367		t = "	&swcursor, \n"
368		s = s "extern VGAcur swcursor;\n";
369		s = s "VGAcur *vgacur[] = {\n" t "\tnil,\n};\n\n"
370
371	}
372
373	t = "";
374	n = 0;
375	if("physseg" in section){
376		for(i = 1; i < section["physseg"]; i++){
377			u = line["physseg", i];
378			if(u ~ /^\.[_A-Za-z][_A-Za-z0-9]*/)
379				t = t "\t";
380			t = t "\t" u "\n";
381			if(sub(/.*\.pgalloc.*=[^_A-Za-z]*/, "", u)){
382				if(match(u, /^[_A-Za-z][_A-Za-z0-9]*/)){
383					u = substr(u, RSTART, RLENGTH);
384					s = s "extern Page *(*" u ")(Segment*, uintptr);\n";
385				}
386			}
387			else if(sub(/.*\.pgfree.*=[^_A-Za-z]*/, "", u)){
388				if(match(u, /^[_A-Za-z][_A-Za-z0-9]*/)){
389					u = substr(u, RSTART, RLENGTH);
390					s = s "extern void (*" u ")(Page*);\n";
391				}
392			}
393			if(match(u, /}/))
394				n++;
395		}
396	}
397	s = s "Physseg physseg[" n+8 "] = {\n";
398	s = s "\t{\t.attr\t= SG_SHARED,\n";
399	s = s "\t\t.name\t= \"shared\",\n";
400	s = s "\t\t.size\t= SEGMAXSIZE,\n\t},\n";
401	s = s "\t{\t.attr\t= SG_BSS,\n";
402	s = s "\t\t.name\t= \"memory\",\n";
403	s = s "\t\t.size\t= SEGMAXSIZE,\n\t},\n";
404	s = s t "};\nint nphysseg = " n+8 ";\n\n";
405
406	s = s "char dbgflg[256]";
407	t = "";
408	for(u in dbgflg)
409		t = t "\t[" u "]\t" dbgflg[u] ",\n";
410	if(t != "")
411		s = s " = {\n" t "}";
412	s = s ";\n\n";
413
414	for(i in m)
415		delete m[i];
416
417	for(i = 1; i < section["misc"]; i++){
418		split(line["misc", i], a);
419		m[a[1]] = line["misc", i];
420	}
421	if(!("rdb" in m)){
422		s = s "void\n";
423		s = s "rdb(void)\n";
424		s = s "{\n";
425		s = s "\tsplhi();\n";
426		s = s "\tiprint(\"rdb...not installed\\n\");\n";
427		s = s "\tfor(;;);\n";
428		s = s "}\n\n";
429	}
430	if(objtype == "power"){
431		for(i = 1; i < section[objtype]; i++){
432			split(line[objtype, i], a);
433			m[a[1]] = line[objtype, i];
434		}
435		if(!("cnksyscall" in m)){
436			s = s "void\n";
437			s = s "cnksyscall(Ureg*)\n";
438			s = s "{\n";
439			s = s "\tpanic(\"cnkemu...not installed\\n\");\n";
440			s = s "\tfor(;;);\n";
441			s = s "}\n\n";
442			s = s "void*\n";
443			s = s "cnksysexecregs(uintptr, ulong, ulong)\n";
444			s = s "{\n";
445			s = s "\tpanic(\"cnkemu...not installed\\n\");\n";
446			s = s "\tfor(;;);\n";
447			s = s "}\n\n";
448		}
449	}
450	if("conf" in section){
451		for(i = 1; i < section["conf"]; i++)
452			s = s line["conf", i] "\n";
453		s = s "\n";
454	}
455	t = ".";
456	while("pwd" | getline > 0){
457		if($0 ~ /^\//)
458			t = $0;
459	}
460	s = s "char* conffile = \"" t "/" ARGV[argc] "\";\n";
461	s = s "ulong kerndate = KERNDATE;\n";
462
463	return s;
464}
465
466function mkrootrules(name, cname, src,			a, i, n){
467	for(i = 1; i < section["rootdir"]; i++){
468		n = split(line["rootdir", i], a);
469		if(n >= 2)
470			name[i] = a[2];
471		else
472			name[i] = a[1];
473		sub(/.*\//, "", name[i]);
474		cname[i] = a[1];
475		gsub(/[^a-zA-Z0-9_]/, "_", cname[i]);
476		src[i] = a[1];
477	}
478}
479
480function mkrules(dir, exists, ameta, cmeta, flags,		f, i, s, t){
481	for(i in ameta)
482		delete ameta[i];
483	for(i in cmeta)
484		delete cmeta[i];
485
486	s = "";
487	while("cd " dir "; /bin/ls *.[cs]" | getline > 0){
488		if($0 !~ /^[A-Za-z0-9]*\.[cs]$/)
489			continue;
490		f = $0;
491		if(!sub(/\.[cs]$/, ""))
492			continue;
493		if($0 in exists)
494			continue;
495		exists[$0] = dir;
496		if(f ~ /\.c$/){
497			if(!($0 in dbgc)){
498				cmeta[cmeta["k"]++] = $0
499				continue;
500			}
501			t = "$CC $CFLAGS " flags;
502		}
503		else{
504			if(!($0 in dbgc)){
505				ameta[ameta["k"]++] = $0
506				continue;
507			}
508			t = "$AS $AFLAGS " flags;
509		}
510		s = s $0 ".$O:\t" dir "/" f "\n";
511		s = s "\t" t " -D'_DBGC_='" dbgc[$0] "'' " dir "/" f "\n";
512	}
513	return s;
514}
515
516function mklinux(					array){
517	arrayify(array, "linux", "", ".$O", 1);
518
519	return listolate(array, " ");
520}
521
522function mkport(					array){
523	arrayify(array, "port", "", ".$O", 1);
524
525	return listolate(array, " ");
526}
527
528function mklib(						array){
529	arrayify(array, "lib", "/$objtype/lib/", ".a", 1);
530
531	return listolate(array," ");
532}
533
534function mkmach(					a, i, s){
535	s = "";
536	for(i = 1; i < section[objtype]; i++){
537		if(!split(line[objtype, i], a))
538			continue;
539		if(s == "")
540			s = a[1] ".$O";
541		else
542			s = s " " a[1] ".$O";
543	}
544
545	return s;
546}
547
548function mkdevlist(					a, array, i, j, n, s){
549	for(s in section){
550		if(line[s, 0] !~ /[ \t]\+dev[^_A-Za-z0-9]*/)
551			continue;
552		if(s == "dev")
553			arrayify(array, s, "dev", ".$O", 1);
554		else if(s == objtype)
555			arrayify(array, s, "", ".$O", 0);
556		else
557			arrayify(array, s, "", ".$O", 1);
558	}
559
560	return listolate(array, " ");
561}
562
563function listolate(array, sep,				i, n, a, s){
564	n = array["k"]
565	if(n == 0)
566		return ""
567	s = array[0]
568	for(i = 1; i < n; i++)
569		s = s sep array[i]
570	return s;
571}
572
573function unique(array, n, s,					i){
574	for(i = 0; i < n; i++)
575		if(array[i] == s)
576			return 0
577	return 1
578}
579
580function arrayify(array, tag, prefix, suffix, one,	a, i, j, k, n){
581	k = 0;
582	if(array["k"] > k)
583		k = array["k"]
584	for(i = 1; i < section[tag]; i++){
585		n = split(line[tag, i], a);
586		if(one)
587			array[k++] = prefix a[1] suffix
588		for(j = 2; j <= n; j++){
589			if(a[$j] ~ /[+=-].*/)
590				continue;
591			if(unique(array, k, a[j] suffix))
592				array[k++] = a[j] suffix
593		}
594	}
595	array["k"] = k
596}
597