xref: /csrg-svn/old/as.vax/asmain.c (revision 596)
1*596Sbill /* Copyright (c) 1980 Regents of the University of California */
2*596Sbill static	char sccsid[] = "@(#)asmain.c 4.1 08/13/80";
3*596Sbill #include <stdio.h>
4*596Sbill #include <ctype.h>
5*596Sbill #include <sys/types.h>
6*596Sbill #include <signal.h>
7*596Sbill #include <a.out.h>
8*596Sbill 
9*596Sbill #include "as.h"
10*596Sbill #include "assyms.h"
11*596Sbill #include "asexpr.h"
12*596Sbill #include "asscan.h"
13*596Sbill 
14*596Sbill #ifdef UNIX
15*596Sbill #define	unix_lang_name "VAX/UNIX Assembler V3.0"
16*596Sbill #endif
17*596Sbill 
18*596Sbill #ifdef VMS
19*596Sbill #define vms_lang_name "VAX/VMS C assembler V1.00"
20*596Sbill #endif VMS
21*596Sbill 
22*596Sbill /*
23*596Sbill  *	variables to manage reading the assembly source files
24*596Sbill  */
25*596Sbill char	*dotsname;	/*the current file name; managed by the parser*/
26*596Sbill int	lineno;		/*current line number; managed by the parser*/
27*596Sbill char	*innames[32];	/*names of the files being assembled*/
28*596Sbill int	ninfiles;	/*how many interesting files there are*/
29*596Sbill /*
30*596Sbill  *	Flags settable from the argv process argument list
31*596Sbill  */
32*596Sbill int	silent = 0;	/*don't complain about any errors*/
33*596Sbill int	savelabels = 0;	/*write the labels to the a.out file*/
34*596Sbill int 	d124 = 4;	/*default allocate 4 bytes for unknown pointers*/
35*596Sbill int	anyerrs = 0;	/*no errors yet*/
36*596Sbill int	orgwarn = 0;	/*Bad origins*/
37*596Sbill int	passno = 1;	/* current pass*/
38*596Sbill 
39*596Sbill #ifdef DEBUG
40*596Sbill int 	debug = 0;
41*596Sbill int	toktrace = 0;
42*596Sbill #endif
43*596Sbill 
44*596Sbill int	useVM =		/*put the temp file in virtual memory*/
45*596Sbill #ifdef VMS
46*596Sbill 	1;		/*VMS has virtual memory (duh)*/
47*596Sbill #endif VMS
48*596Sbill #ifdef UNIX
49*596Sbill  	0;
50*596Sbill #endif
51*596Sbill 
52*596Sbill char	*endcore;	/*where to get more symbol space*/
53*596Sbill 
54*596Sbill /*
55*596Sbill  *	Managers of the a.out file.
56*596Sbill  */
57*596Sbill struct	exec	hdr;
58*596Sbill #define	MAGIC	0410
59*596Sbill u_long	tsize;		/* total text size */
60*596Sbill u_long	dsize;		/* total data size */
61*596Sbill u_long	datbase;	/* base of the data segment */
62*596Sbill u_long	trsize;		/* total text relocation size */
63*596Sbill u_long	drsize;		/* total data relocation size */
64*596Sbill 
65*596Sbill /*
66*596Sbill  *	Information about the current segment is accumulated in
67*596Sbill  *	usedot; the most important information stored is the
68*596Sbill  *	accumulated size of each of the text and data segments
69*596Sbill  *
70*596Sbill  *	dotp points to the correct usedot expression for the current segment
71*596Sbill  */
72*596Sbill struct	exp	usedot[NLOC+NLOC];	/* info about all segments */
73*596Sbill struct	exp	*dotp;			/* data/text location pointer */
74*596Sbill /*
75*596Sbill  *	The inter pass temporary file is opened and closed by stdio, but
76*596Sbill  *	is written to using direct read/write, as the temporary file
77*596Sbill  *	is composed of buffers exactly BUFSIZ long.
78*596Sbill  */
79*596Sbill FILE	*tmpfil;			/* interpass communication file */
80*596Sbill /*
81*596Sbill  *	a.out is created during the second pass.
82*596Sbill  *	It is opened by stdio, but is filled with the parallel
83*596Sbill  *	block I/O library
84*596Sbill  */
85*596Sbill char	*outfile = "a.out";
86*596Sbill FILE	*a_out_file;
87*596Sbill off_t	a_out_off;			/* cumulative offsets for segments */
88*596Sbill /*
89*596Sbill  *	The logical files containing the assembled data for each of
90*596Sbill  *	the text and data segments are
91*596Sbill  *	managed by the parallel block I/O library.
92*596Sbill  *	a.out is logically opened in many places at once to
93*596Sbill  *	receive the assembled data from the various segments as
94*596Sbill  *	it all trickles in, but is physically opened only once
95*596Sbill  *	to minimize file overhead.
96*596Sbill  */
97*596Sbill BFILE	*usefile[NLOC+NLOC];		/* text/data files */
98*596Sbill BFILE	*txtfil;			/* current text/data file */
99*596Sbill /*
100*596Sbill  *	Relocation information is accumulated seperately for each
101*596Sbill  *	segment.  This is required by the old loader (from BTL),
102*596Sbill  *	but not by the new loader (Bill Joy).
103*596Sbill  *
104*596Sbill  *	However, the size of the relocation information can not be computed
105*596Sbill  *	during or after the 1st pass because the ''absoluteness' of values
106*596Sbill  *	is unknown until all locally declared symbols have been seen.
107*596Sbill  *	Thus, the size of the relocation information is only
108*596Sbill  *	known after the second pass is finished.
109*596Sbill  *	This obviates the use of the block I/O
110*596Sbill  *	library, which requires knowing the exact offsets in a.out.
111*596Sbill  *
112*596Sbill  *	So, we save the relocation information internally (we don't
113*596Sbill  *	go to internal files to minimize overhead).
114*596Sbill  *
115*596Sbill  *	Empirically, we studied 259 files composing the system,
116*596Sbill  *	two compilers and a compiler generator: (all of which have
117*596Sbill  *	fairly large source files)
118*596Sbill  *
119*596Sbill  *	Number of files = 259
120*596Sbill  *		Number of non zero text reloc files: 233
121*596Sbill  *		Number of non zero data reloc files: 53
122*596Sbill  *	Average text relocation = 889
123*596Sbill  *	Average data relocation = 346
124*596Sbill  *	Number of files > BUFSIZ text relocation = 71
125*596Sbill  *	Number of files > BUFSIZ data relocation = 6
126*596Sbill  *
127*596Sbill  *	For compiled C code, there is usually one text segment and two
128*596Sbill  *	data segments; we see that allocating our own buffers and
129*596Sbill  *	doing our internal handling of relocation information will,
130*596Sbill  *	on the average, not use more memory than taken up by the buffers
131*596Sbill  *	allocated for doing file I/O in parallel to a number of file.
132*596Sbill  *
133*596Sbill  *	If we are assembling with the -V option, we
134*596Sbill  *	use the left over token buffers from the 2nd pass,
135*596Sbill  *	otherwise, we create our own.
136*596Sbill  *
137*596Sbill  *	When the 2nd pass is complete, closeoutrel flushes the token
138*596Sbill  *	buffers out to a BFILE.
139*596Sbill  *
140*596Sbill  *	The internals to relbufdesc are known only in assyms.c
141*596Sbill  *
142*596Sbill  *	outrel constructs the relocation information.
143*596Sbill  *	closeoutrel flushes the relocation information to relfil.
144*596Sbill  */
145*596Sbill struct	relbufdesc	*rusefile[NLOC+NLOC];
146*596Sbill struct	relbufdesc 	*relfil;	/* un concatnated relocation info */
147*596Sbill BFILE	*relocfile;			/* concatnated relocation info */
148*596Sbill /*
149*596Sbill  *	Once the relocation information has been written,
150*596Sbill  *	we can write out the symbol table using the Block I/O
151*596Sbill  *	mechanisms, as we once again know the offsets into
152*596Sbill  *	the a.out file.
153*596Sbill  *
154*596Sbill  *	We use relfil to output the symbol table information.
155*596Sbill  */
156*596Sbill 
157*596Sbill char	*tmpdirprefix =
158*596Sbill #ifdef UNIX
159*596Sbill 			"/tmp/";
160*596Sbill #else VMS
161*596Sbill 			"/usr/tmp/";
162*596Sbill #endif
163*596Sbill 
164*596Sbill #define		TMP_SUFFIX	"asXXXXXX"
165*596Sbill char		tmpn1[TNAMESIZE];
166*596Sbill 
167*596Sbill int delexit();
168*596Sbill 
169*596Sbill main(argc, argv)
170*596Sbill 	int	argc;
171*596Sbill 	char 	**argv;
172*596Sbill {
173*596Sbill 
174*596Sbill 	tmpn1[0] = 0;
175*596Sbill 	endcore = (char *)sbrk(0);
176*596Sbill 
177*596Sbill 	argprocess(argc, argv);		/* process argument lists */
178*596Sbill 	if (anyerrs) exit(1);
179*596Sbill 
180*596Sbill 	initialize();
181*596Sbill 	zeroorigins();			/* set origins to zero */
182*596Sbill 	zerolocals();			/* fix local label counters */
183*596Sbill 
184*596Sbill 	i_pass1();			/* open temp files, etc */
185*596Sbill 	pass1();			/* first pass through .s files */
186*596Sbill 	testlocals();			/* check for undefined locals */
187*596Sbill 	if (anyerrs) delexit();
188*596Sbill 
189*596Sbill 	pass1_5();			/* resolve jxxx */
190*596Sbill 	if (anyerrs) delexit();
191*596Sbill 
192*596Sbill 	open_a_out();			/* open a.out */
193*596Sbill 	roundsegments();		/* round segments to FW */
194*596Sbill 	build_hdr();			/* build initial header, and output */
195*596Sbill 
196*596Sbill 	i_pass2();			/* reopen temporary file, etc */
197*596Sbill 	pass2();			/* second pass through the virtual .s */
198*596Sbill 	if (anyerrs) delexit();
199*596Sbill 
200*596Sbill 	fillsegments();			/* fill segments with 0 to FW */
201*596Sbill 	reloc_syms();			/* dump relocation and symbol table */
202*596Sbill 
203*596Sbill 	delete();			/* remove tmp file */
204*596Sbill 	bflush();			/* close off block I/O view of a.out */
205*596Sbill 	fix_a_out();			/* add in text and data reloc counts */
206*596Sbill 
207*596Sbill 	if (anyerrs == 0 && orgwarn)
208*596Sbill 		yyerror("Caution: absolute origins.\n");
209*596Sbill 	exit(anyerrs != 0);
210*596Sbill }	/*end of UNIX main*/
211*596Sbill 
212*596Sbill argprocess(argc, argv)
213*596Sbill 	int	argc;
214*596Sbill 	char	*argv[];
215*596Sbill {
216*596Sbill 	register	char	*cp;
217*596Sbill 
218*596Sbill 	ninfiles = 0;
219*596Sbill 	silent = 0;
220*596Sbill #ifdef DEBUG
221*596Sbill 	debug = 0;
222*596Sbill #endif
223*596Sbill 	dotsname = "<argv error>";
224*596Sbill 	while (argc > 1) {
225*596Sbill 		if (argv[1][0] == '-'){
226*596Sbill 			cp = argv[1] + 1;
227*596Sbill 			/*
228*596Sbill 			 *	We can throw away single minus signs, so
229*596Sbill 			 *	that make scripts for the PDP 11 assembler work
230*596Sbill 			 *	on this assembler too
231*596Sbill 			 */
232*596Sbill 			while (*cp){
233*596Sbill 				switch(*cp++){
234*596Sbill 				 default:
235*596Sbill 					yyerror("Unknown flag: %c", *--cp);
236*596Sbill 					cp++;
237*596Sbill 					break;
238*596Sbill 				 case 'd':
239*596Sbill 					d124 = *cp++ - '0';
240*596Sbill 					if ( (d124 != 1) && (d124 != 2) &&
241*596Sbill 					     (d124 != 4)){
242*596Sbill 						yyerror("-d[124] only");
243*596Sbill 						exit(1);
244*596Sbill 					}
245*596Sbill 					break;
246*596Sbill 				 case 'o':
247*596Sbill 					if (argc < 3){
248*596Sbill 						yyerror("-o what???");
249*596Sbill 						exit(1);
250*596Sbill 					}
251*596Sbill 					outfile = argv[2];
252*596Sbill 				   bumpone:
253*596Sbill 					argc -= 2;
254*596Sbill 					argv += 2;
255*596Sbill 					goto nextarg;
256*596Sbill 
257*596Sbill 				 case 't':
258*596Sbill 					if (argc < 3){
259*596Sbill 						yyerror("-t what???");
260*596Sbill 						exit(1);
261*596Sbill 					}
262*596Sbill 					tmpdirprefix = argv[2];
263*596Sbill 					goto bumpone;
264*596Sbill 
265*596Sbill 				 case 'V':
266*596Sbill 					useVM = 1;
267*596Sbill 					break;
268*596Sbill 				 case 'W':
269*596Sbill 					silent = 1;
270*596Sbill 					break;
271*596Sbill 				 case 'L':
272*596Sbill 					savelabels = 1;
273*596Sbill 					break;
274*596Sbill #ifdef DEBUG
275*596Sbill 				 case 'D':
276*596Sbill 					debug = 1;
277*596Sbill 					break;
278*596Sbill 				 case 'T':
279*596Sbill 					toktrace = 1;
280*596Sbill 					break;
281*596Sbill #endif
282*596Sbill 				}	/*end of the switch*/
283*596Sbill 			}	/*end of pulling out all arguments*/
284*596Sbill 		}	/*end of a flag argument*/
285*596Sbill 		else {	/*file name*/
286*596Sbill 			if (ninfiles > 32){
287*596Sbill 				yyerror("More than 32 file names");
288*596Sbill 				exit(3);
289*596Sbill 			}
290*596Sbill 			innames[ninfiles++] = argv[1];
291*596Sbill 		}
292*596Sbill 		--argc; ++argv;
293*596Sbill 	   nextarg:;
294*596Sbill 	}
295*596Sbill }
296*596Sbill 
297*596Sbill initialize()
298*596Sbill {
299*596Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
300*596Sbill 		signal(SIGINT, delexit);
301*596Sbill 	/*
302*596Sbill 	 *	Install symbols in the table
303*596Sbill 	 */
304*596Sbill 	symtabinit();
305*596Sbill 	syminstall();
306*596Sbill 	/*
307*596Sbill 	 *	Build the expression parser accelerator token sets
308*596Sbill 	 */
309*596Sbill 	buildtokensets();
310*596Sbill }
311*596Sbill 
312*596Sbill zeroorigins()
313*596Sbill {
314*596Sbill 	register	int	locindex;
315*596Sbill 	/*
316*596Sbill 	 *	Mark usedot: the first NLOC slots are for named text segments,
317*596Sbill 	 *	the next for named data segments.
318*596Sbill 	 */
319*596Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
320*596Sbill 		usedot[locindex].xtype = XTEXT;
321*596Sbill 		usedot[NLOC + locindex].xtype = XDATA;
322*596Sbill 		usedot[locindex].xvalue = 0;
323*596Sbill 		usedot[NLOC + locindex].xvalue = 0;
324*596Sbill 		usedot[locindex].yvalue = 0;
325*596Sbill 		usedot[NLOC + locindex].yvalue = 0;
326*596Sbill 	}
327*596Sbill }
328*596Sbill 
329*596Sbill zerolocals()
330*596Sbill {
331*596Sbill 	register	int	i;
332*596Sbill 
333*596Sbill 	for (i = 0; i <= 9; i++) {
334*596Sbill 		lgensym[i] = 1;
335*596Sbill 		genref[i] = 0;
336*596Sbill 	}
337*596Sbill }
338*596Sbill 
339*596Sbill i_pass1()
340*596Sbill {
341*596Sbill 	if (useVM == 0){
342*596Sbill 		strcat(tmpn1, tmpdirprefix);
343*596Sbill 		strcat(tmpn1, TMP_SUFFIX);
344*596Sbill 		mktemp(tmpn1);
345*596Sbill 		tmpfil = fopen(tmpn1, "w");
346*596Sbill 		if (tmpfil==NULL) {
347*596Sbill 		  yyerror("Bad pass 1 temporary file for writing %s", tmpn1);
348*596Sbill 		  delexit();
349*596Sbill 		}
350*596Sbill 	}
351*596Sbill 
352*596Sbill 	inittmpfile();
353*596Sbill }
354*596Sbill 
355*596Sbill pass1()
356*596Sbill {
357*596Sbill 	register	int	i;
358*596Sbill 
359*596Sbill 	passno = 1;
360*596Sbill 	dotp = &usedot[0];
361*596Sbill 	txtfil = (BFILE *)0;
362*596Sbill 	relfil = (struct relbufdesc *)0;
363*596Sbill 
364*596Sbill 	if (ninfiles == 0){		/*take the input from stdin directly*/
365*596Sbill 		lineno = 1;
366*596Sbill 		dotsname = "<stdin>";
367*596Sbill 
368*596Sbill 		yyparse();
369*596Sbill 	} else {		/*we have the names tanked*/
370*596Sbill 		for (i = 0; i < ninfiles; i++){
371*596Sbill 			new_dot_s(innames[i]);
372*596Sbill 			if (freopen(innames[i], "r", stdin) == NULL) {
373*596Sbill 				yyerror( "Can't open source file %s\n",
374*596Sbill 					innames[i]);
375*596Sbill 				exit(2);
376*596Sbill 			}
377*596Sbill 			/* stdio is NOT used to read the input characters */
378*596Sbill 			/* we use read directly, into our own buffers */
379*596Sbill 			yyparse();
380*596Sbill 		}
381*596Sbill 	}
382*596Sbill 
383*596Sbill 	closetmpfile();		/*kick out the last buffered intermediate text*/
384*596Sbill }
385*596Sbill 
386*596Sbill testlocals()
387*596Sbill {
388*596Sbill 	register	int	i;
389*596Sbill 	for (i = 0; i <= 9; i++) {
390*596Sbill 		if (genref[i])
391*596Sbill 			yyerror("Reference to undefined local label %df", i);
392*596Sbill 		lgensym[i] = 1;
393*596Sbill 		genref[i] = 0;
394*596Sbill 	}
395*596Sbill }
396*596Sbill 
397*596Sbill pass1_5()
398*596Sbill {
399*596Sbill 	sortsymtab();
400*596Sbill #ifdef DEBUG
401*596Sbill 	if (debug) dumpsymtab();
402*596Sbill #endif
403*596Sbill 	jxxxfix();
404*596Sbill #ifdef DEBUG
405*596Sbill 	if (debug) dumpsymtab();
406*596Sbill #endif
407*596Sbill }
408*596Sbill 
409*596Sbill open_a_out()
410*596Sbill {
411*596Sbill 	/*
412*596Sbill 	 *	Open up the a.out file now, and get set to build
413*596Sbill 	 *	up offsets into it for all of the various text,data
414*596Sbill 	 *	text relocation and data relocation segments.
415*596Sbill 	 */
416*596Sbill 	a_out_file = fopen(outfile, "w");
417*596Sbill 	if (a_out_file == NULL) {
418*596Sbill 		yyerror("Cannot create %s", outfile);
419*596Sbill 		delexit();
420*596Sbill 	}
421*596Sbill 	biofd = a_out_file->_file;
422*596Sbill 	a_out_off = 0;
423*596Sbill }
424*596Sbill 
425*596Sbill roundsegments()
426*596Sbill {
427*596Sbill 	register	int	locindex;
428*596Sbill 	register	long	v;
429*596Sbill 	/*
430*596Sbill 	 *	round and assign text segment origins
431*596Sbill 	 *	the exec header always goes in usefile[0]
432*596Sbill 	 */
433*596Sbill 	tsize = 0;
434*596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
435*596Sbill 		v = round(usedot[locindex].xvalue, FW);
436*596Sbill 		usedot[locindex].xvalue = tsize;
437*596Sbill 		if ((locindex == 0) || (v != 0) ){
438*596Sbill 			usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE));
439*596Sbill 			bopen(usefile[locindex], a_out_off);
440*596Sbill 			if (locindex == 0)
441*596Sbill 				a_out_off = sizeof (struct exec);
442*596Sbill 		} else {
443*596Sbill 			usefile[locindex] = (BFILE *)-1;
444*596Sbill 		}
445*596Sbill 		tsize += v;
446*596Sbill 		a_out_off += v;
447*596Sbill 	}
448*596Sbill 	/*
449*596Sbill 	 *		Round and assign data segment origins.
450*596Sbill 	 */
451*596Sbill 	datbase = round(tsize, PAGRND);
452*596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
453*596Sbill 		v = round(usedot[NLOC+locindex].xvalue, FW);
454*596Sbill 		usedot[NLOC+locindex].xvalue = datbase + dsize;
455*596Sbill 		if (v != 0){
456*596Sbill 			usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE));
457*596Sbill 			bopen(usefile[NLOC + locindex], a_out_off);
458*596Sbill 		} else {
459*596Sbill 			usefile[NLOC + locindex] = (BFILE *)-1;
460*596Sbill 		}
461*596Sbill 		dsize += v;
462*596Sbill 		a_out_off += v;
463*596Sbill 	}
464*596Sbill 	/*
465*596Sbill 	 *	Assign final values to symbols
466*596Sbill 	 */
467*596Sbill 	hdr.a_bss = dsize;
468*596Sbill 	freezesymtab();		/* this touches hdr.a_bss */
469*596Sbill 	stabfix();
470*596Sbill 	/*
471*596Sbill 	 *	Set up the relocation information "files" to
472*596Sbill 	 *	be zero; outrel takes care of the rest
473*596Sbill 	 */
474*596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++){
475*596Sbill 		rusefile[locindex] = (struct relbufdesc *)0;
476*596Sbill 	}
477*596Sbill }
478*596Sbill 
479*596Sbill build_hdr()
480*596Sbill {
481*596Sbill 	/*
482*596Sbill 	 *	Except for the text and data relocation sizes,
483*596Sbill 	 *	calculate the final values for the header
484*596Sbill 	 *
485*596Sbill 	 *	Write out the initial copy; we to come
486*596Sbill 	 *	back later and patch up a_trsize and a_drsize,
487*596Sbill 	 *	and overwrite this first version of the header.
488*596Sbill 	 */
489*596Sbill 	hdr.a_magic = MAGIC;
490*596Sbill 	hdr.a_text = tsize;
491*596Sbill 	hdr.a_data = dsize;
492*596Sbill 	hdr.a_bss -= dsize;
493*596Sbill 	hdr.a_syms = sizesymtab();	/* Does not include string pool length */
494*596Sbill 	hdr.a_entry = 0;
495*596Sbill 	hdr.a_trsize = 0;
496*596Sbill 	hdr.a_drsize = 0;
497*596Sbill 
498*596Sbill 	bwrite((char *)&hdr, sizeof(hdr), usefile[0]);
499*596Sbill }
500*596Sbill 
501*596Sbill i_pass2()
502*596Sbill {
503*596Sbill 	if (useVM == 0) {
504*596Sbill 		fclose(tmpfil);
505*596Sbill 		tmpfil = fopen(tmpn1, "r");
506*596Sbill 		if (tmpfil==NULL) {
507*596Sbill 		   yyerror("Bad pass 2 temporary file for reading %s", tmpn1);
508*596Sbill 		   delexit();
509*596Sbill 		}
510*596Sbill 	}
511*596Sbill }
512*596Sbill 
513*596Sbill pass2()
514*596Sbill {
515*596Sbill #ifdef DEBUG
516*596Sbill 	if (debug)
517*596Sbill 		printf("\n\n\n\t\tPASS 2\n\n\n\n");
518*596Sbill #endif DEBUG
519*596Sbill 	passno = 2;
520*596Sbill 	lineno = 1;
521*596Sbill 	dotp = &usedot[0];
522*596Sbill 	txtfil = usefile[0];	/* already opened (always!) */
523*596Sbill 	relfil = 0;		/* outrel takes care of the rest */
524*596Sbill 	initoutrel();
525*596Sbill 
526*596Sbill 	inittmpfile();
527*596Sbill 
528*596Sbill 	yyparse();
529*596Sbill 
530*596Sbill 	closetmpfile();
531*596Sbill }
532*596Sbill 
533*596Sbill fillsegments()
534*596Sbill {
535*596Sbill 	int	locindex;
536*596Sbill 	/*
537*596Sbill 	 *	Round text and data segments to FW by appending zeros
538*596Sbill 	 */
539*596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++) {
540*596Sbill 		if (usefile[locindex]) {
541*596Sbill 			txtfil = usefile[locindex];
542*596Sbill 			dotp = &usedot[locindex];
543*596Sbill 			while (usedot[locindex].xvalue & FW)
544*596Sbill 				outb(0);
545*596Sbill 		}
546*596Sbill 	}
547*596Sbill }
548*596Sbill 
549*596Sbill reloc_syms()
550*596Sbill {
551*596Sbill 	u_long	closerelfil();
552*596Sbill 	/*
553*596Sbill 	 *	Move the relocation information to a.out
554*596Sbill 	 *	a_out_off is the offset so far:
555*596Sbill 	 *	exec + text segments + data segments
556*596Sbill 	 */
557*596Sbill 	relocfile = (BFILE *)Calloc(1,sizeof(BFILE));
558*596Sbill 	bopen(relocfile, a_out_off);
559*596Sbill 	a_out_off += closeoutrel(relocfile);
560*596Sbill 
561*596Sbill 	hdr.a_trsize = trsize;
562*596Sbill 	hdr.a_drsize = drsize;
563*596Sbill 	/*
564*596Sbill 	 *	Output the symbol table
565*596Sbill 	 *	and if FLEXNAMES is set, the string pool
566*596Sbill 	 */
567*596Sbill 	symwrite(relocfile);
568*596Sbill }
569*596Sbill 
570*596Sbill fix_a_out()
571*596Sbill {
572*596Sbill 	if (lseek(a_out_file->_file, 0L, 0) < 0)
573*596Sbill 		yyerror("Reposition for header rewrite fails");
574*596Sbill 	if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0)
575*596Sbill 		yyerror("Rewrite of header fails");
576*596Sbill }
577*596Sbill 
578*596Sbill delexit()
579*596Sbill {
580*596Sbill 	delete();
581*596Sbill 	if (passno == 2){
582*596Sbill 		unlink(outfile);
583*596Sbill 	}
584*596Sbill 	exit(1);
585*596Sbill }
586*596Sbill 
587*596Sbill delete()
588*596Sbill {
589*596Sbill 	if (useVM == 0 || tmpn1[0])
590*596Sbill 		unlink(tmpn1);
591*596Sbill }
592*596Sbill 
593*596Sbill sawabort()
594*596Sbill {
595*596Sbill 	char	*fillinbuffer();
596*596Sbill 	while (fillinbuffer() != (char *)0)
597*596Sbill 		continue;
598*596Sbill 	delete();
599*596Sbill 	exit(1);	/*although the previous pass will also exit non zero*/
600*596Sbill }
601*596Sbill 
602*596Sbill panic(fmt, a1, a2, a3, a4)
603*596Sbill 	char	*fmt;
604*596Sbill 	/*VARARGS 1*/
605*596Sbill {
606*596Sbill 	yyerror("Assembler panic: bad internal data structure.");
607*596Sbill 	yyerror(fmt, a1, a2, a3, a4);
608*596Sbill 	delete();
609*596Sbill 	abort();
610*596Sbill }
611