xref: /csrg-svn/old/as.vax/asmain.c (revision 13512)
15826Srrh /*
25826Srrh  *	Copyright (c) 1982 Regents of the University of California
35826Srrh  */
45826Srrh #ifndef lint
5*13512Srrh static char sccsid[] = "@(#)asmain.c 4.11 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 
17596Sbill #ifdef UNIX
18*13512Srrh #define	unix_lang_name "VAX/UNIX Assembler V06/30/83 4.11"
19596Sbill #endif
20596Sbill 
21596Sbill #ifdef VMS
22631Shenry #define vms_lang_name "VAX/VMS C Assembler V1.00"
23596Sbill #endif VMS
24596Sbill 
25596Sbill /*
26596Sbill  *	variables to manage reading the assembly source files
27596Sbill  */
28596Sbill char	*dotsname;	/*the current file name; managed by the parser*/
29596Sbill int	lineno;		/*current line number; managed by the parser*/
30643Sbill char	**innames;	/*names of the files being assembled*/
31596Sbill int	ninfiles;	/*how many interesting files there are*/
32596Sbill /*
33596Sbill  *	Flags settable from the argv process argument list
34596Sbill  */
35596Sbill int	silent = 0;	/*don't complain about any errors*/
36596Sbill int	savelabels = 0;	/*write the labels to the a.out file*/
37596Sbill int 	d124 = 4;	/*default allocate 4 bytes for unknown pointers*/
38596Sbill int	anyerrs = 0;	/*no errors yet*/
395826Srrh int	anywarnings=0;	/*no warnings yet*/
40596Sbill int	orgwarn = 0;	/*Bad origins*/
41596Sbill int	passno = 1;	/* current pass*/
42636Shenry int	jxxxJUMP = 0;	/* in jxxxes that branch too far, use jmp instead of brw */
43638Sbill int	readonlydata = 0;	/* initialzed data -> text space */
44596Sbill 
455826Srrh int	nGHnumbers = 0;		/* GH numbers used */
465826Srrh int	nGHopcodes = 0;		/* GH opcodes used */
475826Srrh int	nnewopcodes = 0;	/* new opcodes used */
485826Srrh 
49596Sbill #ifdef DEBUG
50596Sbill int 	debug = 0;
51596Sbill int	toktrace = 0;
52596Sbill #endif
53596Sbill 
54596Sbill int	useVM =		/*put the temp file in virtual memory*/
55596Sbill #ifdef VMS
56596Sbill 	1;		/*VMS has virtual memory (duh)*/
57596Sbill #endif VMS
58596Sbill #ifdef UNIX
59596Sbill  	0;
60596Sbill #endif
61596Sbill 
62596Sbill char	*endcore;	/*where to get more symbol space*/
63596Sbill 
64596Sbill /*
65596Sbill  *	Managers of the a.out file.
66596Sbill  */
67596Sbill struct	exec	hdr;
68638Sbill #define	MAGIC	0407
69596Sbill u_long	tsize;		/* total text size */
70596Sbill u_long	dsize;		/* total data size */
71596Sbill u_long	datbase;	/* base of the data segment */
72596Sbill u_long	trsize;		/* total text relocation size */
73596Sbill u_long	drsize;		/* total data relocation size */
74596Sbill 
75596Sbill /*
76596Sbill  *	Information about the current segment is accumulated in
77596Sbill  *	usedot; the most important information stored is the
78596Sbill  *	accumulated size of each of the text and data segments
79596Sbill  *
80596Sbill  *	dotp points to the correct usedot expression for the current segment
81596Sbill  */
82596Sbill struct	exp	usedot[NLOC+NLOC];	/* info about all segments */
83596Sbill struct	exp	*dotp;			/* data/text location pointer */
84596Sbill /*
85*13512Srrh  *	The inter pass temporary token file is opened and closed by stdio, but
86596Sbill  *	is written to using direct read/write, as the temporary file
87596Sbill  *	is composed of buffers exactly BUFSIZ long.
88596Sbill  */
89*13512Srrh FILE	*tokfile;			/* interpass communication file */
90*13512Srrh char	tokfilename[TNAMESIZE];
91596Sbill /*
92*13512Srrh  *	The string file is the string table
93*13512Srrh  *	cat'ed to the end of the built up a.out file
94*13512Srrh  */
95*13512Srrh FILE	*strfile;			/* interpass string file */
96*13512Srrh char	strfilename[TNAMESIZE];
97*13512Srrh int	strfilepos = 0;			/* position within the string file */
98*13512Srrh /*
99596Sbill  *	a.out is created during the second pass.
100596Sbill  *	It is opened by stdio, but is filled with the parallel
101596Sbill  *	block I/O library
102596Sbill  */
103596Sbill char	*outfile = "a.out";
104596Sbill FILE	*a_out_file;
105596Sbill off_t	a_out_off;			/* cumulative offsets for segments */
106596Sbill /*
107596Sbill  *	The logical files containing the assembled data for each of
108596Sbill  *	the text and data segments are
109596Sbill  *	managed by the parallel block I/O library.
110596Sbill  *	a.out is logically opened in many places at once to
111596Sbill  *	receive the assembled data from the various segments as
112596Sbill  *	it all trickles in, but is physically opened only once
113596Sbill  *	to minimize file overhead.
114596Sbill  */
115596Sbill BFILE	*usefile[NLOC+NLOC];		/* text/data files */
116596Sbill BFILE	*txtfil;			/* current text/data file */
117596Sbill /*
118596Sbill  *	Relocation information is accumulated seperately for each
119596Sbill  *	segment.  This is required by the old loader (from BTL),
120596Sbill  *	but not by the new loader (Bill Joy).
121596Sbill  *
122596Sbill  *	However, the size of the relocation information can not be computed
123596Sbill  *	during or after the 1st pass because the ''absoluteness' of values
124596Sbill  *	is unknown until all locally declared symbols have been seen.
125596Sbill  *	Thus, the size of the relocation information is only
126596Sbill  *	known after the second pass is finished.
127596Sbill  *	This obviates the use of the block I/O
128596Sbill  *	library, which requires knowing the exact offsets in a.out.
129596Sbill  *
130596Sbill  *	So, we save the relocation information internally (we don't
131596Sbill  *	go to internal files to minimize overhead).
132596Sbill  *
133596Sbill  *	Empirically, we studied 259 files composing the system,
134596Sbill  *	two compilers and a compiler generator: (all of which have
135596Sbill  *	fairly large source files)
136596Sbill  *
137596Sbill  *	Number of files = 259
138596Sbill  *		Number of non zero text reloc files: 233
139596Sbill  *		Number of non zero data reloc files: 53
140596Sbill  *	Average text relocation = 889
141596Sbill  *	Average data relocation = 346
142596Sbill  *	Number of files > BUFSIZ text relocation = 71
143596Sbill  *	Number of files > BUFSIZ data relocation = 6
144596Sbill  *
145596Sbill  *	For compiled C code, there is usually one text segment and two
146596Sbill  *	data segments; we see that allocating our own buffers and
147596Sbill  *	doing our internal handling of relocation information will,
148596Sbill  *	on the average, not use more memory than taken up by the buffers
149596Sbill  *	allocated for doing file I/O in parallel to a number of file.
150596Sbill  *
151596Sbill  *	If we are assembling with the -V option, we
152596Sbill  *	use the left over token buffers from the 2nd pass,
153596Sbill  *	otherwise, we create our own.
154596Sbill  *
155596Sbill  *	When the 2nd pass is complete, closeoutrel flushes the token
156596Sbill  *	buffers out to a BFILE.
157596Sbill  *
158596Sbill  *	The internals to relbufdesc are known only in assyms.c
159596Sbill  *
160596Sbill  *	outrel constructs the relocation information.
161596Sbill  *	closeoutrel flushes the relocation information to relfil.
162596Sbill  */
163596Sbill struct	relbufdesc	*rusefile[NLOC+NLOC];
164596Sbill struct	relbufdesc 	*relfil;	/* un concatnated relocation info */
165596Sbill BFILE	*relocfile;			/* concatnated relocation info */
166596Sbill /*
167596Sbill  *	Once the relocation information has been written,
168596Sbill  *	we can write out the symbol table using the Block I/O
169596Sbill  *	mechanisms, as we once again know the offsets into
170596Sbill  *	the a.out file.
171596Sbill  *
172596Sbill  *	We use relfil to output the symbol table information.
173596Sbill  */
174596Sbill 
175596Sbill char	*tmpdirprefix =
176596Sbill #ifdef UNIX
177596Sbill 			"/tmp/";
178596Sbill #else VMS
179596Sbill 			"/usr/tmp/";
180596Sbill #endif
181596Sbill 
182596Sbill 
183596Sbill int delexit();
184596Sbill 
185596Sbill main(argc, argv)
186596Sbill 	int	argc;
187596Sbill 	char 	**argv;
188596Sbill {
1895826Srrh 	char	*sbrk();
190596Sbill 
191*13512Srrh 	tokfilename[0] = 0;
192*13512Srrh 	strfilename[0] = 0;
1935826Srrh 	endcore = sbrk(0);
194596Sbill 
195596Sbill 	argprocess(argc, argv);		/* process argument lists */
196596Sbill 	if (anyerrs) exit(1);
197596Sbill 
198596Sbill 	initialize();
199596Sbill 	zeroorigins();			/* set origins to zero */
200596Sbill 	zerolocals();			/* fix local label counters */
201596Sbill 
202596Sbill 	i_pass1();			/* open temp files, etc */
203596Sbill 	pass1();			/* first pass through .s files */
204596Sbill 	testlocals();			/* check for undefined locals */
205596Sbill 	if (anyerrs) delexit();
206596Sbill 
207596Sbill 	pass1_5();			/* resolve jxxx */
208596Sbill 	if (anyerrs) delexit();
209596Sbill 
210596Sbill 	open_a_out();			/* open a.out */
211679Shenry 	roundsegments();		/* round segments to FW */
212596Sbill 	build_hdr();			/* build initial header, and output */
213596Sbill 
214596Sbill 	i_pass2();			/* reopen temporary file, etc */
215596Sbill 	pass2();			/* second pass through the virtual .s */
216596Sbill 	if (anyerrs) delexit();
217596Sbill 
218679Shenry 	fillsegments();			/* fill segments with 0 to FW */
219596Sbill 	reloc_syms();			/* dump relocation and symbol table */
220596Sbill 
221596Sbill 	delete();			/* remove tmp file */
222596Sbill 	bflush();			/* close off block I/O view of a.out */
223596Sbill 	fix_a_out();			/* add in text and data reloc counts */
224596Sbill 
225596Sbill 	if (anyerrs == 0 && orgwarn)
226596Sbill 		yyerror("Caution: absolute origins.\n");
2275826Srrh 
2285826Srrh 	if (nGHnumbers)
2295826Srrh 		yywarning("Caution: G or H format floating point numbers");
2305826Srrh 	if (nGHopcodes)
2315826Srrh 		yywarning("Caution: G or H format floating point operators");
2325826Srrh 	if (nnewopcodes)
2335826Srrh 		yywarning("Caution: New Opcodes");
2345826Srrh 	if (nGHnumbers || nGHopcodes || nnewopcodes)
2355826Srrh 		yywarning("These are not defined for all implementations of the VAX architecture.\n");
2365826Srrh 
237596Sbill 	exit(anyerrs != 0);
238596Sbill }	/*end of UNIX main*/
239596Sbill 
240596Sbill argprocess(argc, argv)
241596Sbill 	int	argc;
242596Sbill 	char	*argv[];
243596Sbill {
244596Sbill 	register	char	*cp;
245596Sbill 
246596Sbill 	ninfiles = 0;
247596Sbill 	silent = 0;
248596Sbill #ifdef DEBUG
249596Sbill 	debug = 0;
250596Sbill #endif
251643Sbill 	innames = (char **)ClearCalloc(argc+1, sizeof (innames[0]));
252596Sbill 	dotsname = "<argv error>";
253596Sbill 	while (argc > 1) {
254643Sbill 		if (argv[1][0] != '-')
255643Sbill 			innames[ninfiles++] = argv[1];
256643Sbill 		else {
257596Sbill 			cp = argv[1] + 1;
258596Sbill 			/*
259596Sbill 			 *	We can throw away single minus signs, so
260596Sbill 			 *	that make scripts for the PDP 11 assembler work
261596Sbill 			 *	on this assembler too
262596Sbill 			 */
263596Sbill 			while (*cp){
264596Sbill 				switch(*cp++){
265596Sbill 				 default:
266596Sbill 					yyerror("Unknown flag: %c", *--cp);
267596Sbill 					cp++;
268596Sbill 					break;
2696559Srrh 				 case 'v':
2706559Srrh 					selfwhat(stdout);
2716559Srrh 					exit(1);
272596Sbill 				 case 'd':
273596Sbill 					d124 = *cp++ - '0';
274596Sbill 					if ( (d124 != 1) && (d124 != 2) &&
275596Sbill 					     (d124 != 4)){
276596Sbill 						yyerror("-d[124] only");
277596Sbill 						exit(1);
278596Sbill 					}
279596Sbill 					break;
280596Sbill 				 case 'o':
281596Sbill 					if (argc < 3){
282596Sbill 						yyerror("-o what???");
283596Sbill 						exit(1);
284596Sbill 					}
285596Sbill 					outfile = argv[2];
286596Sbill 				   bumpone:
287596Sbill 					argc -= 2;
288596Sbill 					argv += 2;
289596Sbill 					goto nextarg;
290596Sbill 
291596Sbill 				 case 't':
292596Sbill 					if (argc < 3){
293596Sbill 						yyerror("-t what???");
294596Sbill 						exit(1);
295596Sbill 					}
296596Sbill 					tmpdirprefix = argv[2];
297596Sbill 					goto bumpone;
298596Sbill 
299596Sbill 				 case 'V':
300596Sbill 					useVM = 1;
301596Sbill 					break;
302596Sbill 				 case 'W':
303596Sbill 					silent = 1;
304596Sbill 					break;
305596Sbill 				 case 'L':
306596Sbill 					savelabels = 1;
307596Sbill 					break;
308636Shenry 				 case 'J':
309636Shenry 					jxxxJUMP = 1;
310636Shenry 					break;
311596Sbill #ifdef DEBUG
312596Sbill 				 case 'D':
313596Sbill 					debug = 1;
314596Sbill 					break;
315596Sbill 				 case 'T':
316596Sbill 					toktrace = 1;
317596Sbill 					break;
318596Sbill #endif
319638Sbill 				 case 'R':
320638Sbill 					readonlydata = 1;
321638Sbill 					break;
322596Sbill 				}	/*end of the switch*/
323596Sbill 			}	/*end of pulling out all arguments*/
324596Sbill 		}	/*end of a flag argument*/
325596Sbill 		--argc; ++argv;
326596Sbill 	   nextarg:;
327596Sbill 	}
328643Sbill 	/* innames[ninfiles] = 0; */
329596Sbill }
3306559Srrh /*
3316559Srrh  *	poke through the data space and find all sccs identifiers.
3326559Srrh  *	We assume:
3336559Srrh  *	a) that extern char **environ; is the first thing in the bss
3346559Srrh  *	segment (true, if one is using the new version of cmgt.crt0.c)
3356559Srrh  *	b) that the sccsid's have not been put into text space.
3366559Srrh  */
3376559Srrh selfwhat(place)
3386559Srrh 	FILE	*place;
3396559Srrh {
3406559Srrh 	extern	char **environ;
3416559Srrh 	register	char	*ub;
3426559Srrh 	register	char *cp;
3436559Srrh 	register	char	*pat;
3446559Srrh 	char	*sbrk();
345596Sbill 
3466559Srrh 	for (cp = (char *)&environ, ub = sbrk(0); cp < ub; cp++){
3476559Srrh 		if (cp[0] != '@') continue;
3486559Srrh 		if (cp[1] != '(') continue;
3496559Srrh 		if (cp[2] != '#') continue;
3506559Srrh 		if (cp[3] != ')') continue;
3516559Srrh 		fputc('\t', place);
3526559Srrh 		for (cp += 4; cp < ub; cp++){
3536559Srrh 			if (*cp == 0) break;
3546559Srrh 			if (*cp == '>') break;
3556559Srrh 			if (*cp == '\n') break;
3566559Srrh 			fputc(*cp, place);
3576559Srrh 		}
3586559Srrh 		fputc('\n', place);
3596559Srrh 	}
3606559Srrh }
3616559Srrh 
362596Sbill initialize()
363596Sbill {
364596Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
365596Sbill 		signal(SIGINT, delexit);
366596Sbill 	/*
367596Sbill 	 *	Install symbols in the table
368596Sbill 	 */
369596Sbill 	symtabinit();
370596Sbill 	syminstall();
371596Sbill 	/*
372596Sbill 	 *	Build the expression parser accelerator token sets
373596Sbill 	 */
374596Sbill 	buildtokensets();
375596Sbill }
376596Sbill 
377596Sbill zeroorigins()
378596Sbill {
379596Sbill 	register	int	locindex;
380596Sbill 	/*
381596Sbill 	 *	Mark usedot: the first NLOC slots are for named text segments,
382596Sbill 	 *	the next for named data segments.
383596Sbill 	 */
384596Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
385631Shenry 		usedot[locindex].e_xtype = XTEXT;
386631Shenry 		usedot[NLOC + locindex].e_xtype = XDATA;
387631Shenry 		usedot[locindex].e_xvalue = 0;
388631Shenry 		usedot[NLOC + locindex].e_xvalue = 0;
389596Sbill 	}
390596Sbill }
391596Sbill 
392596Sbill zerolocals()
393596Sbill {
394596Sbill 	register	int	i;
395596Sbill 
396596Sbill 	for (i = 0; i <= 9; i++) {
397596Sbill 		lgensym[i] = 1;
398596Sbill 		genref[i] = 0;
399596Sbill 	}
400596Sbill }
401596Sbill 
402596Sbill i_pass1()
403596Sbill {
404*13512Srrh 	FILE	*tempopen();
405*13512Srrh 	if (useVM == 0)
406*13512Srrh 		tokfile = tempopen(tokfilename, "T");
407*13512Srrh 	strfile = tempopen(strfilename, "S");
408*13512Srrh 	/*
409*13512Srrh 	 *	write out the string length.
410*13512Srrh 	 *	This will be overwritten when the
411*13512Srrh 	 *	strings are tacked onto the growing a.out file
412*13512Srrh 	 */
413*13512Srrh 	strfilepos = sizeof(int);
414*13512Srrh 	fwrite(&strfilepos, sizeof(int), 1, strfile);
415596Sbill 
416*13512Srrh 	inittokfile();
417636Shenry 	initijxxx();
418596Sbill }
419596Sbill 
420*13512Srrh FILE *tempopen(tname, part)
421*13512Srrh 	char	*tname;
422*13512Srrh 	char	*part;
423*13512Srrh {
424*13512Srrh 	FILE	*file;
425*13512Srrh 	sprintf(tname, "%s%sas%s%05d",
426*13512Srrh 		tmpdirprefix,
427*13512Srrh 		(tmpdirprefix[strlen(tmpdirprefix)-1] != '/') ? "/" : 0,
428*13512Srrh 		part,
429*13512Srrh 		getpid());
430*13512Srrh 	file = fopen(tname, "w");
431*13512Srrh 	if (file == NULL) {
432*13512Srrh 		yyerror("Bad pass 1 temporary file for writing %s", tname);
433*13512Srrh 		delexit();
434*13512Srrh 	}
435*13512Srrh 	return(file);
436*13512Srrh }
437*13512Srrh 
438596Sbill pass1()
439596Sbill {
440596Sbill 	register	int	i;
441596Sbill 
442596Sbill 	passno = 1;
443596Sbill 	dotp = &usedot[0];
444596Sbill 	txtfil = (BFILE *)0;
445596Sbill 	relfil = (struct relbufdesc *)0;
446596Sbill 
447596Sbill 	if (ninfiles == 0){		/*take the input from stdin directly*/
448596Sbill 		lineno = 1;
449596Sbill 		dotsname = "<stdin>";
450596Sbill 
451596Sbill 		yyparse();
452596Sbill 	} else {		/*we have the names tanked*/
453596Sbill 		for (i = 0; i < ninfiles; i++){
454596Sbill 			new_dot_s(innames[i]);
455596Sbill 			if (freopen(innames[i], "r", stdin) == NULL) {
456596Sbill 				yyerror( "Can't open source file %s\n",
457596Sbill 					innames[i]);
458596Sbill 				exit(2);
459596Sbill 			}
460596Sbill 			/* stdio is NOT used to read the input characters */
461596Sbill 			/* we use read directly, into our own buffers */
462596Sbill 			yyparse();
463596Sbill 		}
464596Sbill 	}
465596Sbill 
466*13512Srrh 	closetokfile();		/*kick out the last buffered intermediate text*/
467596Sbill }
468596Sbill 
469596Sbill testlocals()
470596Sbill {
471596Sbill 	register	int	i;
472596Sbill 	for (i = 0; i <= 9; i++) {
473596Sbill 		if (genref[i])
474596Sbill 			yyerror("Reference to undefined local label %df", i);
475596Sbill 		lgensym[i] = 1;
476596Sbill 		genref[i] = 0;
477596Sbill 	}
478596Sbill }
479596Sbill 
480596Sbill pass1_5()
481596Sbill {
482596Sbill 	sortsymtab();
483596Sbill #ifdef DEBUG
484596Sbill 	if (debug) dumpsymtab();
485596Sbill #endif
486596Sbill 	jxxxfix();
487596Sbill #ifdef DEBUG
488596Sbill 	if (debug) dumpsymtab();
489596Sbill #endif
490596Sbill }
491596Sbill 
492596Sbill open_a_out()
493596Sbill {
494596Sbill 	/*
495596Sbill 	 *	Open up the a.out file now, and get set to build
496596Sbill 	 *	up offsets into it for all of the various text,data
497596Sbill 	 *	text relocation and data relocation segments.
498596Sbill 	 */
499596Sbill 	a_out_file = fopen(outfile, "w");
500596Sbill 	if (a_out_file == NULL) {
501596Sbill 		yyerror("Cannot create %s", outfile);
502596Sbill 		delexit();
503596Sbill 	}
504596Sbill 	biofd = a_out_file->_file;
505596Sbill 	a_out_off = 0;
506596Sbill }
507596Sbill 
508596Sbill roundsegments()
509596Sbill {
510596Sbill 	register	int	locindex;
511596Sbill 	register	long	v;
512596Sbill 	/*
513596Sbill 	 *	round and assign text segment origins
514596Sbill 	 *	the exec header always goes in usefile[0]
515596Sbill 	 */
516596Sbill 	tsize = 0;
517596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
518679Shenry 		v = round(usedot[locindex].e_xvalue, FW);
519631Shenry 		usedot[locindex].e_xvalue = tsize;
520596Sbill 		if ((locindex == 0) || (v != 0) ){
521596Sbill 			usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE));
522596Sbill 			bopen(usefile[locindex], a_out_off);
523596Sbill 			if (locindex == 0)
524596Sbill 				a_out_off = sizeof (struct exec);
525596Sbill 		} else {
526596Sbill 			usefile[locindex] = (BFILE *)-1;
527596Sbill 		}
528596Sbill 		tsize += v;
529596Sbill 		a_out_off += v;
530596Sbill 	}
531596Sbill 	/*
532596Sbill 	 *		Round and assign data segment origins.
533596Sbill 	 */
534679Shenry 	datbase = round(tsize, FW);
535596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
536679Shenry 		v = round(usedot[NLOC+locindex].e_xvalue, FW);
537631Shenry 		usedot[NLOC+locindex].e_xvalue = datbase + dsize;
538596Sbill 		if (v != 0){
539596Sbill 			usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE));
540596Sbill 			bopen(usefile[NLOC + locindex], a_out_off);
541596Sbill 		} else {
542596Sbill 			usefile[NLOC + locindex] = (BFILE *)-1;
543596Sbill 		}
544596Sbill 		dsize += v;
545596Sbill 		a_out_off += v;
546596Sbill 	}
547596Sbill 	/*
548596Sbill 	 *	Assign final values to symbols
549596Sbill 	 */
550596Sbill 	hdr.a_bss = dsize;
551596Sbill 	freezesymtab();		/* this touches hdr.a_bss */
552596Sbill 	stabfix();
553596Sbill 	/*
554596Sbill 	 *	Set up the relocation information "files" to
555596Sbill 	 *	be zero; outrel takes care of the rest
556596Sbill 	 */
557596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++){
558596Sbill 		rusefile[locindex] = (struct relbufdesc *)0;
559596Sbill 	}
560596Sbill }
561596Sbill 
562596Sbill build_hdr()
563596Sbill {
564596Sbill 	/*
565596Sbill 	 *	Except for the text and data relocation sizes,
566596Sbill 	 *	calculate the final values for the header
567596Sbill 	 *
568596Sbill 	 *	Write out the initial copy; we to come
569596Sbill 	 *	back later and patch up a_trsize and a_drsize,
570596Sbill 	 *	and overwrite this first version of the header.
571596Sbill 	 */
572596Sbill 	hdr.a_magic = MAGIC;
573596Sbill 	hdr.a_text = tsize;
574596Sbill 	hdr.a_data = dsize;
575596Sbill 	hdr.a_bss -= dsize;
576596Sbill 	hdr.a_syms = sizesymtab();	/* Does not include string pool length */
577596Sbill 	hdr.a_entry = 0;
578596Sbill 	hdr.a_trsize = 0;
579596Sbill 	hdr.a_drsize = 0;
580596Sbill 
581596Sbill 	bwrite((char *)&hdr, sizeof(hdr), usefile[0]);
582596Sbill }
583596Sbill 
584596Sbill i_pass2()
585596Sbill {
586596Sbill 	if (useVM == 0) {
587*13512Srrh 		fclose(tokfile);
588*13512Srrh 		tokfile = fopen(tokfilename, "r");
589*13512Srrh 		if (tokfile==NULL) {
590*13512Srrh 		   yyerror("Bad pass 2 temporary file for reading %s", tokfilename);
591596Sbill 		   delexit();
592596Sbill 		}
593596Sbill 	}
594*13512Srrh 	fclose(strfile);
595*13512Srrh 	strfile = fopen(strfilename, "r");
596596Sbill }
597596Sbill 
598596Sbill pass2()
599596Sbill {
600596Sbill #ifdef DEBUG
601596Sbill 	if (debug)
602596Sbill 		printf("\n\n\n\t\tPASS 2\n\n\n\n");
603596Sbill #endif DEBUG
604596Sbill 	passno = 2;
605596Sbill 	lineno = 1;
606596Sbill 	dotp = &usedot[0];
607596Sbill 	txtfil = usefile[0];	/* already opened (always!) */
608596Sbill 	relfil = 0;		/* outrel takes care of the rest */
609596Sbill 	initoutrel();
610596Sbill 
611*13512Srrh 	inittokfile();
612596Sbill 
613596Sbill 	yyparse();
614596Sbill 
615*13512Srrh 	closetokfile();
616596Sbill }
617596Sbill 
618596Sbill fillsegments()
619596Sbill {
620596Sbill 	int	locindex;
621596Sbill 	/*
622679Shenry 	 *	Round text and data segments to FW by appending zeros
623596Sbill 	 */
624596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++) {
625596Sbill 		if (usefile[locindex]) {
626596Sbill 			txtfil = usefile[locindex];
627596Sbill 			dotp = &usedot[locindex];
628679Shenry 			while (usedot[locindex].e_xvalue & FW)
629596Sbill 				outb(0);
630596Sbill 		}
631596Sbill 	}
632596Sbill }
633596Sbill 
634596Sbill reloc_syms()
635596Sbill {
636596Sbill 	u_long	closerelfil();
637596Sbill 	/*
638596Sbill 	 *	Move the relocation information to a.out
639596Sbill 	 *	a_out_off is the offset so far:
640596Sbill 	 *	exec + text segments + data segments
641596Sbill 	 */
642596Sbill 	relocfile = (BFILE *)Calloc(1,sizeof(BFILE));
643596Sbill 	bopen(relocfile, a_out_off);
644596Sbill 	a_out_off += closeoutrel(relocfile);
645596Sbill 
646596Sbill 	hdr.a_trsize = trsize;
647596Sbill 	hdr.a_drsize = drsize;
648638Sbill 	if (readonlydata) {
649638Sbill 		hdr.a_text += hdr.a_data;
650638Sbill 		hdr.a_data = 0;
651638Sbill 		hdr.a_trsize += hdr.a_drsize;
652638Sbill 		hdr.a_drsize = 0;
653638Sbill 	}
654596Sbill 	/*
655596Sbill 	 *	Output the symbol table
656596Sbill 	 *	and if FLEXNAMES is set, the string pool
657*13512Srrh 	 *
658*13512Srrh 	 *	We must first rewind the string pool file to its beginning,
659*13512Srrh 	 *	in case it was seek'ed into for fetching ascii and asciz
660*13512Srrh 	 *	strings.
661596Sbill 	 */
662*13512Srrh 	fseek(strfile, 0, 0);
663596Sbill 	symwrite(relocfile);
664596Sbill }
665596Sbill 
666596Sbill fix_a_out()
667596Sbill {
6685826Srrh 	if (lseek(a_out_file->_file, 0L, 0) < 0L)
669596Sbill 		yyerror("Reposition for header rewrite fails");
670596Sbill 	if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0)
671596Sbill 		yyerror("Rewrite of header fails");
672596Sbill }
673596Sbill 
674596Sbill delexit()
675596Sbill {
676596Sbill 	delete();
677596Sbill 	if (passno == 2){
678596Sbill 		unlink(outfile);
679596Sbill 	}
680596Sbill 	exit(1);
681596Sbill }
682596Sbill 
683596Sbill delete()
684596Sbill {
685*13512Srrh 	if (useVM == 0 || tokfilename[0])
686*13512Srrh 		unlink(tokfilename);
687*13512Srrh 	if (strfilename[0])
688*13512Srrh 		unlink(strfilename);
689596Sbill }
690596Sbill 
691596Sbill sawabort()
692596Sbill {
693596Sbill 	char	*fillinbuffer();
694596Sbill 	while (fillinbuffer() != (char *)0)
695596Sbill 		continue;
696596Sbill 	delete();
697596Sbill 	exit(1);	/*although the previous pass will also exit non zero*/
698596Sbill }
699596Sbill 
700596Sbill panic(fmt, a1, a2, a3, a4)
701596Sbill 	char	*fmt;
702596Sbill 	/*VARARGS 1*/
703596Sbill {
704596Sbill 	yyerror("Assembler panic: bad internal data structure.");
705596Sbill 	yyerror(fmt, a1, a2, a3, a4);
706596Sbill 	delete();
707596Sbill 	abort();
708596Sbill }
709