xref: /plan9-contrib/sys/src/boot/vt5/parse (revision 98a68993d685eb89080b5d73dba0a8f0a226848c)
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("dbgflg" in section){
55		for(i = 1; i < section["dbgflg"]; i++){
56			n = split(line["dbgflg", i], a);
57			if(n < 2 || n > 4 || a[2] !~ /'[a-zA-Z]'/)
58				continue;
59			if(n > 2 && a[3] !~ /'[a-zA-Z]'/)
60				continue;
61			if(n == 4 && (a[4] < 1 || a[4] >= 128))
62				continue;
63			dbgc[a[1]] = a[2];
64			if(n == 4)
65				dbgflg[a[3]] = a[4];
66			else if(n == 3)
67				dbgflg[a[3]] = 1;
68		}
69	}
70	if((!oargc || ("-mkrules" in oargv)) && ("dir" in section)){
71		o = o mkrules(".", exists, a, c, "-I.");
72		for(i = 1; i < section["dir"]; i++){
73			n = split(line["dir", i], a);
74			dir = "../" a[1];
75			if(n == 1)
76				a[2] = "-I.";
77			s = a[2];
78			o = o mkrules(dir, exists, a, c, s);
79			l = listolate(a, "|");
80			if(l != ""){
81				o = o "^(" l ")\\.$O:R:	" dir "/\\1.s\n";
82				o = o "\t$AS $AFLAGS " s " " dir "/$stem1.s\n";
83			}
84			l = listolate(c, "|");
85			if(l != ""){
86				o = o "^(" l ")\\.$O:R:	" dir "/\\1.c\n";
87				o = o "\t$CC $CFLAGS " s " " dir "/$stem1.c\n";
88			}
89		}
90	}
91	if((!oargc || ("-mkrootrules" in oargv)) && ("rootdir" in section)){
92		mkrootrules(name, cname, src);
93		s = ARGV[argc] ".root.s:D:";
94		for(i = 1; i < section["rootdir"]; i++)
95			s = s " " src[i];
96		s = s "\n\tmkrootall\\\n";
97		for(i = 1; i < section["rootdir"]; i++)
98			s = s "\t\t" name[i] " " cname[i] " " src[i] "\\\n";
99		s = s "\t>$target\n";
100		if(section["rootdir"] > 1)
101			o = o s;
102	}
103	if((!oargc || ("-mkrrrules" in oargv)) && ("rr" in section)){
104		n = split(line["rr", 0], a);
105		if(n == 1)
106			a[2] = ARGV[argc] ".proto";
107		s = "$CONF.rr:\tmkrr $CONF " a[2] "\n";
108		s = s "\tmkrr $CONF " a[2] "\n";
109		for(i = 1; i < section["rr"]; i++)
110			s = s "$CONF.rr:\t" line["rr", i] "\n";
111		o = o s;
112	}
113	if("-mkdevc" in oargv)
114		o = o mkdevc();
115	if("-mkerrstr" in oargv)
116		o = o mkerrstr();
117	if("-mksystab" in oargv)
118		o = o mksystab();
119	if("-mkbootconf" in oargv)
120		o = o mkbootconf();
121
122	#
123	# to do:
124	#	bootmkfile
125	#	mkrootall (can it be done at all?)
126	#
127	printf o;
128
129	exit 0;
130}
131
132function mkbootconf(				a, n, s, t, u, c, d, p, r){
133	s = "#include <u.h>\n";
134	s = s "#include <libc.h>\n\n";
135	s = s "#include \"../boot/boot.h\"\n\n";
136	s = s "Method method[] = {\n";
137
138	c = "0";
139	d = "#S/sdC0/";
140	p = "boot";
141	r = "/root";
142
143	for(i = 0; i < section["boot"]; i++){		# NOTE: start at 0
144		n = split(line["boot", i], a);
145		if(a[1] == "boot"){
146			if(a[2] == "cpu"){
147				c = "1";
148				if(n == 4 && a[3] == "boot")
149					d = a[4];
150			}
151			else if(a[2] == "rootdir" && n == 3)
152				r = a[3];
153			else if(a[2] ~ /^(bboot|dosboot|romboot)$/){
154				c = "1";
155				p = a[2];
156			}
157			else if(a[2] == "boot" && n == 3)
158				d = a[3];
159			continue;
160		}
161		s = s "\t{ \"" a[1] "\", config" a[1] ", connect" a[1] ", ";
162		t = "nil";
163		if(n > 1){
164			u = line["boot", i];
165			if(sub(/^[_A-Za-z][_A-Za-z0-9]*[ \t]*/, "", u)){
166				if(match(u, /^".*"$/))
167					u = substr(u, RSTART+1, RLENGTH-2);
168				t = "\"" u "\"";
169			}
170		}
171		s = s t ", },\n";
172	}
173	s = s "\t{ nil },\n};\n\n";
174	s = s "int cpuflag = " c ";\n";
175	s = s "char* rootdir = \"" r "\";\n";
176	s = s "char* bootdisk = \"" d "\";\n";
177	s = s "extern void " p "(int, char**);\n\n";
178	s = s "void\nmain(int argc, char **argv)\n";
179	s = s "{\n\t" p "(argc, argv);\n}\n"
180
181	t = "int (*cfs)(int) = 0;\n";
182	for(i = 1; i < section["rootdir"]; i++){
183		if($1 !~ /\/bin\/cfs$/)
184			continue;
185		t = "int (*cfs)(int) = cache;\n";
186		break;
187	}
188	s = s t;
189
190	return s;
191}
192
193function mksystab(					a, i, f, n, s, t){
194	s = "#include \"/sys/src/libc/9syscall/sys.h\"\n\n";
195	s = s "typedef void Syscall(Ar0*, va_list);\n\n";
196
197	t = "";
198	while(getline < "/sys/src/libc/9syscall/sys.h"){
199		if($1 != "#define" || NF != 3)
200			continue;
201
202		f = "sys" tolower($2);
203		if($2 == "SYSR1")
204			f = "sysr1";
205		if($2 == "RENDEZVOUS")
206			n = "Rendez";
207		else if($2 == "BRK_")
208			n = "Brk";
209		else
210			n = substr($2, 1, 1) tolower(substr($2, 2));
211
212		s = s "Syscall " f ";\n";
213		t = t "\t[" $2 "]\t";
214		if(length($2) < 6)
215			t = t "\t";
216		t = t "{ \"" n "\", " f ", ";
217		#
218		# if($1 ~ "(FVERSION|FSTAT|STAT)")
219		#	t = t "{ .u = 0 } },\n";
220		# else
221		#
222		if($1 ~ "(BIND|MOUNT|FWSTAT|WSTAT)")
223			t = t "{ .l = 0 } },\n";
224		else if($1 ~ "(EXEC|RENDEZVOUS|SEGBRK|SEGATTACH)")
225			t = t "{ .v = (void*)-1 } },\n";
226		else
227			t = t "{ .i = -1 } },\n";
228	}
229	if("syscall" in section){
230		for(i = 1; i < section["syscall"]; i++){
231			if(split(line["syscall", i], a) != 8)
232				continue;
233			if(line["syscall", i] !~ /#define.*{ \.[ilpuv] = .* }$/)
234				continue;
235
236			f = "sys" tolower(a[2]);
237			n = substr(a[2], 1, 1) tolower(substr(a[2], 2));
238
239			s = s "\nSyscall " f ";\n";
240			t = t a[1] " " a[2] "\t" a[3] "\n\t[" a[2] "]\t";
241			if(length(a[2]) < 6)
242				t = t "\t";
243			split(line["syscall", i], a, "{");
244			t = t "{ \"" n "\", " f ", {" a[2] " },\n";
245		}
246	}
247	s = s "struct {\n\tchar*\tn;\n\tSyscall*f;\n\tAr0\tr;\n}";
248	s = s " systab[] = {\n" t "};\n\nint nsyscall = nelem(systab);\n";
249
250	return s;
251}
252
253function mkerrstr(					a, s){
254	FS="[ \t;]+";
255	while(getline < "error.h"){
256		split($0, a, /\/\* | \*\//);
257		s = s $2 " " $3 " = \"" a[2] "\";\n";
258	}
259	FS=" ";
260
261	return s;
262}
263
264function mkdevc(		a, d, i, m, n, s, t, u, name, cname){
265	s = "#include \"u.h\"\n";
266	s = s "#include \"lib.h\"\n";
267	s = s "#include \"mem.h\"\n";
268	s = s "#include \"dat.h\"\n";
269	s = s "#include \"fns.h\"\n";
270	s = s "#include \"error.h\"\n\n";
271	s = s "#include \"io.h\"\n\n";
272
273	t = "";
274	for(i = 1; i < section["dev"]; i++){
275		split(line["dev", i], a);
276		s = s "extern Dev " a[1] "devtab;\n";
277		t = t "\t&" a[1] "devtab,\n";
278		d[a[1]]++;
279	}
280	s = s "Dev* devtab[] = {\n" t "\tnil,\n};\n\n";
281
282	mkrootrules(name, cname, m);
283	t = "";
284	for(i = 1; i < section["rootdir"]; i++){
285		s = s "extern uchar " cname[i] "code[];\n";
286		s = s "extern usize " cname[i] "len;\n";
287		t = t "\taddbootfile(\"" name[i] "\", " cname[i] "code, " cname[i] "len);\n";
288	}
289	for(i = 1; i < section["link"]; i++){
290		split(line["link", i], a);
291		s = s "extern void " a[1] "link(void);\n";
292		t = t "\t" a[1] "link();\n";
293	}
294	s = s "void\nlinks(void)\n{\n" t "}\n\n";
295
296	if("ip" in d && "ip" in section){
297		t = "";
298		s = s "#include \"../ip/ip.h\"\n";
299		for(i = 1; i < section["ip"]; i++){
300			split(line["ip", i], a);
301			s = s "extern void " a[1] "init(Fs*);\n";
302			t = t "\t" a[1] "init,\n";
303		}
304		s = s "void (*ipprotoinit[])(Fs*) = {\n" t "\tnil,\n};\n\n";
305	}
306
307	if("sd" in d && "sd" in section){
308		t = "";
309		s = s "#include \"sd.h\"\n";
310		for(i = 1; i < section["sd"]; i++){
311			split(line["sd", i], a);
312			s = s "extern SDifc " a[1] "ifc;\n";
313			t = t  "\t&" a[1] "ifc,\n";
314		}
315		s = s "SDifc* sdifc[] = {\n" t "\tnil,\n};\n\n";
316	}
317
318	if("uart" in d && "uart" in section){
319		t = "";
320		for(i = 1; i < section["uart"]; i++){
321			split(line["uart", i], a);
322			a[1] = substr(a[1], 5, length(a[1])-4) "physuart";
323			s = s "extern PhysUart " a[1] ";\n";
324			t = t  "\t&" a[1] ",\n";
325		}
326		s = s "PhysUart* physuart[] = {\n" t "\tnil,\n};\n\n";
327	}
328
329	t = "";
330	n = 0;
331	if("physseg" in section){
332		for(i = 1; i < section["physseg"]; i++){
333			u = line["physseg", i];
334			if(u ~ /^\.[_A-Za-z][_A-Za-z0-9]*/)
335				t = t "\t";
336			t = t "\t" u "\n";
337			if(sub(/.*\.pgalloc.*=[^_A-Za-z]*/, "", u)){
338				if(match(u, /^[_A-Za-z][_A-Za-z0-9]*/)){
339					u = substr(u, RSTART, RLENGTH);
340					s = s "extern Page *(*" u ")(Segment*, uintptr);\n";
341				}
342			}
343			else if(sub(/.*\.pgfree.*=[^_A-Za-z]*/, "", u)){
344				if(match(u, /^[_A-Za-z][_A-Za-z0-9]*/)){
345					u = substr(u, RSTART, RLENGTH);
346					s = s "extern void (*" u ")(Page*);\n";
347				}
348			}
349			if(match(u, /}/))
350				n++;
351		}
352	}
353	s = s "Physseg physseg[" n+8 "] = {\n";
354	s = s "\t{\t.attr\t= SG_SHARED,\n";
355	s = s "\t\t.name\t= \"shared\",\n";
356	s = s "\t\t.size\t= SEGMAXSIZE,\n\t},\n";
357	s = s "\t{\t.attr\t= SG_BSS,\n";
358	s = s "\t\t.name\t= \"memory\",\n";
359	s = s "\t\t.size\t= SEGMAXSIZE,\n\t},\n";
360	s = s t "};\nint nphysseg = " n+8 ";\n\n";
361
362	s = s "char dbgflg[256]";
363	t = "";
364	for(u in dbgflg)
365		t = t "\t[" u "]\t" dbgflg[u] ",\n";
366	if(t != "")
367		s = s " = {\n" t "}";
368	s = s ";\n\n";
369
370	for(i in m)
371		delete m[i];
372
373	for(i = 1; i < section["misc"]; i++){
374		split(line["misc", i], a);
375		m[a[1]] = line["misc", i];
376	}
377	if("cache" in m){
378		s = s "extern void cinit(void);\n";
379		s = s "extern void copen(Chan*);\n";
380		s = s "extern int cread(Chan*, uchar*, int, vlong);\n";
381		s = s "extern void cupdate(Chan*, uchar*, int, vlong);\n";
382		s = s "extern void cwrite(Chan*, uchar*, int, vlong);\n\n";
383		s = s "void (*mfcinit)(void) = cinit;\n";
384		s = s "void (*mfcopen)(Chan*) = copen;\n";
385		s = s "int (*mfcread)(Chan*, uchar*, int, vlong) = cread;\n";
386		s = s "void (*mfcupdate)(Chan*, uchar*, int, vlong) = cupdate;\n";
387		s = s "void (*mfcwrite)(Chan*, uchar*, int, vlong) = cwrite;\n\n";
388	}
389	else{
390		s = s "void (*mfcinit)(void) = nil;\n";
391		s = s "void (*mfcopen)(Chan*) = nil;\n";
392		s = s "int (*mfcread)(Chan*, uchar*, int, vlong) = nil;\n";
393		s = s "void (*mfcupdate)(Chan*, uchar*, int, vlong) = nil;\n";
394		s = s "void (*mfcwrite)(Chan*, uchar*, int, vlong) = nil;\n\n";
395	}
396	if(!("rdb" in misc)){
397		s = s "void\n";
398		s = s "rdb(void)\n";
399		s = s "{\n";
400		s = s "\tsplhi();\n";
401		s = s "\tiprint(\"rdb...not installed\\n\");\n";
402		s = s "\tfor(;;);\n";
403		s = s "}\n\n";
404	}
405
406	if("conf" in section){
407		for(i = 1; i < section["conf"]; i++)
408			s = s line["conf", i] "\n";
409		s = s "\n";
410	}
411	t = ".";
412	while("pwd" | getline > 0){
413		if($0 ~ /^\//)
414			t = $0;
415	}
416	s = s "char* conffile = \"" t "/" ARGV[argc] "\";\n";
417	s = s "ulong kerndate = KERNDATE;\n";
418
419	return s;
420}
421
422function mkrootrules(name, cname, src,			a, i, n){
423	for(i = 1; i < section["rootdir"]; i++){
424		n = split(line["rootdir", i], a);
425		if(n >= 2)
426			name[i] = a[2];
427		else
428			name[i] = a[1];
429		sub(/.*\//, "", name[i]);
430		cname[i] = a[1];
431		gsub(/[^a-zA-Z0-9_]/, "_", cname[i]);
432		src[i] = a[1];
433	}
434}
435
436function mkrules(dir, exists, ameta, cmeta, flags,		f, i, s, t){
437	for(i in ameta)
438		delete ameta[i];
439	for(i in cmeta)
440		delete cmeta[i];
441
442	s = "";
443	while("cd " dir "; /bin/ls *.[cs]" | getline > 0){
444		if($0 !~ /^[A-Za-z0-9]*\.[cs]$/)
445			continue;
446		f = $0;
447		if(!sub(/\.[cs]$/, ""))
448			continue;
449		if($0 in exists)
450			continue;
451		exists[$0] = dir;
452		if(f ~ /\.c$/){
453			if(!($0 in dbgc)){
454				cmeta[$0]++;
455				continue;
456			}
457			t = "$CC $CFLAGS " flags;
458		}
459		else{
460			if(!($0 in dbgc)){
461				ameta[$0]++;
462				continue;
463			}
464			t = "$AS $AFLAGS " flags;
465		}
466		s = s $0 ".$O:\t" dir "/" f "\n";
467		s = s "\t" t " -D'_DBGC_='" dbgc[$0] "'' " dir "/" f "\n";
468	}
469	return s;
470}
471
472function mkport(					array){
473	arrayify(array, "port", "", ".$O", 1);
474
475	return listolate(array, " ");
476}
477
478function mklib(						array){
479	arrayify(array, "lib", "/$objtype/lib/", ".a", 1);
480
481	return listolate(array," ");
482}
483
484function mkmach(					a, i, s){
485	s = "";
486	for(i = 1; i < section[objtype]; i++){
487		if(!split(line[objtype, i], a))
488			continue;
489		if(s == "")
490			s = a[1] ".$O";
491		else
492			s = s " " a[1] ".$O";
493	}
494
495	return s;
496}
497
498function mkdevlist(					a, array, i, j, n, s){
499	for(s in section){
500		if(line[s, 0] !~ /[ \t]\+dev[^_A-Za-z0-9]*/)
501			continue;
502		if(s == "dev")
503			arrayify(array, s, "dev", ".$O", 1);
504		else if(s == objtype)
505			arrayify(array, s, "", ".$O", 0);
506		else
507			arrayify(array, s, "", ".$O", 1);
508	}
509
510	return listolate(array, " ");
511}
512
513function listolate(array, sep,				a, s){
514	s = "";
515	for(a in array){
516		if(s == "")
517			s = a;
518		else
519			s = a sep s;
520	}
521
522	return s;
523}
524
525function arrayify(array, tag, prefix, suffix, one,	a, i, j, n){
526	for(i = 1; i < section[tag]; i++){
527		n = split(line[tag, i], a);
528		if(one)
529			array[prefix a[1] suffix]++;
530		for(j = 2; j <= n; j++){
531			if(a[$j] ~ /[+=-].*/)
532				continue;
533			array[a[j] suffix]++;
534		}
535	}
536}
537