xref: /csrg-svn/old/as.vax/asmain.c (revision 44770)
15826Srrh /*
218689Sdist  * Copyright (c) 1982 Regents of the University of California.
318689Sdist  * All rights reserved.  The Berkeley software License Agreement
418689Sdist  * specifies the terms and conditions for redistribution.
55826Srrh  */
618689Sdist 
75826Srrh #ifndef lint
818689Sdist char copyright[] =
918689Sdist "@(#) Copyright (c) 1982 Regents of the University of California.\n\
1018689Sdist  All rights reserved.\n";
115826Srrh #endif not lint
125826Srrh 
1318689Sdist #ifndef lint
14*44770Sbostic static char sccsid[] = "@(#)asmain.c	5.6 (Berkeley) 06/30/90";
1518689Sdist #endif not lint
1618689Sdist 
17596Sbill #include <stdio.h>
18596Sbill #include <ctype.h>
19596Sbill #include <signal.h>
20596Sbill 
21596Sbill #include "as.h"
22596Sbill #include "assyms.h"
235826Srrh #include "asscan.h"
24596Sbill #include "asexpr.h"
2537786Sbostic #include <paths.h>
26596Sbill 
2716071Sralph #include <sys/stat.h>
2816071Sralph 
29*44770Sbostic #define	unix_lang_name "VAX/UNIX Assembler V06/30/90 5.6"
30596Sbill /*
31596Sbill  *	variables to manage reading the assembly source files
32596Sbill  */
33596Sbill char	*dotsname;	/*the current file name; managed by the parser*/
34596Sbill int	lineno;		/*current line number; managed by the parser*/
35643Sbill char	**innames;	/*names of the files being assembled*/
36596Sbill int	ninfiles;	/*how many interesting files there are*/
37596Sbill /*
38596Sbill  *	Flags settable from the argv process argument list
39596Sbill  */
40596Sbill int	silent = 0;	/*don't complain about any errors*/
41596Sbill int	savelabels = 0;	/*write the labels to the a.out file*/
42596Sbill int 	d124 = 4;	/*default allocate 4 bytes for unknown pointers*/
4315560Srrh int 	maxalign = 2;	/*default .align maximum*/
44596Sbill int	anyerrs = 0;	/*no errors yet*/
455826Srrh int	anywarnings=0;	/*no warnings yet*/
46596Sbill int	orgwarn = 0;	/*Bad origins*/
47596Sbill int	passno = 1;	/* current pass*/
48636Shenry int	jxxxJUMP = 0;	/* in jxxxes that branch too far, use jmp instead of brw */
49638Sbill int	readonlydata = 0;	/* initialzed data -> text space */
50596Sbill 
515826Srrh int	nGHnumbers = 0;		/* GH numbers used */
525826Srrh int	nGHopcodes = 0;		/* GH opcodes used */
535826Srrh int	nnewopcodes = 0;	/* new opcodes used */
545826Srrh 
55596Sbill #ifdef DEBUG
56596Sbill int 	debug = 0;
57596Sbill int	toktrace = 0;
58596Sbill #endif
59596Sbill 
6013518Srrh int	useVM =	0;
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 /*
8513512Srrh  *	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  */
8913512Srrh FILE	*tokfile;			/* interpass communication file */
9013512Srrh char	tokfilename[TNAMESIZE];
91596Sbill /*
9213512Srrh  *	The string file is the string table
9313512Srrh  *	cat'ed to the end of the built up a.out file
9413512Srrh  */
9513512Srrh FILE	*strfile;			/* interpass string file */
9613512Srrh char	strfilename[TNAMESIZE];
9713512Srrh int	strfilepos = 0;			/* position within the string file */
9813512Srrh /*
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  */
103*44770Sbostic 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  */
17413518Srrh char	*tmpdirprefix = "/tmp/";
175596Sbill int delexit();
176596Sbill 
main(argc,argv)177596Sbill main(argc, argv)
178596Sbill 	int	argc;
179596Sbill 	char 	**argv;
180596Sbill {
1815826Srrh 	char	*sbrk();
182596Sbill 
18313512Srrh 	tokfilename[0] = 0;
18413512Srrh 	strfilename[0] = 0;
1855826Srrh 	endcore = sbrk(0);
186596Sbill 
187596Sbill 	argprocess(argc, argv);		/* process argument lists */
188596Sbill 	if (anyerrs) exit(1);
189596Sbill 
190596Sbill 	initialize();
191596Sbill 	zeroorigins();			/* set origins to zero */
192596Sbill 	zerolocals();			/* fix local label counters */
193596Sbill 
194596Sbill 	i_pass1();			/* open temp files, etc */
195596Sbill 	pass1();			/* first pass through .s files */
196596Sbill 	testlocals();			/* check for undefined locals */
197596Sbill 	if (anyerrs) delexit();
198596Sbill 
199596Sbill 	pass1_5();			/* resolve jxxx */
200596Sbill 	if (anyerrs) delexit();
201596Sbill 
202596Sbill 	open_a_out();			/* open a.out */
203679Shenry 	roundsegments();		/* round segments to FW */
204596Sbill 	build_hdr();			/* build initial header, and output */
205596Sbill 
206596Sbill 	i_pass2();			/* reopen temporary file, etc */
207596Sbill 	pass2();			/* second pass through the virtual .s */
208596Sbill 	if (anyerrs) delexit();
209596Sbill 
210679Shenry 	fillsegments();			/* fill segments with 0 to FW */
211596Sbill 	reloc_syms();			/* dump relocation and symbol table */
212596Sbill 
213596Sbill 	delete();			/* remove tmp file */
214596Sbill 	bflush();			/* close off block I/O view of a.out */
215596Sbill 	fix_a_out();			/* add in text and data reloc counts */
216596Sbill 
217596Sbill 	if (anyerrs == 0 && orgwarn)
218596Sbill 		yyerror("Caution: absolute origins.\n");
2195826Srrh 
2205826Srrh 	if (nGHnumbers)
2215826Srrh 		yywarning("Caution: G or H format floating point numbers");
2225826Srrh 	if (nGHopcodes)
2235826Srrh 		yywarning("Caution: G or H format floating point operators");
2245826Srrh 	if (nnewopcodes)
2255826Srrh 		yywarning("Caution: New Opcodes");
2265826Srrh 	if (nGHnumbers || nGHopcodes || nnewopcodes)
2275826Srrh 		yywarning("These are not defined for all implementations of the VAX architecture.\n");
2285826Srrh 
229596Sbill 	exit(anyerrs != 0);
23013518Srrh }
231596Sbill 
argprocess(argc,argv)232596Sbill argprocess(argc, argv)
233596Sbill 	int	argc;
234596Sbill 	char	*argv[];
235596Sbill {
236596Sbill 	register	char	*cp;
237596Sbill 
238596Sbill 	ninfiles = 0;
239596Sbill 	silent = 0;
240596Sbill #ifdef DEBUG
241596Sbill 	debug = 0;
242596Sbill #endif
243643Sbill 	innames = (char **)ClearCalloc(argc+1, sizeof (innames[0]));
244596Sbill 	dotsname = "<argv error>";
245596Sbill 	while (argc > 1) {
246643Sbill 		if (argv[1][0] != '-')
247643Sbill 			innames[ninfiles++] = argv[1];
248643Sbill 		else {
249596Sbill 			cp = argv[1] + 1;
250596Sbill 			/*
251596Sbill 			 *	We can throw away single minus signs, so
252596Sbill 			 *	that make scripts for the PDP 11 assembler work
253596Sbill 			 *	on this assembler too
254596Sbill 			 */
255596Sbill 			while (*cp){
256596Sbill 				switch(*cp++){
257596Sbill 				 default:
258596Sbill 					yyerror("Unknown flag: %c", *--cp);
259596Sbill 					cp++;
260596Sbill 					break;
2616559Srrh 				 case 'v':
2626559Srrh 					selfwhat(stdout);
2636559Srrh 					exit(1);
264596Sbill 				 case 'd':
265596Sbill 					d124 = *cp++ - '0';
266596Sbill 					if ( (d124 != 1) && (d124 != 2) &&
267596Sbill 					     (d124 != 4)){
268596Sbill 						yyerror("-d[124] only");
269596Sbill 						exit(1);
270596Sbill 					}
271596Sbill 					break;
27215560Srrh 				 case 'a':
27315560Srrh 					maxalign = atoi(cp+1);
27415560Srrh 					for (cp++; isdigit(*cp); cp++)
27515560Srrh 						/*VOID*/;
27615560Srrh 					if ( (maxalign > 16) || (maxalign < 0)){
27715560Srrh 						yyerror("-a: 0<=align<=16");
27815560Srrh 						exit(1);
27915560Srrh 					}
28015560Srrh 					break;
281596Sbill 				 case 'o':
282596Sbill 					if (argc < 3){
283596Sbill 						yyerror("-o what???");
284596Sbill 						exit(1);
285596Sbill 					}
286*44770Sbostic 					outfile = argv[2];
287596Sbill 				   bumpone:
288596Sbill 					argc -= 2;
289596Sbill 					argv += 2;
290596Sbill 					goto nextarg;
291596Sbill 
292596Sbill 				 case 't':
293596Sbill 					if (argc < 3){
294596Sbill 						yyerror("-t what???");
295596Sbill 						exit(1);
296596Sbill 					}
297596Sbill 					tmpdirprefix = argv[2];
298596Sbill 					goto bumpone;
299596Sbill 
300596Sbill 				 case 'V':
301596Sbill 					useVM = 1;
302596Sbill 					break;
303596Sbill 				 case 'W':
304596Sbill 					silent = 1;
305596Sbill 					break;
306596Sbill 				 case 'L':
307596Sbill 					savelabels = 1;
308596Sbill 					break;
309636Shenry 				 case 'J':
310636Shenry 					jxxxJUMP = 1;
311636Shenry 					break;
312596Sbill #ifdef DEBUG
313596Sbill 				 case 'D':
314596Sbill 					debug = 1;
315596Sbill 					break;
316596Sbill 				 case 'T':
317596Sbill 					toktrace = 1;
318596Sbill 					break;
319596Sbill #endif
320638Sbill 				 case 'R':
321638Sbill 					readonlydata = 1;
322638Sbill 					break;
323596Sbill 				}	/*end of the switch*/
324596Sbill 			}	/*end of pulling out all arguments*/
325596Sbill 		}	/*end of a flag argument*/
326596Sbill 		--argc; ++argv;
327596Sbill 	   nextarg:;
328596Sbill 	}
329643Sbill 	/* innames[ninfiles] = 0; */
330596Sbill }
3316559Srrh /*
3326559Srrh  *	poke through the data space and find all sccs identifiers.
3336559Srrh  *	We assume:
3346559Srrh  *	a) that extern char **environ; is the first thing in the bss
3356559Srrh  *	segment (true, if one is using the new version of cmgt.crt0.c)
3366559Srrh  *	b) that the sccsid's have not been put into text space.
3376559Srrh  */
selfwhat(place)3386559Srrh selfwhat(place)
3396559Srrh 	FILE	*place;
3406559Srrh {
3416559Srrh 	extern	char **environ;
3426559Srrh 	register	char	*ub;
3436559Srrh 	register	char *cp;
3446559Srrh 	register	char	*pat;
3456559Srrh 	char	*sbrk();
346596Sbill 
3476559Srrh 	for (cp = (char *)&environ, ub = sbrk(0); cp < ub; cp++){
3486559Srrh 		if (cp[0] != '@') continue;
3496559Srrh 		if (cp[1] != '(') continue;
3506559Srrh 		if (cp[2] != '#') continue;
3516559Srrh 		if (cp[3] != ')') continue;
3526559Srrh 		fputc('\t', place);
3536559Srrh 		for (cp += 4; cp < ub; cp++){
3546559Srrh 			if (*cp == 0) break;
3556559Srrh 			if (*cp == '>') break;
3566559Srrh 			if (*cp == '\n') break;
3576559Srrh 			fputc(*cp, place);
3586559Srrh 		}
3596559Srrh 		fputc('\n', place);
3606559Srrh 	}
3616559Srrh }
3626559Srrh 
initialize()363596Sbill initialize()
364596Sbill {
365596Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
366596Sbill 		signal(SIGINT, delexit);
367596Sbill 	/*
368596Sbill 	 *	Install symbols in the table
369596Sbill 	 */
370596Sbill 	symtabinit();
371596Sbill 	syminstall();
372596Sbill 	/*
373596Sbill 	 *	Build the expression parser accelerator token sets
374596Sbill 	 */
375596Sbill 	buildtokensets();
376596Sbill }
377596Sbill 
zeroorigins()378596Sbill zeroorigins()
379596Sbill {
380596Sbill 	register	int	locindex;
381596Sbill 	/*
382596Sbill 	 *	Mark usedot: the first NLOC slots are for named text segments,
383596Sbill 	 *	the next for named data segments.
384596Sbill 	 */
385596Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
386631Shenry 		usedot[locindex].e_xtype = XTEXT;
387631Shenry 		usedot[NLOC + locindex].e_xtype = XDATA;
388631Shenry 		usedot[locindex].e_xvalue = 0;
389631Shenry 		usedot[NLOC + locindex].e_xvalue = 0;
390596Sbill 	}
391596Sbill }
392596Sbill 
zerolocals()393596Sbill zerolocals()
394596Sbill {
395596Sbill 	register	int	i;
396596Sbill 
397596Sbill 	for (i = 0; i <= 9; i++) {
398596Sbill 		lgensym[i] = 1;
399596Sbill 		genref[i] = 0;
400596Sbill 	}
401596Sbill }
402596Sbill 
i_pass1()403596Sbill i_pass1()
404596Sbill {
40513512Srrh 	FILE	*tempopen();
40613512Srrh 	if (useVM == 0)
40713512Srrh 		tokfile = tempopen(tokfilename, "T");
40813512Srrh 	strfile = tempopen(strfilename, "S");
40913512Srrh 	/*
41013512Srrh 	 *	write out the string length.
41113512Srrh 	 *	This will be overwritten when the
41213512Srrh 	 *	strings are tacked onto the growing a.out file
41313512Srrh 	 */
41413512Srrh 	strfilepos = sizeof(int);
41513512Srrh 	fwrite(&strfilepos, sizeof(int), 1, strfile);
416596Sbill 
41713512Srrh 	inittokfile();
418636Shenry 	initijxxx();
419596Sbill }
420596Sbill 
tempopen(tname,part)42113512Srrh FILE *tempopen(tname, part)
42213512Srrh 	char	*tname;
42313512Srrh 	char	*part;
42413512Srrh {
42513512Srrh 	FILE	*file;
42632431Sbostic 	(void)sprintf(tname, "%s%sas%s%05d",
42713512Srrh 		tmpdirprefix,
42825246Smckusick 		(tmpdirprefix[strlen(tmpdirprefix)-1] != '/') ? "/" : "",
42913512Srrh 		part,
43013512Srrh 		getpid());
43113512Srrh 	file = fopen(tname, "w");
43213512Srrh 	if (file == NULL) {
43313512Srrh 		yyerror("Bad pass 1 temporary file for writing %s", tname);
43413512Srrh 		delexit();
43513512Srrh 	}
43613512Srrh 	return(file);
43713512Srrh }
43813512Srrh 
pass1()439596Sbill pass1()
440596Sbill {
441596Sbill 	register	int	i;
442596Sbill 
443596Sbill 	passno = 1;
444596Sbill 	dotp = &usedot[0];
445596Sbill 	txtfil = (BFILE *)0;
446596Sbill 	relfil = (struct relbufdesc *)0;
447596Sbill 
448596Sbill 	if (ninfiles == 0){		/*take the input from stdin directly*/
449596Sbill 		lineno = 1;
450596Sbill 		dotsname = "<stdin>";
451596Sbill 
452596Sbill 		yyparse();
453596Sbill 	} else {		/*we have the names tanked*/
454596Sbill 		for (i = 0; i < ninfiles; i++){
455596Sbill 			new_dot_s(innames[i]);
456596Sbill 			if (freopen(innames[i], "r", stdin) == NULL) {
457596Sbill 				yyerror( "Can't open source file %s\n",
458596Sbill 					innames[i]);
459596Sbill 				exit(2);
460596Sbill 			}
461596Sbill 			/* stdio is NOT used to read the input characters */
462596Sbill 			/* we use read directly, into our own buffers */
463596Sbill 			yyparse();
464596Sbill 		}
465596Sbill 	}
466596Sbill 
46713512Srrh 	closetokfile();		/*kick out the last buffered intermediate text*/
468596Sbill }
469596Sbill 
testlocals()470596Sbill testlocals()
471596Sbill {
472596Sbill 	register	int	i;
473596Sbill 	for (i = 0; i <= 9; i++) {
474596Sbill 		if (genref[i])
475596Sbill 			yyerror("Reference to undefined local label %df", i);
476596Sbill 		lgensym[i] = 1;
477596Sbill 		genref[i] = 0;
478596Sbill 	}
479596Sbill }
480596Sbill 
pass1_5()481596Sbill pass1_5()
482596Sbill {
483596Sbill 	sortsymtab();
484596Sbill #ifdef DEBUG
485596Sbill 	if (debug) dumpsymtab();
486596Sbill #endif
487596Sbill 	jxxxfix();
488596Sbill #ifdef DEBUG
489596Sbill 	if (debug) dumpsymtab();
490596Sbill #endif
491596Sbill }
492596Sbill 
open_a_out()493596Sbill open_a_out()
494596Sbill {
49516071Sralph 	struct stat stb;
49616071Sralph 
497596Sbill 	/*
498596Sbill 	 *	Open up the a.out file now, and get set to build
499596Sbill 	 *	up offsets into it for all of the various text,data
500596Sbill 	 *	text relocation and data relocation segments.
501596Sbill 	 */
502596Sbill 	a_out_file = fopen(outfile, "w");
503596Sbill 	if (a_out_file == NULL) {
504596Sbill 		yyerror("Cannot create %s", outfile);
505596Sbill 		delexit();
506596Sbill 	}
507596Sbill 	biofd = a_out_file->_file;
50816071Sralph 	fstat(biofd, &stb);
50916071Sralph 	biobufsize = stb.st_blksize;
510596Sbill 	a_out_off = 0;
511596Sbill }
512596Sbill 
roundsegments()513596Sbill roundsegments()
514596Sbill {
515596Sbill 	register	int	locindex;
516596Sbill 	register	long	v;
517596Sbill 	/*
518596Sbill 	 *	round and assign text segment origins
519596Sbill 	 *	the exec header always goes in usefile[0]
520596Sbill 	 */
521596Sbill 	tsize = 0;
522596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
523679Shenry 		v = round(usedot[locindex].e_xvalue, FW);
524631Shenry 		usedot[locindex].e_xvalue = tsize;
525596Sbill 		if ((locindex == 0) || (v != 0) ){
526596Sbill 			usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE));
527596Sbill 			bopen(usefile[locindex], a_out_off);
528596Sbill 			if (locindex == 0)
529596Sbill 				a_out_off = sizeof (struct exec);
530596Sbill 		} else {
531596Sbill 			usefile[locindex] = (BFILE *)-1;
532596Sbill 		}
533596Sbill 		tsize += v;
534596Sbill 		a_out_off += v;
535596Sbill 	}
536596Sbill 	/*
537596Sbill 	 *		Round and assign data segment origins.
538596Sbill 	 */
539679Shenry 	datbase = round(tsize, FW);
540596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
541679Shenry 		v = round(usedot[NLOC+locindex].e_xvalue, FW);
542631Shenry 		usedot[NLOC+locindex].e_xvalue = datbase + dsize;
543596Sbill 		if (v != 0){
544596Sbill 			usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE));
545596Sbill 			bopen(usefile[NLOC + locindex], a_out_off);
546596Sbill 		} else {
547596Sbill 			usefile[NLOC + locindex] = (BFILE *)-1;
548596Sbill 		}
549596Sbill 		dsize += v;
550596Sbill 		a_out_off += v;
551596Sbill 	}
552596Sbill 	/*
553596Sbill 	 *	Assign final values to symbols
554596Sbill 	 */
555596Sbill 	hdr.a_bss = dsize;
556596Sbill 	freezesymtab();		/* this touches hdr.a_bss */
557596Sbill 	stabfix();
558596Sbill 	/*
559596Sbill 	 *	Set up the relocation information "files" to
560596Sbill 	 *	be zero; outrel takes care of the rest
561596Sbill 	 */
562596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++){
563596Sbill 		rusefile[locindex] = (struct relbufdesc *)0;
564596Sbill 	}
565596Sbill }
566596Sbill 
build_hdr()567596Sbill build_hdr()
568596Sbill {
569596Sbill 	/*
570596Sbill 	 *	Except for the text and data relocation sizes,
571596Sbill 	 *	calculate the final values for the header
572596Sbill 	 *
573596Sbill 	 *	Write out the initial copy; we to come
574596Sbill 	 *	back later and patch up a_trsize and a_drsize,
575596Sbill 	 *	and overwrite this first version of the header.
576596Sbill 	 */
577596Sbill 	hdr.a_magic = MAGIC;
578596Sbill 	hdr.a_text = tsize;
579596Sbill 	hdr.a_data = dsize;
580596Sbill 	hdr.a_bss -= dsize;
581596Sbill 	hdr.a_syms = sizesymtab();	/* Does not include string pool length */
582596Sbill 	hdr.a_entry = 0;
583596Sbill 	hdr.a_trsize = 0;
584596Sbill 	hdr.a_drsize = 0;
585596Sbill 
586596Sbill 	bwrite((char *)&hdr, sizeof(hdr), usefile[0]);
587596Sbill }
588596Sbill 
i_pass2()589596Sbill i_pass2()
590596Sbill {
591596Sbill 	if (useVM == 0) {
59213512Srrh 		fclose(tokfile);
59313512Srrh 		tokfile = fopen(tokfilename, "r");
59413512Srrh 		if (tokfile==NULL) {
59513512Srrh 		   yyerror("Bad pass 2 temporary file for reading %s", tokfilename);
596596Sbill 		   delexit();
597596Sbill 		}
598596Sbill 	}
59913512Srrh 	fclose(strfile);
60013512Srrh 	strfile = fopen(strfilename, "r");
601596Sbill }
602596Sbill 
pass2()603596Sbill pass2()
604596Sbill {
605596Sbill #ifdef DEBUG
606596Sbill 	if (debug)
607596Sbill 		printf("\n\n\n\t\tPASS 2\n\n\n\n");
608596Sbill #endif DEBUG
609596Sbill 	passno = 2;
610596Sbill 	lineno = 1;
611596Sbill 	dotp = &usedot[0];
612596Sbill 	txtfil = usefile[0];	/* already opened (always!) */
613596Sbill 	relfil = 0;		/* outrel takes care of the rest */
614596Sbill 	initoutrel();
615596Sbill 
61613512Srrh 	inittokfile();
617596Sbill 
618596Sbill 	yyparse();
619596Sbill 
62013512Srrh 	closetokfile();
621596Sbill }
622596Sbill 
fillsegments()623596Sbill fillsegments()
624596Sbill {
625596Sbill 	int	locindex;
626596Sbill 	/*
627679Shenry 	 *	Round text and data segments to FW by appending zeros
628596Sbill 	 */
629596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++) {
630596Sbill 		if (usefile[locindex]) {
631596Sbill 			txtfil = usefile[locindex];
632596Sbill 			dotp = &usedot[locindex];
633679Shenry 			while (usedot[locindex].e_xvalue & FW)
634596Sbill 				outb(0);
635596Sbill 		}
636596Sbill 	}
637596Sbill }
638596Sbill 
reloc_syms()639596Sbill reloc_syms()
640596Sbill {
641596Sbill 	u_long	closerelfil();
642596Sbill 	/*
643596Sbill 	 *	Move the relocation information to a.out
644596Sbill 	 *	a_out_off is the offset so far:
645596Sbill 	 *	exec + text segments + data segments
646596Sbill 	 */
647596Sbill 	relocfile = (BFILE *)Calloc(1,sizeof(BFILE));
648596Sbill 	bopen(relocfile, a_out_off);
649596Sbill 	a_out_off += closeoutrel(relocfile);
650596Sbill 
651596Sbill 	hdr.a_trsize = trsize;
652596Sbill 	hdr.a_drsize = drsize;
653638Sbill 	if (readonlydata) {
654638Sbill 		hdr.a_text += hdr.a_data;
655638Sbill 		hdr.a_data = 0;
656638Sbill 		hdr.a_trsize += hdr.a_drsize;
657638Sbill 		hdr.a_drsize = 0;
658638Sbill 	}
659596Sbill 	/*
66013521Srrh 	 *	Output the symbol table and the string pool
66113512Srrh 	 *
66213512Srrh 	 *	We must first rewind the string pool file to its beginning,
66313512Srrh 	 *	in case it was seek'ed into for fetching ascii and asciz
66413512Srrh 	 *	strings.
665596Sbill 	 */
66613512Srrh 	fseek(strfile, 0, 0);
667596Sbill 	symwrite(relocfile);
668596Sbill }
669596Sbill 
fix_a_out()670596Sbill fix_a_out()
671596Sbill {
6725826Srrh 	if (lseek(a_out_file->_file, 0L, 0) < 0L)
673596Sbill 		yyerror("Reposition for header rewrite fails");
674596Sbill 	if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0)
675596Sbill 		yyerror("Rewrite of header fails");
676596Sbill }
677596Sbill 
delexit()678596Sbill delexit()
679596Sbill {
680596Sbill 	delete();
681596Sbill 	if (passno == 2){
682596Sbill 		unlink(outfile);
683596Sbill 	}
684596Sbill 	exit(1);
685596Sbill }
686596Sbill 
delete()687596Sbill delete()
688596Sbill {
68913512Srrh 	if (useVM == 0 || tokfilename[0])
69013512Srrh 		unlink(tokfilename);
69113512Srrh 	if (strfilename[0])
69213512Srrh 		unlink(strfilename);
693596Sbill }
694596Sbill 
sawabort()695596Sbill sawabort()
696596Sbill {
697596Sbill 	char	*fillinbuffer();
698596Sbill 	while (fillinbuffer() != (char *)0)
699596Sbill 		continue;
700596Sbill 	delete();
701596Sbill 	exit(1);	/*although the previous pass will also exit non zero*/
702596Sbill }
703596Sbill 
panic(fmt,a1,a2,a3,a4)704596Sbill panic(fmt, a1, a2, a3, a4)
705596Sbill 	char	*fmt;
706596Sbill 	/*VARARGS 1*/
707596Sbill {
708596Sbill 	yyerror("Assembler panic: bad internal data structure.");
709596Sbill 	yyerror(fmt, a1, a2, a3, a4);
710596Sbill 	delete();
711596Sbill 	abort();
712596Sbill }
713