xref: /inferno-os/utils/ka/lex.c (revision 50b0dbb170df61467e42c7ea4deb0b5692d15f4c)
1 #define	EXTERN
2 #include "a.h"
3 #include "y.tab.h"
4 #include <ctype.h>
5 
6 void
7 main(int argc, char *argv[])
8 {
9 	char *p;
10 	int nout, nproc, status, i, c;
11 
12 	thechar = 'k';
13 	thestring = "sparc";
14 	memset(debug, 0, sizeof(debug));
15 	cinit();
16 	outfile = 0;
17 	include[ninclude++] = ".";
18 	ARGBEGIN {
19 	default:
20 		c = ARGC();
21 		if(c >= 0 || c < sizeof(debug))
22 			debug[c] = 1;
23 		break;
24 
25 	case 'o':
26 		outfile = ARGF();
27 		break;
28 
29 	case 'D':
30 		p = ARGF();
31 		if(p)
32 			Dlist[nDlist++] = p;
33 		break;
34 
35 	case 'I':
36 		p = ARGF();
37 		setinclude(p);
38 		break;
39 	} ARGEND
40 	if(*argv == 0) {
41 		print("usage: %ca [-options] file.s\n", thechar);
42 		errorexit();
43 	}
44 	if(argc > 1 && systemtype(Windows)){
45 		print("can't assemble multiple files on windows\n");
46 		errorexit();
47 	}
48 	if(argc > 1 && !systemtype(Windows)) {
49 		nproc = 1;
50 		if(p = getenv("NPROC"))
51 			nproc = atol(p);	/* */
52 		c = 0;
53 		nout = 0;
54 		for(;;) {
55 			while(nout < nproc && argc > 0) {
56 				i = myfork();
57 				if(i < 0) {
58 					i = mywait(&status);
59 					if(i < 0)
60 						errorexit();
61 					if(status)
62 						c++;
63 					nout--;
64 					continue;
65 				}
66 				if(i == 0) {
67 					print("%s:\n", *argv);
68 					if(assemble(*argv))
69 						errorexit();
70 					exits(0);
71 				}
72 				nout++;
73 				argc--;
74 				argv++;
75 			}
76 			i = mywait(&status);
77 			if(i < 0) {
78 				if(c)
79 					errorexit();
80 				exits(0);
81 			}
82 			if(status)
83 				c++;
84 			nout--;
85 		}
86 	}
87 	if(assemble(argv[0]))
88 		errorexit();
89 	exits(0);
90 }
91 
92 int
93 assemble(char *file)
94 {
95 	char ofile[100], incfile[20], *p;
96 	int i, of;
97 
98 	strcpy(ofile, file);
99 	p = utfrrune(ofile, pathchar());
100 	if(p) {
101 		include[0] = ofile;
102 		*p++ = 0;
103 	} else
104 		p = ofile;
105 	if(outfile == 0) {
106 		outfile = p;
107 		if(outfile){
108 			p = utfrrune(outfile, '.');
109 			if(p)
110 				if(p[1] == 's' && p[2] == 0)
111 					p[0] = 0;
112 			p = utfrune(outfile, 0);
113 			p[0] = '.';
114 			p[1] = thechar;
115 			p[2] = 0;
116 		} else
117 			outfile = "/dev/null";
118 	}
119 	p = getenv("INCLUDE");
120 	if(p) {
121 		setinclude(p);
122 	} else {
123 		if(systemtype(Plan9)) {
124 			sprint(incfile,"/%s/include", thestring);
125 			setinclude(strdup(incfile));
126 		}
127 	}
128 
129 	of = mycreat(outfile, 0664);
130 	if(of < 0) {
131 		yyerror("%ca: cannot create %s", thechar, outfile);
132 		errorexit();
133 	}
134 	Binit(&obuf, of, OWRITE);
135 
136 	pass = 1;
137 	pinit(file);
138 	for(i=0; i<nDlist; i++)
139 		dodefine(Dlist[i]);
140 	yyparse();
141 	if(nerrors) {
142 		cclean();
143 		return nerrors;
144 	}
145 
146 	pass = 2;
147 	outhist();
148 	pinit(file);
149 	for(i=0; i<nDlist; i++)
150 		dodefine(Dlist[i]);
151 	yyparse();
152 	cclean();
153 	return nerrors;
154 }
155 
156 struct
157 {
158 	char	*name;
159 	ushort	type;
160 	ushort	value;
161 } itab[] =
162 {
163 	"SP",		LSP,	D_AUTO,
164 	"SB",		LSB,	D_EXTERN,
165 	"FP",		LFP,	D_PARAM,
166 	"PC",		LPC,	D_BRANCH,
167 
168 	"FSR",		LFSR,	D_FSR,
169 	"CSR",		LFSR,	D_CSR,
170 
171 	"FQ",		LFPQ,	D_FPQ,
172 	"CQ",		LFPQ,	D_CPQ,
173 
174 	"Y",		LPSR,	D_Y,
175 	"PSR",		LPSR,	D_PSR,
176 	"WIM",		LPSR,	D_WIM,
177 	"TBR",		LPSR,	D_TBR,
178 
179 	"R",		LR,	0,
180 	"R0",		LREG,	0,
181 	"R1",		LREG,	1,
182 	"R2",		LREG,	2,
183 	"R3",		LREG,	3,
184 	"R4",		LREG,	4,
185 	"R5",		LREG,	5,
186 	"R6",		LREG,	6,
187 	"R7",		LREG,	7,
188 	"R8",		LREG,	8,
189 	"R9",		LREG,	9,
190 	"R10",		LREG,	10,
191 	"R11",		LREG,	11,
192 	"R12",		LREG,	12,
193 	"R13",		LREG,	13,
194 	"R14",		LREG,	14,
195 	"R15",		LREG,	15,
196 	"R16",		LREG,	16,
197 	"R17",		LREG,	17,
198 	"R18",		LREG,	18,
199 	"R19",		LREG,	19,
200 	"R20",		LREG,	20,
201 	"R21",		LREG,	21,
202 	"R22",		LREG,	22,
203 	"R23",		LREG,	23,
204 	"R24",		LREG,	24,
205 	"R25",		LREG,	25,
206 	"R26",		LREG,	26,
207 	"R27",		LREG,	27,
208 	"R28",		LREG,	28,
209 	"R29",		LREG,	29,
210 	"R30",		LREG,	30,
211 	"R31",		LREG,	31,
212 
213 	"C",		LC,	0,
214 	"C0",		LCREG,	0,
215 	"C1",		LCREG,	1,
216 	"C2",		LCREG,	2,
217 	"C3",		LCREG,	3,
218 	"C4",		LCREG,	4,
219 	"C5",		LCREG,	5,
220 	"C6",		LCREG,	6,
221 	"C7",		LCREG,	7,
222 	"C8",		LCREG,	8,
223 	"C9",		LCREG,	9,
224 	"C10",		LCREG,	10,
225 	"C11",		LCREG,	11,
226 	"C12",		LCREG,	12,
227 	"C13",		LCREG,	13,
228 	"C14",		LCREG,	14,
229 	"C15",		LCREG,	15,
230 	"C16",		LCREG,	16,
231 	"C17",		LCREG,	17,
232 	"C18",		LCREG,	18,
233 	"C19",		LCREG,	19,
234 	"C20",		LCREG,	20,
235 	"C21",		LCREG,	21,
236 	"C22",		LCREG,	22,
237 	"C23",		LCREG,	23,
238 	"C24",		LCREG,	24,
239 	"C25",		LCREG,	25,
240 	"C26",		LCREG,	26,
241 	"C27",		LCREG,	27,
242 	"C28",		LCREG,	28,
243 	"C29",		LCREG,	29,
244 	"C30",		LCREG,	30,
245 	"C31",		LCREG,	31,
246 
247 	"F",		LF,	0,
248 	"F0",		LFREG,	0,
249 	"F2",		LFREG,	2,
250 	"F4",		LFREG,	4,
251 	"F6",		LFREG,	6,
252 	"F8",		LFREG,	8,
253 	"F10",		LFREG,	10,
254 	"F12",		LFREG,	12,
255 	"F14",		LFREG,	14,
256 	"F16",		LFREG,	16,
257 	"F18",		LFREG,	18,
258 	"F20",		LFREG,	20,
259 	"F22",		LFREG,	22,
260 	"F24",		LFREG,	24,
261 	"F26",		LFREG,	26,
262 	"F28",		LFREG,	28,
263 	"F30",		LFREG,	30,
264 	"F1",		LFREG,	1,
265 	"F3",		LFREG,	3,
266 	"F5",		LFREG,	5,
267 	"F7",		LFREG,	7,
268 	"F9",		LFREG,	9,
269 	"F11",		LFREG,	11,
270 	"F13",		LFREG,	13,
271 	"F15",		LFREG,	15,
272 	"F17",		LFREG,	17,
273 	"F19",		LFREG,	19,
274 	"F21",		LFREG,	21,
275 	"F23",		LFREG,	23,
276 	"F25",		LFREG,	25,
277 	"F27",		LFREG,	27,
278 	"F29",		LFREG,	29,
279 	"F31",		LFREG,	31,
280 
281 	"ADD",		LADDW, AADD,
282 	"ADDCC",	LADDW, AADDCC,
283 	"ADDX",		LADDW, AADDX,
284 	"ADDXCC",	LADDW, AADDXCC,
285 	"AND",		LADDW, AAND,
286 	"ANDCC",	LADDW, AANDCC,
287 	"ANDN",		LADDW, AANDN,
288 	"ANDNCC",	LADDW, AANDNCC,
289 	"BA",		LBRA, ABA,
290 	"BCC",		LBRA, ABCC,
291 	"BCS",		LBRA, ABCS,
292 	"BE",		LBRA, ABE,
293 	"BG",		LBRA, ABG,
294 	"BGE",		LBRA, ABGE,
295 	"BGU",		LBRA, ABGU,
296 	"BL",		LBRA, ABL,
297 	"BLE",		LBRA, ABLE,
298 	"BLEU",		LBRA, ABLEU,
299 	"BN",		LBRA, ABN,
300 	"BNE",		LBRA, ABNE,
301 	"BNEG",		LBRA, ABNEG,
302 	"BPOS",		LBRA, ABPOS,
303 	"BVC",		LBRA, ABVC,
304 	"BVS",		LBRA, ABVS,
305 	"CB0",		LBRA, ACB0,
306 	"CB01",		LBRA, ACB01,
307 	"CB012",	LBRA, ACB012,
308 	"CB013",	LBRA, ACB013,
309 	"CB02",		LBRA, ACB02,
310 	"CB023",	LBRA, ACB023,
311 	"CB03",		LBRA, ACB03,
312 	"CB1",		LBRA, ACB1,
313 	"CB12",		LBRA, ACB12,
314 	"CB123",	LBRA, ACB123,
315 	"CB13",		LBRA, ACB13,
316 	"CB2",		LBRA, ACB2,
317 	"CB23",		LBRA, ACB23,
318 	"CB3",		LBRA, ACB3,
319 	"CBA",		LBRA, ACBA,
320 	"CBN",		LBRA, ACBN,
321 	"CMP",		LCMP, ACMP,
322 	"CPOP1",	LCPOP, ACPOP1,
323 	"CPOP2",	LCPOP, ACPOP2,
324 	"DATA",		LDATA, ADATA,
325 	"DIV",		LADDW, ADIV,
326 	"DIVL",		LADDW, ADIVL,
327 	"END",		LEND, AEND,
328 	"FABSD",	LFCONV, AFABSD,
329 	"FABSF",	LFCONV, AFABSF,
330 	"FABSX",	LFCONV, AFABSX,
331 	"FADDD",	LFADD, AFADDD,
332 	"FADDF",	LFADD, AFADDF,
333 	"FADDX",	LFADD, AFADDX,
334 	"FBA",		LBRA, AFBA,
335 	"FBE",		LBRA, AFBE,
336 	"FBG",		LBRA, AFBG,
337 	"FBGE",		LBRA, AFBGE,
338 	"FBL",		LBRA, AFBL,
339 	"FBLE",		LBRA, AFBLE,
340 	"FBLG",		LBRA, AFBLG,
341 	"FBN",		LBRA, AFBN,
342 	"FBNE",		LBRA, AFBNE,
343 	"FBO",		LBRA, AFBO,
344 	"FBU",		LBRA, AFBU,
345 	"FBUE",		LBRA, AFBUE,
346 	"FBUG",		LBRA, AFBUG,
347 	"FBUGE",	LBRA, AFBUGE,
348 	"FBUL",		LBRA, AFBUL,
349 	"FBULE",	LBRA, AFBULE,
350 	"FCMPD",	LFADD, AFCMPD,
351 	"FCMPED",	LFADD, AFCMPED,
352 	"FCMPEF",	LFADD, AFCMPEF,
353 	"FCMPEX",	LFADD, AFCMPEX,
354 	"FCMPF",	LFADD, AFCMPF,
355 	"FCMPX",	LFADD, AFCMPX,
356 	"FDIVD",	LFADD, AFDIVD,
357 	"FDIVF",	LFADD, AFDIVF,
358 	"FDIVX",	LFADD, AFDIVX,
359 	"FMOVD",	LFMOV, AFMOVD,
360 	"FMOVDF",	LFCONV, AFMOVDF,
361 	"FMOVDW",	LFCONV, AFMOVDW,
362 	"FMOVDX",	LFCONV, AFMOVDX,
363 	"FMOVF",	LFMOV, AFMOVF,
364 	"FMOVFD",	LFCONV, AFMOVFD,
365 	"FMOVFW",	LFCONV, AFMOVFW,
366 	"FMOVFX",	LFCONV, AFMOVFX,
367 	"FMOVWD",	LFCONV, AFMOVWD,
368 	"FMOVWF",	LFCONV, AFMOVWF,
369 	"FMOVWX",	LFCONV, AFMOVWX,
370 	"FMOVX",	LFCONV, AFMOVX,
371 	"FMOVXD",	LFCONV, AFMOVXD,
372 	"FMOVXF",	LFCONV, AFMOVXF,
373 	"FMOVXW",	LFCONV, AFMOVXW,
374 	"FMULD",	LFADD, AFMULD,
375 	"FMULF",	LFADD, AFMULF,
376 	"FMULX",	LFADD, AFMULX,
377 	"FNEGD",	LFCONV, AFNEGD,
378 	"FNEGF",	LFCONV, AFNEGF,
379 	"FNEGX",	LFCONV, AFNEGX,
380 	"FSQRTD",	LFCONV, AFSQRTD,
381 	"FSQRTF",	LFCONV, AFSQRTF,
382 	"FSQRTX",	LFCONV, AFSQRTX,
383 	"FSUBD",	LFADD, AFSUBD,
384 	"FSUBF",	LFADD, AFSUBF,
385 	"FSUBX",	LFADD, AFSUBX,
386 	"GLOBL",	LTEXT, AGLOBL,
387 	"IFLUSH",	LFLUSH, AIFLUSH,
388 	"JMPL",		LJMPL, AJMPL,
389 	"JMP",		LJMPL, AJMP,
390 	"MOD",		LADDW, AMOD,
391 	"MODL",		LADDW, AMODL,
392 	"MOVB",		LMOVB, AMOVB,
393 	"MOVBU",	LMOVB, AMOVBU,
394 	"MOVD",		LMOVD, AMOVD,
395 	"MOVH",		LMOVB, AMOVH,
396 	"MOVHU",	LMOVB, AMOVHU,
397 	"MOVW",		LMOVW, AMOVW,
398 	"MUL",		LADDW, AMUL,
399 	"MULSCC",	LADDW, AMULSCC,
400 	"NOP",		LNOP, ANOP,
401 	"OR",		LADDW, AOR,
402 	"ORCC",		LADDW, AORCC,
403 	"ORN",		LADDW, AORN,
404 	"ORNCC",	LADDW, AORNCC,
405 	"RESTORE",	LADDW, ARESTORE,
406 	"RETT",		LRETT, ARETT,
407 	"RETURN",	LRETRN, ARETURN,
408 	"SAVE",		LADDW, ASAVE,
409 	"SLL",		LADDW, ASLL,
410 	"SRA",		LADDW, ASRA,
411 	"SRL",		LADDW, ASRL,
412 	"SUB",		LADDW, ASUB,
413 	"SUBCC",	LADDW, ASUBCC,
414 	"SUBX",		LADDW, ASUBX,
415 	"SUBXCC",	LADDW, ASUBXCC,
416 	"SWAP",		LSWAP, ASWAP,
417 	"TA",		LTRAP, ATA,
418 	"TADDCC",	LADDW, ATADDCC,
419 	"TADDCCTV",	LADDW, ATADDCCTV,
420 	"TAS",		LSWAP, ATAS,
421 	"TCC",		LTRAP, ATCC,
422 	"TCS",		LTRAP, ATCS,
423 	"TE",		LTRAP, ATE,
424 	"TEXT",		LTEXT, ATEXT,
425 	"TG",		LTRAP, ATG,
426 	"TGE",		LTRAP, ATGE,
427 	"TGU",		LTRAP, ATGU,
428 	"TL",		LTRAP, ATL,
429 	"TLE",		LTRAP, ATLE,
430 	"TLEU",		LTRAP, ATLEU,
431 	"TN",		LTRAP, ATN,
432 	"TNE",		LTRAP, ATNE,
433 	"TNEG",		LTRAP, ATNEG,
434 	"TPOS",		LTRAP, ATPOS,
435 	"TSUBCC",	LADDW, ATSUBCC,
436 	"TSUBCCTV",	LADDW, ATSUBCCTV,
437 	"TVC",		LTRAP, ATVC,
438 	"TVS",		LTRAP, ATVS,
439 	"UNIMP",	LUNIMP, AUNIMP,
440 	"WORD",		LUNIMP, AWORD,
441 	"XNOR",		LADDW, AXNOR,
442 	"XNORCC",	LADDW, AXNORCC,
443 	"XOR",		LXORW, AXOR,
444 	"XORCC",	LADDW, AXORCC,
445 
446 	"SCHED",	LSCHED, 0,
447 	"NOSCHED",	LSCHED, 0x80,
448 
449 	0
450 };
451 
452 void
453 cinit(void)
454 {
455 	Sym *s;
456 	int i;
457 
458 	nullgen.sym = S;
459 	nullgen.offset = 0;
460 	nullgen.type = D_NONE;
461 	nullgen.name = D_NONE;
462 	nullgen.reg = NREG;
463 	nullgen.xreg = NREG;
464 	if(FPCHIP)
465 		nullgen.dval = 0;
466 	for(i=0; i<sizeof(nullgen.sval); i++)
467 		nullgen.sval[i] = 0;
468 
469 	nerrors = 0;
470 	iostack = I;
471 	iofree = I;
472 	peekc = IGN;
473 	nhunk = 0;
474 	for(i=0; i<NHASH; i++)
475 		hash[i] = S;
476 	for(i=0; itab[i].name; i++) {
477 		s = slookup(itab[i].name);
478 		s->type = itab[i].type;
479 		s->value = itab[i].value;
480 	}
481 
482 	pathname = allocn(pathname, 0, 100);
483 	if(mygetwd(pathname, 99) == 0) {
484 		pathname = allocn(pathname, 100, 900);
485 		if(mygetwd(pathname, 999) == 0)
486 			strcpy(pathname, "/?");
487 	}
488 }
489 
490 void
491 syminit(Sym *s)
492 {
493 
494 	s->type = LNAME;
495 	s->value = 0;
496 }
497 
498 void
499 cclean(void)
500 {
501 
502 	outcode(AEND, &nullgen, NREG, &nullgen);
503 	Bflush(&obuf);
504 }
505 
506 void
507 zname(char *n, int t, int s)
508 {
509 
510 	Bputc(&obuf, ANAME);
511 	Bputc(&obuf, t);	/* type */
512 	Bputc(&obuf, s);	/* sym */
513 	while(*n) {
514 		Bputc(&obuf, *n);
515 		n++;
516 	}
517 	Bputc(&obuf, 0);
518 }
519 
520 void
521 zaddr(Gen *a, int s)
522 {
523 	long l;
524 	int i;
525 	char *n;
526 	Ieee e;
527 
528 	Bputc(&obuf, a->type);
529 	Bputc(&obuf, a->reg);
530 	Bputc(&obuf, s);
531 	Bputc(&obuf, a->name);
532 	switch(a->type) {
533 	default:
534 		print("unknown type %d\n", a->type);
535 		exits("arg");
536 
537 	case D_NONE:
538 	case D_REG:
539 	case D_FREG:
540 	case D_CREG:
541 	case D_PREG:
542 		break;
543 
544 	case D_OREG:
545 	case D_ASI:
546 	case D_CONST:
547 	case D_BRANCH:
548 		l = a->offset;
549 		Bputc(&obuf, l);
550 		Bputc(&obuf, l>>8);
551 		Bputc(&obuf, l>>16);
552 		Bputc(&obuf, l>>24);
553 		break;
554 
555 	case D_SCONST:
556 		n = a->sval;
557 		for(i=0; i<NSNAME; i++) {
558 			Bputc(&obuf, *n);
559 			n++;
560 		}
561 		break;
562 
563 	case D_FCONST:
564 		ieeedtod(&e, a->dval);
565 		Bputc(&obuf, e.l);
566 		Bputc(&obuf, e.l>>8);
567 		Bputc(&obuf, e.l>>16);
568 		Bputc(&obuf, e.l>>24);
569 		Bputc(&obuf, e.h);
570 		Bputc(&obuf, e.h>>8);
571 		Bputc(&obuf, e.h>>16);
572 		Bputc(&obuf, e.h>>24);
573 		break;
574 	}
575 }
576 
577 void
578 outcode(int a, Gen *g1, int reg, Gen *g2)
579 {
580 	int sf, st, t;
581 	Sym *s;
582 
583 	if(pass == 1)
584 		goto out;
585 	if(g1->xreg != NREG) {
586 		if(reg != NREG || g2->xreg != NREG)
587 			yyerror("bad addressing modes");
588 		reg = g1->xreg;
589 	} else
590 	if(g2->xreg != NREG) {
591 		if(reg != NREG)
592 			yyerror("bad addressing modes");
593 		reg = g2->xreg;
594 	}
595 jackpot:
596 	sf = 0;
597 	s = g1->sym;
598 	while(s != S) {
599 		sf = s->sym;
600 		if(sf < 0 || sf >= NSYM)
601 			sf = 0;
602 		t = g1->name;
603 		if(h[sf].type == t)
604 		if(h[sf].sym == s)
605 			break;
606 		zname(s->name, t, sym);
607 		s->sym = sym;
608 		h[sym].sym = s;
609 		h[sym].type = t;
610 		sf = sym;
611 		sym++;
612 		if(sym >= NSYM)
613 			sym = 1;
614 		break;
615 	}
616 	st = 0;
617 	s = g2->sym;
618 	while(s != S) {
619 		st = s->sym;
620 		if(st < 0 || st >= NSYM)
621 			st = 0;
622 		t = g2->name;
623 		if(h[st].type == t)
624 		if(h[st].sym == s)
625 			break;
626 		zname(s->name, t, sym);
627 		s->sym = sym;
628 		h[sym].sym = s;
629 		h[sym].type = t;
630 		st = sym;
631 		sym++;
632 		if(sym >= NSYM)
633 			sym = 1;
634 		if(st == sf)
635 			goto jackpot;
636 		break;
637 	}
638 	Bputc(&obuf, a);
639 	Bputc(&obuf, reg|nosched);
640 	Bputc(&obuf, lineno);
641 	Bputc(&obuf, lineno>>8);
642 	Bputc(&obuf, lineno>>16);
643 	Bputc(&obuf, lineno>>24);
644 	zaddr(g1, sf);
645 	zaddr(g2, st);
646 
647 out:
648 	if(a != AGLOBL && a != ADATA)
649 		pc++;
650 }
651 
652 void
653 outhist(void)
654 {
655 	Gen g;
656 	Hist *h;
657 	char *p, *q, *op, c;
658 	int n;
659 
660 	g = nullgen;
661 	c = pathchar();
662 	for(h = hist; h != H; h = h->link) {
663 		p = h->name;
664 		op = 0;
665 		/* on windows skip drive specifier in pathname */
666 		if(systemtype(Windows) && p && p[1] == ':'){
667 			p += 2;
668 			c = *p;
669 		}
670 		if(p && p[0] != c && h->offset == 0 && pathname){
671 			/* on windows skip drive specifier in pathname */
672 			if(systemtype(Windows) && pathname[1] == ':') {
673 				op = p;
674 				p = pathname+2;
675 				c = *p;
676 			} else if(pathname[0] == c){
677 				op = p;
678 				p = pathname;
679 			}
680 		}
681 		while(p) {
682 			q = strchr(p, c);
683 			if(q) {
684 				n = q-p;
685 				if(n == 0){
686 					n = 1;	/* leading "/" */
687 					*p = '/';	/* don't emit "\" on windows */
688 				}
689 				q++;
690 			} else {
691 				n = strlen(p);
692 				q = 0;
693 			}
694 			if(n) {
695 				Bputc(&obuf, ANAME);
696 				Bputc(&obuf, D_FILE);	/* type */
697 				Bputc(&obuf, 1);	/* sym */
698 				Bputc(&obuf, '<');
699 				Bwrite(&obuf, p, n);
700 				Bputc(&obuf, 0);
701 			}
702 			p = q;
703 			if(p == 0 && op) {
704 				p = op;
705 				op = 0;
706 			}
707 		}
708 		g.offset = h->offset;
709 
710 		Bputc(&obuf, AHISTORY);
711 		Bputc(&obuf, 0);
712 		Bputc(&obuf, h->line);
713 		Bputc(&obuf, h->line>>8);
714 		Bputc(&obuf, h->line>>16);
715 		Bputc(&obuf, h->line>>24);
716 		zaddr(&nullgen, 0);
717 		zaddr(&g, 0);
718 	}
719 }
720 
721 #include "../cc/lexbody"
722 #include "../cc/macbody"
723