xref: /csrg-svn/old/as.vax/asmain.c (revision 643)
1596Sbill /* Copyright (c) 1980 Regents of the University of California */
2*643Sbill static	char sccsid[] = "@(#)asmain.c 4.5 08/16/80";
3596Sbill #include <stdio.h>
4596Sbill #include <ctype.h>
5596Sbill #include <signal.h>
6596Sbill 
7596Sbill #include "as.h"
8596Sbill #include "assyms.h"
9596Sbill #include "asexpr.h"
10596Sbill #include "asscan.h"
11596Sbill 
12596Sbill #ifdef UNIX
13*643Sbill #define	unix_lang_name "VAX/UNIX Assembler V08/16/80 4.5"
14596Sbill #endif
15596Sbill 
16596Sbill #ifdef VMS
17631Shenry #define vms_lang_name "VAX/VMS C Assembler V1.00"
18596Sbill #endif VMS
19596Sbill 
20596Sbill /*
21596Sbill  *	variables to manage reading the assembly source files
22596Sbill  */
23596Sbill char	*dotsname;	/*the current file name; managed by the parser*/
24596Sbill int	lineno;		/*current line number; managed by the parser*/
25*643Sbill char	**innames;	/*names of the files being assembled*/
26596Sbill int	ninfiles;	/*how many interesting files there are*/
27596Sbill /*
28596Sbill  *	Flags settable from the argv process argument list
29596Sbill  */
30596Sbill int	silent = 0;	/*don't complain about any errors*/
31596Sbill int	savelabels = 0;	/*write the labels to the a.out file*/
32596Sbill int 	d124 = 4;	/*default allocate 4 bytes for unknown pointers*/
33596Sbill int	anyerrs = 0;	/*no errors yet*/
34596Sbill int	orgwarn = 0;	/*Bad origins*/
35596Sbill int	passno = 1;	/* current pass*/
36636Shenry int	jxxxJUMP = 0;	/* in jxxxes that branch too far, use jmp instead of brw */
37638Sbill int	readonlydata = 0;	/* initialzed data -> text space */
38596Sbill 
39596Sbill #ifdef DEBUG
40596Sbill int 	debug = 0;
41596Sbill int	toktrace = 0;
42596Sbill #endif
43596Sbill 
44596Sbill int	useVM =		/*put the temp file in virtual memory*/
45596Sbill #ifdef VMS
46596Sbill 	1;		/*VMS has virtual memory (duh)*/
47596Sbill #endif VMS
48596Sbill #ifdef UNIX
49596Sbill  	0;
50596Sbill #endif
51596Sbill 
52596Sbill char	*endcore;	/*where to get more symbol space*/
53596Sbill 
54596Sbill /*
55596Sbill  *	Managers of the a.out file.
56596Sbill  */
57596Sbill struct	exec	hdr;
58638Sbill #define	MAGIC	0407
59596Sbill u_long	tsize;		/* total text size */
60596Sbill u_long	dsize;		/* total data size */
61596Sbill u_long	datbase;	/* base of the data segment */
62596Sbill u_long	trsize;		/* total text relocation size */
63596Sbill u_long	drsize;		/* total data relocation size */
64596Sbill 
65596Sbill /*
66596Sbill  *	Information about the current segment is accumulated in
67596Sbill  *	usedot; the most important information stored is the
68596Sbill  *	accumulated size of each of the text and data segments
69596Sbill  *
70596Sbill  *	dotp points to the correct usedot expression for the current segment
71596Sbill  */
72596Sbill struct	exp	usedot[NLOC+NLOC];	/* info about all segments */
73596Sbill struct	exp	*dotp;			/* data/text location pointer */
74596Sbill /*
75596Sbill  *	The inter pass temporary file is opened and closed by stdio, but
76596Sbill  *	is written to using direct read/write, as the temporary file
77596Sbill  *	is composed of buffers exactly BUFSIZ long.
78596Sbill  */
79596Sbill FILE	*tmpfil;			/* interpass communication file */
80596Sbill /*
81596Sbill  *	a.out is created during the second pass.
82596Sbill  *	It is opened by stdio, but is filled with the parallel
83596Sbill  *	block I/O library
84596Sbill  */
85596Sbill char	*outfile = "a.out";
86596Sbill FILE	*a_out_file;
87596Sbill off_t	a_out_off;			/* cumulative offsets for segments */
88596Sbill /*
89596Sbill  *	The logical files containing the assembled data for each of
90596Sbill  *	the text and data segments are
91596Sbill  *	managed by the parallel block I/O library.
92596Sbill  *	a.out is logically opened in many places at once to
93596Sbill  *	receive the assembled data from the various segments as
94596Sbill  *	it all trickles in, but is physically opened only once
95596Sbill  *	to minimize file overhead.
96596Sbill  */
97596Sbill BFILE	*usefile[NLOC+NLOC];		/* text/data files */
98596Sbill BFILE	*txtfil;			/* current text/data file */
99596Sbill /*
100596Sbill  *	Relocation information is accumulated seperately for each
101596Sbill  *	segment.  This is required by the old loader (from BTL),
102596Sbill  *	but not by the new loader (Bill Joy).
103596Sbill  *
104596Sbill  *	However, the size of the relocation information can not be computed
105596Sbill  *	during or after the 1st pass because the ''absoluteness' of values
106596Sbill  *	is unknown until all locally declared symbols have been seen.
107596Sbill  *	Thus, the size of the relocation information is only
108596Sbill  *	known after the second pass is finished.
109596Sbill  *	This obviates the use of the block I/O
110596Sbill  *	library, which requires knowing the exact offsets in a.out.
111596Sbill  *
112596Sbill  *	So, we save the relocation information internally (we don't
113596Sbill  *	go to internal files to minimize overhead).
114596Sbill  *
115596Sbill  *	Empirically, we studied 259 files composing the system,
116596Sbill  *	two compilers and a compiler generator: (all of which have
117596Sbill  *	fairly large source files)
118596Sbill  *
119596Sbill  *	Number of files = 259
120596Sbill  *		Number of non zero text reloc files: 233
121596Sbill  *		Number of non zero data reloc files: 53
122596Sbill  *	Average text relocation = 889
123596Sbill  *	Average data relocation = 346
124596Sbill  *	Number of files > BUFSIZ text relocation = 71
125596Sbill  *	Number of files > BUFSIZ data relocation = 6
126596Sbill  *
127596Sbill  *	For compiled C code, there is usually one text segment and two
128596Sbill  *	data segments; we see that allocating our own buffers and
129596Sbill  *	doing our internal handling of relocation information will,
130596Sbill  *	on the average, not use more memory than taken up by the buffers
131596Sbill  *	allocated for doing file I/O in parallel to a number of file.
132596Sbill  *
133596Sbill  *	If we are assembling with the -V option, we
134596Sbill  *	use the left over token buffers from the 2nd pass,
135596Sbill  *	otherwise, we create our own.
136596Sbill  *
137596Sbill  *	When the 2nd pass is complete, closeoutrel flushes the token
138596Sbill  *	buffers out to a BFILE.
139596Sbill  *
140596Sbill  *	The internals to relbufdesc are known only in assyms.c
141596Sbill  *
142596Sbill  *	outrel constructs the relocation information.
143596Sbill  *	closeoutrel flushes the relocation information to relfil.
144596Sbill  */
145596Sbill struct	relbufdesc	*rusefile[NLOC+NLOC];
146596Sbill struct	relbufdesc 	*relfil;	/* un concatnated relocation info */
147596Sbill BFILE	*relocfile;			/* concatnated relocation info */
148596Sbill /*
149596Sbill  *	Once the relocation information has been written,
150596Sbill  *	we can write out the symbol table using the Block I/O
151596Sbill  *	mechanisms, as we once again know the offsets into
152596Sbill  *	the a.out file.
153596Sbill  *
154596Sbill  *	We use relfil to output the symbol table information.
155596Sbill  */
156596Sbill 
157596Sbill char	*tmpdirprefix =
158596Sbill #ifdef UNIX
159596Sbill 			"/tmp/";
160596Sbill #else VMS
161596Sbill 			"/usr/tmp/";
162596Sbill #endif
163596Sbill 
164596Sbill #define		TMP_SUFFIX	"asXXXXXX"
165596Sbill char		tmpn1[TNAMESIZE];
166596Sbill 
167596Sbill int delexit();
168596Sbill 
169596Sbill main(argc, argv)
170596Sbill 	int	argc;
171596Sbill 	char 	**argv;
172596Sbill {
173596Sbill 
174596Sbill 	tmpn1[0] = 0;
175596Sbill 	endcore = (char *)sbrk(0);
176596Sbill 
177596Sbill 	argprocess(argc, argv);		/* process argument lists */
178596Sbill 	if (anyerrs) exit(1);
179596Sbill 
180596Sbill 	initialize();
181596Sbill 	zeroorigins();			/* set origins to zero */
182596Sbill 	zerolocals();			/* fix local label counters */
183596Sbill 
184596Sbill 	i_pass1();			/* open temp files, etc */
185596Sbill 	pass1();			/* first pass through .s files */
186596Sbill 	testlocals();			/* check for undefined locals */
187596Sbill 	if (anyerrs) delexit();
188596Sbill 
189596Sbill 	pass1_5();			/* resolve jxxx */
190596Sbill 	if (anyerrs) delexit();
191596Sbill 
192596Sbill 	open_a_out();			/* open a.out */
193596Sbill 	roundsegments();		/* round segments to FW */
194596Sbill 	build_hdr();			/* build initial header, and output */
195596Sbill 
196596Sbill 	i_pass2();			/* reopen temporary file, etc */
197596Sbill 	pass2();			/* second pass through the virtual .s */
198596Sbill 	if (anyerrs) delexit();
199596Sbill 
200596Sbill 	fillsegments();			/* fill segments with 0 to FW */
201596Sbill 	reloc_syms();			/* dump relocation and symbol table */
202596Sbill 
203596Sbill 	delete();			/* remove tmp file */
204596Sbill 	bflush();			/* close off block I/O view of a.out */
205596Sbill 	fix_a_out();			/* add in text and data reloc counts */
206596Sbill 
207596Sbill 	if (anyerrs == 0 && orgwarn)
208596Sbill 		yyerror("Caution: absolute origins.\n");
209596Sbill 	exit(anyerrs != 0);
210596Sbill }	/*end of UNIX main*/
211596Sbill 
212596Sbill argprocess(argc, argv)
213596Sbill 	int	argc;
214596Sbill 	char	*argv[];
215596Sbill {
216596Sbill 	register	char	*cp;
217596Sbill 
218596Sbill 	ninfiles = 0;
219596Sbill 	silent = 0;
220596Sbill #ifdef DEBUG
221596Sbill 	debug = 0;
222596Sbill #endif
223*643Sbill 	innames = (char **)ClearCalloc(argc+1, sizeof (innames[0]));
224596Sbill 	dotsname = "<argv error>";
225596Sbill 	while (argc > 1) {
226*643Sbill 		if (argv[1][0] != '-')
227*643Sbill 			innames[ninfiles++] = argv[1];
228*643Sbill 		else {
229596Sbill 			cp = argv[1] + 1;
230596Sbill 			/*
231596Sbill 			 *	We can throw away single minus signs, so
232596Sbill 			 *	that make scripts for the PDP 11 assembler work
233596Sbill 			 *	on this assembler too
234596Sbill 			 */
235596Sbill 			while (*cp){
236596Sbill 				switch(*cp++){
237596Sbill 				 default:
238596Sbill 					yyerror("Unknown flag: %c", *--cp);
239596Sbill 					cp++;
240596Sbill 					break;
241596Sbill 				 case 'd':
242596Sbill 					d124 = *cp++ - '0';
243596Sbill 					if ( (d124 != 1) && (d124 != 2) &&
244596Sbill 					     (d124 != 4)){
245596Sbill 						yyerror("-d[124] only");
246596Sbill 						exit(1);
247596Sbill 					}
248596Sbill 					break;
249596Sbill 				 case 'o':
250596Sbill 					if (argc < 3){
251596Sbill 						yyerror("-o what???");
252596Sbill 						exit(1);
253596Sbill 					}
254596Sbill 					outfile = argv[2];
255596Sbill 				   bumpone:
256596Sbill 					argc -= 2;
257596Sbill 					argv += 2;
258596Sbill 					goto nextarg;
259596Sbill 
260596Sbill 				 case 't':
261596Sbill 					if (argc < 3){
262596Sbill 						yyerror("-t what???");
263596Sbill 						exit(1);
264596Sbill 					}
265596Sbill 					tmpdirprefix = argv[2];
266596Sbill 					goto bumpone;
267596Sbill 
268596Sbill 				 case 'V':
269596Sbill 					useVM = 1;
270596Sbill 					break;
271596Sbill 				 case 'W':
272596Sbill 					silent = 1;
273596Sbill 					break;
274596Sbill 				 case 'L':
275596Sbill 					savelabels = 1;
276596Sbill 					break;
277636Shenry 				 case 'J':
278636Shenry 					jxxxJUMP = 1;
279636Shenry 					break;
280596Sbill #ifdef DEBUG
281596Sbill 				 case 'D':
282596Sbill 					debug = 1;
283596Sbill 					break;
284596Sbill 				 case 'T':
285596Sbill 					toktrace = 1;
286596Sbill 					break;
287596Sbill #endif
288638Sbill 				 case 'R':
289638Sbill 					readonlydata = 1;
290638Sbill 					break;
291596Sbill 				}	/*end of the switch*/
292596Sbill 			}	/*end of pulling out all arguments*/
293596Sbill 		}	/*end of a flag argument*/
294596Sbill 		--argc; ++argv;
295596Sbill 	   nextarg:;
296596Sbill 	}
297*643Sbill 	/* innames[ninfiles] = 0; */
298596Sbill }
299596Sbill 
300596Sbill initialize()
301596Sbill {
302596Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
303596Sbill 		signal(SIGINT, delexit);
304596Sbill 	/*
305596Sbill 	 *	Install symbols in the table
306596Sbill 	 */
307596Sbill 	symtabinit();
308596Sbill 	syminstall();
309596Sbill 	/*
310596Sbill 	 *	Build the expression parser accelerator token sets
311596Sbill 	 */
312596Sbill 	buildtokensets();
313596Sbill }
314596Sbill 
315596Sbill zeroorigins()
316596Sbill {
317596Sbill 	register	int	locindex;
318596Sbill 	/*
319596Sbill 	 *	Mark usedot: the first NLOC slots are for named text segments,
320596Sbill 	 *	the next for named data segments.
321596Sbill 	 */
322596Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
323631Shenry 		usedot[locindex].e_xtype = XTEXT;
324631Shenry 		usedot[NLOC + locindex].e_xtype = XDATA;
325631Shenry 		usedot[locindex].e_xvalue = 0;
326631Shenry 		usedot[NLOC + locindex].e_xvalue = 0;
327631Shenry 		usedot[locindex].e_yvalue = 0;
328631Shenry 		usedot[NLOC + locindex].e_yvalue = 0;
329596Sbill 	}
330596Sbill }
331596Sbill 
332596Sbill zerolocals()
333596Sbill {
334596Sbill 	register	int	i;
335596Sbill 
336596Sbill 	for (i = 0; i <= 9; i++) {
337596Sbill 		lgensym[i] = 1;
338596Sbill 		genref[i] = 0;
339596Sbill 	}
340596Sbill }
341596Sbill 
342596Sbill i_pass1()
343596Sbill {
344596Sbill 	if (useVM == 0){
345596Sbill 		strcat(tmpn1, tmpdirprefix);
346596Sbill 		strcat(tmpn1, TMP_SUFFIX);
347596Sbill 		mktemp(tmpn1);
348596Sbill 		tmpfil = fopen(tmpn1, "w");
349596Sbill 		if (tmpfil==NULL) {
350596Sbill 		  yyerror("Bad pass 1 temporary file for writing %s", tmpn1);
351596Sbill 		  delexit();
352596Sbill 		}
353596Sbill 	}
354596Sbill 
355596Sbill 	inittmpfile();
356636Shenry 	initijxxx();
357596Sbill }
358596Sbill 
359596Sbill pass1()
360596Sbill {
361596Sbill 	register	int	i;
362596Sbill 
363596Sbill 	passno = 1;
364596Sbill 	dotp = &usedot[0];
365596Sbill 	txtfil = (BFILE *)0;
366596Sbill 	relfil = (struct relbufdesc *)0;
367596Sbill 
368596Sbill 	if (ninfiles == 0){		/*take the input from stdin directly*/
369596Sbill 		lineno = 1;
370596Sbill 		dotsname = "<stdin>";
371596Sbill 
372596Sbill 		yyparse();
373596Sbill 	} else {		/*we have the names tanked*/
374596Sbill 		for (i = 0; i < ninfiles; i++){
375596Sbill 			new_dot_s(innames[i]);
376596Sbill 			if (freopen(innames[i], "r", stdin) == NULL) {
377596Sbill 				yyerror( "Can't open source file %s\n",
378596Sbill 					innames[i]);
379596Sbill 				exit(2);
380596Sbill 			}
381596Sbill 			/* stdio is NOT used to read the input characters */
382596Sbill 			/* we use read directly, into our own buffers */
383596Sbill 			yyparse();
384596Sbill 		}
385596Sbill 	}
386596Sbill 
387596Sbill 	closetmpfile();		/*kick out the last buffered intermediate text*/
388596Sbill }
389596Sbill 
390596Sbill testlocals()
391596Sbill {
392596Sbill 	register	int	i;
393596Sbill 	for (i = 0; i <= 9; i++) {
394596Sbill 		if (genref[i])
395596Sbill 			yyerror("Reference to undefined local label %df", i);
396596Sbill 		lgensym[i] = 1;
397596Sbill 		genref[i] = 0;
398596Sbill 	}
399596Sbill }
400596Sbill 
401596Sbill pass1_5()
402596Sbill {
403596Sbill 	sortsymtab();
404596Sbill #ifdef DEBUG
405596Sbill 	if (debug) dumpsymtab();
406596Sbill #endif
407596Sbill 	jxxxfix();
408596Sbill #ifdef DEBUG
409596Sbill 	if (debug) dumpsymtab();
410596Sbill #endif
411596Sbill }
412596Sbill 
413596Sbill open_a_out()
414596Sbill {
415596Sbill 	/*
416596Sbill 	 *	Open up the a.out file now, and get set to build
417596Sbill 	 *	up offsets into it for all of the various text,data
418596Sbill 	 *	text relocation and data relocation segments.
419596Sbill 	 */
420596Sbill 	a_out_file = fopen(outfile, "w");
421596Sbill 	if (a_out_file == NULL) {
422596Sbill 		yyerror("Cannot create %s", outfile);
423596Sbill 		delexit();
424596Sbill 	}
425596Sbill 	biofd = a_out_file->_file;
426596Sbill 	a_out_off = 0;
427596Sbill }
428596Sbill 
429596Sbill roundsegments()
430596Sbill {
431596Sbill 	register	int	locindex;
432596Sbill 	register	long	v;
433596Sbill 	/*
434596Sbill 	 *	round and assign text segment origins
435596Sbill 	 *	the exec header always goes in usefile[0]
436596Sbill 	 */
437596Sbill 	tsize = 0;
438596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
439631Shenry 		v = round(usedot[locindex].e_xvalue, FW);
440631Shenry 		usedot[locindex].e_xvalue = tsize;
441596Sbill 		if ((locindex == 0) || (v != 0) ){
442596Sbill 			usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE));
443596Sbill 			bopen(usefile[locindex], a_out_off);
444596Sbill 			if (locindex == 0)
445596Sbill 				a_out_off = sizeof (struct exec);
446596Sbill 		} else {
447596Sbill 			usefile[locindex] = (BFILE *)-1;
448596Sbill 		}
449596Sbill 		tsize += v;
450596Sbill 		a_out_off += v;
451596Sbill 	}
452596Sbill 	/*
453596Sbill 	 *		Round and assign data segment origins.
454596Sbill 	 */
455638Sbill 	datbase = round(tsize, FW);
456596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
457631Shenry 		v = round(usedot[NLOC+locindex].e_xvalue, FW);
458631Shenry 		usedot[NLOC+locindex].e_xvalue = datbase + dsize;
459596Sbill 		if (v != 0){
460596Sbill 			usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE));
461596Sbill 			bopen(usefile[NLOC + locindex], a_out_off);
462596Sbill 		} else {
463596Sbill 			usefile[NLOC + locindex] = (BFILE *)-1;
464596Sbill 		}
465596Sbill 		dsize += v;
466596Sbill 		a_out_off += v;
467596Sbill 	}
468596Sbill 	/*
469596Sbill 	 *	Assign final values to symbols
470596Sbill 	 */
471596Sbill 	hdr.a_bss = dsize;
472596Sbill 	freezesymtab();		/* this touches hdr.a_bss */
473596Sbill 	stabfix();
474596Sbill 	/*
475596Sbill 	 *	Set up the relocation information "files" to
476596Sbill 	 *	be zero; outrel takes care of the rest
477596Sbill 	 */
478596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++){
479596Sbill 		rusefile[locindex] = (struct relbufdesc *)0;
480596Sbill 	}
481596Sbill }
482596Sbill 
483596Sbill build_hdr()
484596Sbill {
485596Sbill 	/*
486596Sbill 	 *	Except for the text and data relocation sizes,
487596Sbill 	 *	calculate the final values for the header
488596Sbill 	 *
489596Sbill 	 *	Write out the initial copy; we to come
490596Sbill 	 *	back later and patch up a_trsize and a_drsize,
491596Sbill 	 *	and overwrite this first version of the header.
492596Sbill 	 */
493596Sbill 	hdr.a_magic = MAGIC;
494596Sbill 	hdr.a_text = tsize;
495596Sbill 	hdr.a_data = dsize;
496596Sbill 	hdr.a_bss -= dsize;
497596Sbill 	hdr.a_syms = sizesymtab();	/* Does not include string pool length */
498596Sbill 	hdr.a_entry = 0;
499596Sbill 	hdr.a_trsize = 0;
500596Sbill 	hdr.a_drsize = 0;
501596Sbill 
502596Sbill 	bwrite((char *)&hdr, sizeof(hdr), usefile[0]);
503596Sbill }
504596Sbill 
505596Sbill i_pass2()
506596Sbill {
507596Sbill 	if (useVM == 0) {
508596Sbill 		fclose(tmpfil);
509596Sbill 		tmpfil = fopen(tmpn1, "r");
510596Sbill 		if (tmpfil==NULL) {
511596Sbill 		   yyerror("Bad pass 2 temporary file for reading %s", tmpn1);
512596Sbill 		   delexit();
513596Sbill 		}
514596Sbill 	}
515596Sbill }
516596Sbill 
517596Sbill pass2()
518596Sbill {
519596Sbill #ifdef DEBUG
520596Sbill 	if (debug)
521596Sbill 		printf("\n\n\n\t\tPASS 2\n\n\n\n");
522596Sbill #endif DEBUG
523596Sbill 	passno = 2;
524596Sbill 	lineno = 1;
525596Sbill 	dotp = &usedot[0];
526596Sbill 	txtfil = usefile[0];	/* already opened (always!) */
527596Sbill 	relfil = 0;		/* outrel takes care of the rest */
528596Sbill 	initoutrel();
529596Sbill 
530596Sbill 	inittmpfile();
531596Sbill 
532596Sbill 	yyparse();
533596Sbill 
534596Sbill 	closetmpfile();
535596Sbill }
536596Sbill 
537596Sbill fillsegments()
538596Sbill {
539596Sbill 	int	locindex;
540596Sbill 	/*
541596Sbill 	 *	Round text and data segments to FW by appending zeros
542596Sbill 	 */
543596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++) {
544596Sbill 		if (usefile[locindex]) {
545596Sbill 			txtfil = usefile[locindex];
546596Sbill 			dotp = &usedot[locindex];
547631Shenry 			while (usedot[locindex].e_xvalue & FW)
548596Sbill 				outb(0);
549596Sbill 		}
550596Sbill 	}
551596Sbill }
552596Sbill 
553596Sbill reloc_syms()
554596Sbill {
555596Sbill 	u_long	closerelfil();
556596Sbill 	/*
557596Sbill 	 *	Move the relocation information to a.out
558596Sbill 	 *	a_out_off is the offset so far:
559596Sbill 	 *	exec + text segments + data segments
560596Sbill 	 */
561596Sbill 	relocfile = (BFILE *)Calloc(1,sizeof(BFILE));
562596Sbill 	bopen(relocfile, a_out_off);
563596Sbill 	a_out_off += closeoutrel(relocfile);
564596Sbill 
565596Sbill 	hdr.a_trsize = trsize;
566596Sbill 	hdr.a_drsize = drsize;
567638Sbill 	if (readonlydata) {
568638Sbill 		hdr.a_text += hdr.a_data;
569638Sbill 		hdr.a_data = 0;
570638Sbill 		hdr.a_trsize += hdr.a_drsize;
571638Sbill 		hdr.a_drsize = 0;
572638Sbill 	}
573596Sbill 	/*
574596Sbill 	 *	Output the symbol table
575596Sbill 	 *	and if FLEXNAMES is set, the string pool
576596Sbill 	 */
577596Sbill 	symwrite(relocfile);
578596Sbill }
579596Sbill 
580596Sbill fix_a_out()
581596Sbill {
582596Sbill 	if (lseek(a_out_file->_file, 0L, 0) < 0)
583596Sbill 		yyerror("Reposition for header rewrite fails");
584596Sbill 	if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0)
585596Sbill 		yyerror("Rewrite of header fails");
586596Sbill }
587596Sbill 
588596Sbill delexit()
589596Sbill {
590596Sbill 	delete();
591596Sbill 	if (passno == 2){
592596Sbill 		unlink(outfile);
593596Sbill 	}
594596Sbill 	exit(1);
595596Sbill }
596596Sbill 
597596Sbill delete()
598596Sbill {
599596Sbill 	if (useVM == 0 || tmpn1[0])
600596Sbill 		unlink(tmpn1);
601596Sbill }
602596Sbill 
603596Sbill sawabort()
604596Sbill {
605596Sbill 	char	*fillinbuffer();
606596Sbill 	while (fillinbuffer() != (char *)0)
607596Sbill 		continue;
608596Sbill 	delete();
609596Sbill 	exit(1);	/*although the previous pass will also exit non zero*/
610596Sbill }
611596Sbill 
612596Sbill panic(fmt, a1, a2, a3, a4)
613596Sbill 	char	*fmt;
614596Sbill 	/*VARARGS 1*/
615596Sbill {
616596Sbill 	yyerror("Assembler panic: bad internal data structure.");
617596Sbill 	yyerror(fmt, a1, a2, a3, a4);
618596Sbill 	delete();
619596Sbill 	abort();
620596Sbill }
621