xref: /csrg-svn/old/as.vax/asmain.c (revision 13518)
15826Srrh /*
25826Srrh  *	Copyright (c) 1982 Regents of the University of California
35826Srrh  */
45826Srrh #ifndef lint
5*13518Srrh static char sccsid[] = "@(#)asmain.c 4.12 06/30/83";
65826Srrh #endif not lint
75826Srrh 
8596Sbill #include <stdio.h>
9596Sbill #include <ctype.h>
10596Sbill #include <signal.h>
11596Sbill 
12596Sbill #include "as.h"
13596Sbill #include "assyms.h"
145826Srrh #include "asscan.h"
15596Sbill #include "asexpr.h"
16596Sbill 
17*13518Srrh #define	unix_lang_name "VAX/UNIX Assembler V06/30/83 4.12"
18596Sbill /*
19596Sbill  *	variables to manage reading the assembly source files
20596Sbill  */
21596Sbill char	*dotsname;	/*the current file name; managed by the parser*/
22596Sbill int	lineno;		/*current line number; managed by the parser*/
23643Sbill char	**innames;	/*names of the files being assembled*/
24596Sbill int	ninfiles;	/*how many interesting files there are*/
25596Sbill /*
26596Sbill  *	Flags settable from the argv process argument list
27596Sbill  */
28596Sbill int	silent = 0;	/*don't complain about any errors*/
29596Sbill int	savelabels = 0;	/*write the labels to the a.out file*/
30596Sbill int 	d124 = 4;	/*default allocate 4 bytes for unknown pointers*/
31596Sbill int	anyerrs = 0;	/*no errors yet*/
325826Srrh int	anywarnings=0;	/*no warnings yet*/
33596Sbill int	orgwarn = 0;	/*Bad origins*/
34596Sbill int	passno = 1;	/* current pass*/
35636Shenry int	jxxxJUMP = 0;	/* in jxxxes that branch too far, use jmp instead of brw */
36638Sbill int	readonlydata = 0;	/* initialzed data -> text space */
37596Sbill 
385826Srrh int	nGHnumbers = 0;		/* GH numbers used */
395826Srrh int	nGHopcodes = 0;		/* GH opcodes used */
405826Srrh int	nnewopcodes = 0;	/* new opcodes used */
415826Srrh 
42596Sbill #ifdef DEBUG
43596Sbill int 	debug = 0;
44596Sbill int	toktrace = 0;
45596Sbill #endif
46596Sbill 
47*13518Srrh int	useVM =	0;
48596Sbill 
49596Sbill char	*endcore;	/*where to get more symbol space*/
50596Sbill 
51596Sbill /*
52596Sbill  *	Managers of the a.out file.
53596Sbill  */
54596Sbill struct	exec	hdr;
55638Sbill #define	MAGIC	0407
56596Sbill u_long	tsize;		/* total text size */
57596Sbill u_long	dsize;		/* total data size */
58596Sbill u_long	datbase;	/* base of the data segment */
59596Sbill u_long	trsize;		/* total text relocation size */
60596Sbill u_long	drsize;		/* total data relocation size */
61596Sbill 
62596Sbill /*
63596Sbill  *	Information about the current segment is accumulated in
64596Sbill  *	usedot; the most important information stored is the
65596Sbill  *	accumulated size of each of the text and data segments
66596Sbill  *
67596Sbill  *	dotp points to the correct usedot expression for the current segment
68596Sbill  */
69596Sbill struct	exp	usedot[NLOC+NLOC];	/* info about all segments */
70596Sbill struct	exp	*dotp;			/* data/text location pointer */
71596Sbill /*
7213512Srrh  *	The inter pass temporary token file is opened and closed by stdio, but
73596Sbill  *	is written to using direct read/write, as the temporary file
74596Sbill  *	is composed of buffers exactly BUFSIZ long.
75596Sbill  */
7613512Srrh FILE	*tokfile;			/* interpass communication file */
7713512Srrh char	tokfilename[TNAMESIZE];
78596Sbill /*
7913512Srrh  *	The string file is the string table
8013512Srrh  *	cat'ed to the end of the built up a.out file
8113512Srrh  */
8213512Srrh FILE	*strfile;			/* interpass string file */
8313512Srrh char	strfilename[TNAMESIZE];
8413512Srrh int	strfilepos = 0;			/* position within the string file */
8513512Srrh /*
86596Sbill  *	a.out is created during the second pass.
87596Sbill  *	It is opened by stdio, but is filled with the parallel
88596Sbill  *	block I/O library
89596Sbill  */
90596Sbill char	*outfile = "a.out";
91596Sbill FILE	*a_out_file;
92596Sbill off_t	a_out_off;			/* cumulative offsets for segments */
93596Sbill /*
94596Sbill  *	The logical files containing the assembled data for each of
95596Sbill  *	the text and data segments are
96596Sbill  *	managed by the parallel block I/O library.
97596Sbill  *	a.out is logically opened in many places at once to
98596Sbill  *	receive the assembled data from the various segments as
99596Sbill  *	it all trickles in, but is physically opened only once
100596Sbill  *	to minimize file overhead.
101596Sbill  */
102596Sbill BFILE	*usefile[NLOC+NLOC];		/* text/data files */
103596Sbill BFILE	*txtfil;			/* current text/data file */
104596Sbill /*
105596Sbill  *	Relocation information is accumulated seperately for each
106596Sbill  *	segment.  This is required by the old loader (from BTL),
107596Sbill  *	but not by the new loader (Bill Joy).
108596Sbill  *
109596Sbill  *	However, the size of the relocation information can not be computed
110596Sbill  *	during or after the 1st pass because the ''absoluteness' of values
111596Sbill  *	is unknown until all locally declared symbols have been seen.
112596Sbill  *	Thus, the size of the relocation information is only
113596Sbill  *	known after the second pass is finished.
114596Sbill  *	This obviates the use of the block I/O
115596Sbill  *	library, which requires knowing the exact offsets in a.out.
116596Sbill  *
117596Sbill  *	So, we save the relocation information internally (we don't
118596Sbill  *	go to internal files to minimize overhead).
119596Sbill  *
120596Sbill  *	Empirically, we studied 259 files composing the system,
121596Sbill  *	two compilers and a compiler generator: (all of which have
122596Sbill  *	fairly large source files)
123596Sbill  *
124596Sbill  *	Number of files = 259
125596Sbill  *		Number of non zero text reloc files: 233
126596Sbill  *		Number of non zero data reloc files: 53
127596Sbill  *	Average text relocation = 889
128596Sbill  *	Average data relocation = 346
129596Sbill  *	Number of files > BUFSIZ text relocation = 71
130596Sbill  *	Number of files > BUFSIZ data relocation = 6
131596Sbill  *
132596Sbill  *	For compiled C code, there is usually one text segment and two
133596Sbill  *	data segments; we see that allocating our own buffers and
134596Sbill  *	doing our internal handling of relocation information will,
135596Sbill  *	on the average, not use more memory than taken up by the buffers
136596Sbill  *	allocated for doing file I/O in parallel to a number of file.
137596Sbill  *
138596Sbill  *	If we are assembling with the -V option, we
139596Sbill  *	use the left over token buffers from the 2nd pass,
140596Sbill  *	otherwise, we create our own.
141596Sbill  *
142596Sbill  *	When the 2nd pass is complete, closeoutrel flushes the token
143596Sbill  *	buffers out to a BFILE.
144596Sbill  *
145596Sbill  *	The internals to relbufdesc are known only in assyms.c
146596Sbill  *
147596Sbill  *	outrel constructs the relocation information.
148596Sbill  *	closeoutrel flushes the relocation information to relfil.
149596Sbill  */
150596Sbill struct	relbufdesc	*rusefile[NLOC+NLOC];
151596Sbill struct	relbufdesc 	*relfil;	/* un concatnated relocation info */
152596Sbill BFILE	*relocfile;			/* concatnated relocation info */
153596Sbill /*
154596Sbill  *	Once the relocation information has been written,
155596Sbill  *	we can write out the symbol table using the Block I/O
156596Sbill  *	mechanisms, as we once again know the offsets into
157596Sbill  *	the a.out file.
158596Sbill  *
159596Sbill  *	We use relfil to output the symbol table information.
160596Sbill  */
161*13518Srrh char	*tmpdirprefix = "/tmp/";
162596Sbill int delexit();
163596Sbill 
164596Sbill main(argc, argv)
165596Sbill 	int	argc;
166596Sbill 	char 	**argv;
167596Sbill {
1685826Srrh 	char	*sbrk();
169596Sbill 
17013512Srrh 	tokfilename[0] = 0;
17113512Srrh 	strfilename[0] = 0;
1725826Srrh 	endcore = sbrk(0);
173596Sbill 
174596Sbill 	argprocess(argc, argv);		/* process argument lists */
175596Sbill 	if (anyerrs) exit(1);
176596Sbill 
177596Sbill 	initialize();
178596Sbill 	zeroorigins();			/* set origins to zero */
179596Sbill 	zerolocals();			/* fix local label counters */
180596Sbill 
181596Sbill 	i_pass1();			/* open temp files, etc */
182596Sbill 	pass1();			/* first pass through .s files */
183596Sbill 	testlocals();			/* check for undefined locals */
184596Sbill 	if (anyerrs) delexit();
185596Sbill 
186596Sbill 	pass1_5();			/* resolve jxxx */
187596Sbill 	if (anyerrs) delexit();
188596Sbill 
189596Sbill 	open_a_out();			/* open a.out */
190679Shenry 	roundsegments();		/* round segments to FW */
191596Sbill 	build_hdr();			/* build initial header, and output */
192596Sbill 
193596Sbill 	i_pass2();			/* reopen temporary file, etc */
194596Sbill 	pass2();			/* second pass through the virtual .s */
195596Sbill 	if (anyerrs) delexit();
196596Sbill 
197679Shenry 	fillsegments();			/* fill segments with 0 to FW */
198596Sbill 	reloc_syms();			/* dump relocation and symbol table */
199596Sbill 
200596Sbill 	delete();			/* remove tmp file */
201596Sbill 	bflush();			/* close off block I/O view of a.out */
202596Sbill 	fix_a_out();			/* add in text and data reloc counts */
203596Sbill 
204596Sbill 	if (anyerrs == 0 && orgwarn)
205596Sbill 		yyerror("Caution: absolute origins.\n");
2065826Srrh 
2075826Srrh 	if (nGHnumbers)
2085826Srrh 		yywarning("Caution: G or H format floating point numbers");
2095826Srrh 	if (nGHopcodes)
2105826Srrh 		yywarning("Caution: G or H format floating point operators");
2115826Srrh 	if (nnewopcodes)
2125826Srrh 		yywarning("Caution: New Opcodes");
2135826Srrh 	if (nGHnumbers || nGHopcodes || nnewopcodes)
2145826Srrh 		yywarning("These are not defined for all implementations of the VAX architecture.\n");
2155826Srrh 
216596Sbill 	exit(anyerrs != 0);
217*13518Srrh }
218596Sbill 
219596Sbill argprocess(argc, argv)
220596Sbill 	int	argc;
221596Sbill 	char	*argv[];
222596Sbill {
223596Sbill 	register	char	*cp;
224596Sbill 
225596Sbill 	ninfiles = 0;
226596Sbill 	silent = 0;
227596Sbill #ifdef DEBUG
228596Sbill 	debug = 0;
229596Sbill #endif
230643Sbill 	innames = (char **)ClearCalloc(argc+1, sizeof (innames[0]));
231596Sbill 	dotsname = "<argv error>";
232596Sbill 	while (argc > 1) {
233643Sbill 		if (argv[1][0] != '-')
234643Sbill 			innames[ninfiles++] = argv[1];
235643Sbill 		else {
236596Sbill 			cp = argv[1] + 1;
237596Sbill 			/*
238596Sbill 			 *	We can throw away single minus signs, so
239596Sbill 			 *	that make scripts for the PDP 11 assembler work
240596Sbill 			 *	on this assembler too
241596Sbill 			 */
242596Sbill 			while (*cp){
243596Sbill 				switch(*cp++){
244596Sbill 				 default:
245596Sbill 					yyerror("Unknown flag: %c", *--cp);
246596Sbill 					cp++;
247596Sbill 					break;
2486559Srrh 				 case 'v':
2496559Srrh 					selfwhat(stdout);
2506559Srrh 					exit(1);
251596Sbill 				 case 'd':
252596Sbill 					d124 = *cp++ - '0';
253596Sbill 					if ( (d124 != 1) && (d124 != 2) &&
254596Sbill 					     (d124 != 4)){
255596Sbill 						yyerror("-d[124] only");
256596Sbill 						exit(1);
257596Sbill 					}
258596Sbill 					break;
259596Sbill 				 case 'o':
260596Sbill 					if (argc < 3){
261596Sbill 						yyerror("-o what???");
262596Sbill 						exit(1);
263596Sbill 					}
264596Sbill 					outfile = argv[2];
265596Sbill 				   bumpone:
266596Sbill 					argc -= 2;
267596Sbill 					argv += 2;
268596Sbill 					goto nextarg;
269596Sbill 
270596Sbill 				 case 't':
271596Sbill 					if (argc < 3){
272596Sbill 						yyerror("-t what???");
273596Sbill 						exit(1);
274596Sbill 					}
275596Sbill 					tmpdirprefix = argv[2];
276596Sbill 					goto bumpone;
277596Sbill 
278596Sbill 				 case 'V':
279596Sbill 					useVM = 1;
280596Sbill 					break;
281596Sbill 				 case 'W':
282596Sbill 					silent = 1;
283596Sbill 					break;
284596Sbill 				 case 'L':
285596Sbill 					savelabels = 1;
286596Sbill 					break;
287636Shenry 				 case 'J':
288636Shenry 					jxxxJUMP = 1;
289636Shenry 					break;
290596Sbill #ifdef DEBUG
291596Sbill 				 case 'D':
292596Sbill 					debug = 1;
293596Sbill 					break;
294596Sbill 				 case 'T':
295596Sbill 					toktrace = 1;
296596Sbill 					break;
297596Sbill #endif
298638Sbill 				 case 'R':
299638Sbill 					readonlydata = 1;
300638Sbill 					break;
301596Sbill 				}	/*end of the switch*/
302596Sbill 			}	/*end of pulling out all arguments*/
303596Sbill 		}	/*end of a flag argument*/
304596Sbill 		--argc; ++argv;
305596Sbill 	   nextarg:;
306596Sbill 	}
307643Sbill 	/* innames[ninfiles] = 0; */
308596Sbill }
3096559Srrh /*
3106559Srrh  *	poke through the data space and find all sccs identifiers.
3116559Srrh  *	We assume:
3126559Srrh  *	a) that extern char **environ; is the first thing in the bss
3136559Srrh  *	segment (true, if one is using the new version of cmgt.crt0.c)
3146559Srrh  *	b) that the sccsid's have not been put into text space.
3156559Srrh  */
3166559Srrh selfwhat(place)
3176559Srrh 	FILE	*place;
3186559Srrh {
3196559Srrh 	extern	char **environ;
3206559Srrh 	register	char	*ub;
3216559Srrh 	register	char *cp;
3226559Srrh 	register	char	*pat;
3236559Srrh 	char	*sbrk();
324596Sbill 
3256559Srrh 	for (cp = (char *)&environ, ub = sbrk(0); cp < ub; cp++){
3266559Srrh 		if (cp[0] != '@') continue;
3276559Srrh 		if (cp[1] != '(') continue;
3286559Srrh 		if (cp[2] != '#') continue;
3296559Srrh 		if (cp[3] != ')') continue;
3306559Srrh 		fputc('\t', place);
3316559Srrh 		for (cp += 4; cp < ub; cp++){
3326559Srrh 			if (*cp == 0) break;
3336559Srrh 			if (*cp == '>') break;
3346559Srrh 			if (*cp == '\n') break;
3356559Srrh 			fputc(*cp, place);
3366559Srrh 		}
3376559Srrh 		fputc('\n', place);
3386559Srrh 	}
3396559Srrh }
3406559Srrh 
341596Sbill initialize()
342596Sbill {
343596Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
344596Sbill 		signal(SIGINT, delexit);
345596Sbill 	/*
346596Sbill 	 *	Install symbols in the table
347596Sbill 	 */
348596Sbill 	symtabinit();
349596Sbill 	syminstall();
350596Sbill 	/*
351596Sbill 	 *	Build the expression parser accelerator token sets
352596Sbill 	 */
353596Sbill 	buildtokensets();
354596Sbill }
355596Sbill 
356596Sbill zeroorigins()
357596Sbill {
358596Sbill 	register	int	locindex;
359596Sbill 	/*
360596Sbill 	 *	Mark usedot: the first NLOC slots are for named text segments,
361596Sbill 	 *	the next for named data segments.
362596Sbill 	 */
363596Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
364631Shenry 		usedot[locindex].e_xtype = XTEXT;
365631Shenry 		usedot[NLOC + locindex].e_xtype = XDATA;
366631Shenry 		usedot[locindex].e_xvalue = 0;
367631Shenry 		usedot[NLOC + locindex].e_xvalue = 0;
368596Sbill 	}
369596Sbill }
370596Sbill 
371596Sbill zerolocals()
372596Sbill {
373596Sbill 	register	int	i;
374596Sbill 
375596Sbill 	for (i = 0; i <= 9; i++) {
376596Sbill 		lgensym[i] = 1;
377596Sbill 		genref[i] = 0;
378596Sbill 	}
379596Sbill }
380596Sbill 
381596Sbill i_pass1()
382596Sbill {
38313512Srrh 	FILE	*tempopen();
38413512Srrh 	if (useVM == 0)
38513512Srrh 		tokfile = tempopen(tokfilename, "T");
38613512Srrh 	strfile = tempopen(strfilename, "S");
38713512Srrh 	/*
38813512Srrh 	 *	write out the string length.
38913512Srrh 	 *	This will be overwritten when the
39013512Srrh 	 *	strings are tacked onto the growing a.out file
39113512Srrh 	 */
39213512Srrh 	strfilepos = sizeof(int);
39313512Srrh 	fwrite(&strfilepos, sizeof(int), 1, strfile);
394596Sbill 
39513512Srrh 	inittokfile();
396636Shenry 	initijxxx();
397596Sbill }
398596Sbill 
39913512Srrh FILE *tempopen(tname, part)
40013512Srrh 	char	*tname;
40113512Srrh 	char	*part;
40213512Srrh {
40313512Srrh 	FILE	*file;
40413512Srrh 	sprintf(tname, "%s%sas%s%05d",
40513512Srrh 		tmpdirprefix,
40613512Srrh 		(tmpdirprefix[strlen(tmpdirprefix)-1] != '/') ? "/" : 0,
40713512Srrh 		part,
40813512Srrh 		getpid());
40913512Srrh 	file = fopen(tname, "w");
41013512Srrh 	if (file == NULL) {
41113512Srrh 		yyerror("Bad pass 1 temporary file for writing %s", tname);
41213512Srrh 		delexit();
41313512Srrh 	}
41413512Srrh 	return(file);
41513512Srrh }
41613512Srrh 
417596Sbill pass1()
418596Sbill {
419596Sbill 	register	int	i;
420596Sbill 
421596Sbill 	passno = 1;
422596Sbill 	dotp = &usedot[0];
423596Sbill 	txtfil = (BFILE *)0;
424596Sbill 	relfil = (struct relbufdesc *)0;
425596Sbill 
426596Sbill 	if (ninfiles == 0){		/*take the input from stdin directly*/
427596Sbill 		lineno = 1;
428596Sbill 		dotsname = "<stdin>";
429596Sbill 
430596Sbill 		yyparse();
431596Sbill 	} else {		/*we have the names tanked*/
432596Sbill 		for (i = 0; i < ninfiles; i++){
433596Sbill 			new_dot_s(innames[i]);
434596Sbill 			if (freopen(innames[i], "r", stdin) == NULL) {
435596Sbill 				yyerror( "Can't open source file %s\n",
436596Sbill 					innames[i]);
437596Sbill 				exit(2);
438596Sbill 			}
439596Sbill 			/* stdio is NOT used to read the input characters */
440596Sbill 			/* we use read directly, into our own buffers */
441596Sbill 			yyparse();
442596Sbill 		}
443596Sbill 	}
444596Sbill 
44513512Srrh 	closetokfile();		/*kick out the last buffered intermediate text*/
446596Sbill }
447596Sbill 
448596Sbill testlocals()
449596Sbill {
450596Sbill 	register	int	i;
451596Sbill 	for (i = 0; i <= 9; i++) {
452596Sbill 		if (genref[i])
453596Sbill 			yyerror("Reference to undefined local label %df", i);
454596Sbill 		lgensym[i] = 1;
455596Sbill 		genref[i] = 0;
456596Sbill 	}
457596Sbill }
458596Sbill 
459596Sbill pass1_5()
460596Sbill {
461596Sbill 	sortsymtab();
462596Sbill #ifdef DEBUG
463596Sbill 	if (debug) dumpsymtab();
464596Sbill #endif
465596Sbill 	jxxxfix();
466596Sbill #ifdef DEBUG
467596Sbill 	if (debug) dumpsymtab();
468596Sbill #endif
469596Sbill }
470596Sbill 
471596Sbill open_a_out()
472596Sbill {
473596Sbill 	/*
474596Sbill 	 *	Open up the a.out file now, and get set to build
475596Sbill 	 *	up offsets into it for all of the various text,data
476596Sbill 	 *	text relocation and data relocation segments.
477596Sbill 	 */
478596Sbill 	a_out_file = fopen(outfile, "w");
479596Sbill 	if (a_out_file == NULL) {
480596Sbill 		yyerror("Cannot create %s", outfile);
481596Sbill 		delexit();
482596Sbill 	}
483596Sbill 	biofd = a_out_file->_file;
484596Sbill 	a_out_off = 0;
485596Sbill }
486596Sbill 
487596Sbill roundsegments()
488596Sbill {
489596Sbill 	register	int	locindex;
490596Sbill 	register	long	v;
491596Sbill 	/*
492596Sbill 	 *	round and assign text segment origins
493596Sbill 	 *	the exec header always goes in usefile[0]
494596Sbill 	 */
495596Sbill 	tsize = 0;
496596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
497679Shenry 		v = round(usedot[locindex].e_xvalue, FW);
498631Shenry 		usedot[locindex].e_xvalue = tsize;
499596Sbill 		if ((locindex == 0) || (v != 0) ){
500596Sbill 			usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE));
501596Sbill 			bopen(usefile[locindex], a_out_off);
502596Sbill 			if (locindex == 0)
503596Sbill 				a_out_off = sizeof (struct exec);
504596Sbill 		} else {
505596Sbill 			usefile[locindex] = (BFILE *)-1;
506596Sbill 		}
507596Sbill 		tsize += v;
508596Sbill 		a_out_off += v;
509596Sbill 	}
510596Sbill 	/*
511596Sbill 	 *		Round and assign data segment origins.
512596Sbill 	 */
513679Shenry 	datbase = round(tsize, FW);
514596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
515679Shenry 		v = round(usedot[NLOC+locindex].e_xvalue, FW);
516631Shenry 		usedot[NLOC+locindex].e_xvalue = datbase + dsize;
517596Sbill 		if (v != 0){
518596Sbill 			usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE));
519596Sbill 			bopen(usefile[NLOC + locindex], a_out_off);
520596Sbill 		} else {
521596Sbill 			usefile[NLOC + locindex] = (BFILE *)-1;
522596Sbill 		}
523596Sbill 		dsize += v;
524596Sbill 		a_out_off += v;
525596Sbill 	}
526596Sbill 	/*
527596Sbill 	 *	Assign final values to symbols
528596Sbill 	 */
529596Sbill 	hdr.a_bss = dsize;
530596Sbill 	freezesymtab();		/* this touches hdr.a_bss */
531596Sbill 	stabfix();
532596Sbill 	/*
533596Sbill 	 *	Set up the relocation information "files" to
534596Sbill 	 *	be zero; outrel takes care of the rest
535596Sbill 	 */
536596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++){
537596Sbill 		rusefile[locindex] = (struct relbufdesc *)0;
538596Sbill 	}
539596Sbill }
540596Sbill 
541596Sbill build_hdr()
542596Sbill {
543596Sbill 	/*
544596Sbill 	 *	Except for the text and data relocation sizes,
545596Sbill 	 *	calculate the final values for the header
546596Sbill 	 *
547596Sbill 	 *	Write out the initial copy; we to come
548596Sbill 	 *	back later and patch up a_trsize and a_drsize,
549596Sbill 	 *	and overwrite this first version of the header.
550596Sbill 	 */
551596Sbill 	hdr.a_magic = MAGIC;
552596Sbill 	hdr.a_text = tsize;
553596Sbill 	hdr.a_data = dsize;
554596Sbill 	hdr.a_bss -= dsize;
555596Sbill 	hdr.a_syms = sizesymtab();	/* Does not include string pool length */
556596Sbill 	hdr.a_entry = 0;
557596Sbill 	hdr.a_trsize = 0;
558596Sbill 	hdr.a_drsize = 0;
559596Sbill 
560596Sbill 	bwrite((char *)&hdr, sizeof(hdr), usefile[0]);
561596Sbill }
562596Sbill 
563596Sbill i_pass2()
564596Sbill {
565596Sbill 	if (useVM == 0) {
56613512Srrh 		fclose(tokfile);
56713512Srrh 		tokfile = fopen(tokfilename, "r");
56813512Srrh 		if (tokfile==NULL) {
56913512Srrh 		   yyerror("Bad pass 2 temporary file for reading %s", tokfilename);
570596Sbill 		   delexit();
571596Sbill 		}
572596Sbill 	}
57313512Srrh 	fclose(strfile);
57413512Srrh 	strfile = fopen(strfilename, "r");
575596Sbill }
576596Sbill 
577596Sbill pass2()
578596Sbill {
579596Sbill #ifdef DEBUG
580596Sbill 	if (debug)
581596Sbill 		printf("\n\n\n\t\tPASS 2\n\n\n\n");
582596Sbill #endif DEBUG
583596Sbill 	passno = 2;
584596Sbill 	lineno = 1;
585596Sbill 	dotp = &usedot[0];
586596Sbill 	txtfil = usefile[0];	/* already opened (always!) */
587596Sbill 	relfil = 0;		/* outrel takes care of the rest */
588596Sbill 	initoutrel();
589596Sbill 
59013512Srrh 	inittokfile();
591596Sbill 
592596Sbill 	yyparse();
593596Sbill 
59413512Srrh 	closetokfile();
595596Sbill }
596596Sbill 
597596Sbill fillsegments()
598596Sbill {
599596Sbill 	int	locindex;
600596Sbill 	/*
601679Shenry 	 *	Round text and data segments to FW by appending zeros
602596Sbill 	 */
603596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++) {
604596Sbill 		if (usefile[locindex]) {
605596Sbill 			txtfil = usefile[locindex];
606596Sbill 			dotp = &usedot[locindex];
607679Shenry 			while (usedot[locindex].e_xvalue & FW)
608596Sbill 				outb(0);
609596Sbill 		}
610596Sbill 	}
611596Sbill }
612596Sbill 
613596Sbill reloc_syms()
614596Sbill {
615596Sbill 	u_long	closerelfil();
616596Sbill 	/*
617596Sbill 	 *	Move the relocation information to a.out
618596Sbill 	 *	a_out_off is the offset so far:
619596Sbill 	 *	exec + text segments + data segments
620596Sbill 	 */
621596Sbill 	relocfile = (BFILE *)Calloc(1,sizeof(BFILE));
622596Sbill 	bopen(relocfile, a_out_off);
623596Sbill 	a_out_off += closeoutrel(relocfile);
624596Sbill 
625596Sbill 	hdr.a_trsize = trsize;
626596Sbill 	hdr.a_drsize = drsize;
627638Sbill 	if (readonlydata) {
628638Sbill 		hdr.a_text += hdr.a_data;
629638Sbill 		hdr.a_data = 0;
630638Sbill 		hdr.a_trsize += hdr.a_drsize;
631638Sbill 		hdr.a_drsize = 0;
632638Sbill 	}
633596Sbill 	/*
634596Sbill 	 *	Output the symbol table
635596Sbill 	 *	and if FLEXNAMES is set, the string pool
63613512Srrh 	 *
63713512Srrh 	 *	We must first rewind the string pool file to its beginning,
63813512Srrh 	 *	in case it was seek'ed into for fetching ascii and asciz
63913512Srrh 	 *	strings.
640596Sbill 	 */
64113512Srrh 	fseek(strfile, 0, 0);
642596Sbill 	symwrite(relocfile);
643596Sbill }
644596Sbill 
645596Sbill fix_a_out()
646596Sbill {
6475826Srrh 	if (lseek(a_out_file->_file, 0L, 0) < 0L)
648596Sbill 		yyerror("Reposition for header rewrite fails");
649596Sbill 	if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0)
650596Sbill 		yyerror("Rewrite of header fails");
651596Sbill }
652596Sbill 
653596Sbill delexit()
654596Sbill {
655596Sbill 	delete();
656596Sbill 	if (passno == 2){
657596Sbill 		unlink(outfile);
658596Sbill 	}
659596Sbill 	exit(1);
660596Sbill }
661596Sbill 
662596Sbill delete()
663596Sbill {
66413512Srrh 	if (useVM == 0 || tokfilename[0])
66513512Srrh 		unlink(tokfilename);
66613512Srrh 	if (strfilename[0])
66713512Srrh 		unlink(strfilename);
668596Sbill }
669596Sbill 
670596Sbill sawabort()
671596Sbill {
672596Sbill 	char	*fillinbuffer();
673596Sbill 	while (fillinbuffer() != (char *)0)
674596Sbill 		continue;
675596Sbill 	delete();
676596Sbill 	exit(1);	/*although the previous pass will also exit non zero*/
677596Sbill }
678596Sbill 
679596Sbill panic(fmt, a1, a2, a3, a4)
680596Sbill 	char	*fmt;
681596Sbill 	/*VARARGS 1*/
682596Sbill {
683596Sbill 	yyerror("Assembler panic: bad internal data structure.");
684596Sbill 	yyerror(fmt, a1, a2, a3, a4);
685596Sbill 	delete();
686596Sbill 	abort();
687596Sbill }
688