xref: /csrg-svn/old/as.vax/asmain.c (revision 6559)
15826Srrh /*
25826Srrh  *	Copyright (c) 1982 Regents of the University of California
35826Srrh  */
45826Srrh #ifndef lint
5*6559Srrh static char sccsid[] = "@(#)asmain.c 4.10 04/17/82";
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*6559Srrh #define	unix_lang_name "VAX/UNIX Assembler V04/17/82 4.10"
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 /*
85596Sbill  *	The inter pass temporary 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  */
89596Sbill FILE	*tmpfil;			/* interpass communication file */
90596Sbill /*
91596Sbill  *	a.out is created during the second pass.
92596Sbill  *	It is opened by stdio, but is filled with the parallel
93596Sbill  *	block I/O library
94596Sbill  */
95596Sbill char	*outfile = "a.out";
96596Sbill FILE	*a_out_file;
97596Sbill off_t	a_out_off;			/* cumulative offsets for segments */
98596Sbill /*
99596Sbill  *	The logical files containing the assembled data for each of
100596Sbill  *	the text and data segments are
101596Sbill  *	managed by the parallel block I/O library.
102596Sbill  *	a.out is logically opened in many places at once to
103596Sbill  *	receive the assembled data from the various segments as
104596Sbill  *	it all trickles in, but is physically opened only once
105596Sbill  *	to minimize file overhead.
106596Sbill  */
107596Sbill BFILE	*usefile[NLOC+NLOC];		/* text/data files */
108596Sbill BFILE	*txtfil;			/* current text/data file */
109596Sbill /*
110596Sbill  *	Relocation information is accumulated seperately for each
111596Sbill  *	segment.  This is required by the old loader (from BTL),
112596Sbill  *	but not by the new loader (Bill Joy).
113596Sbill  *
114596Sbill  *	However, the size of the relocation information can not be computed
115596Sbill  *	during or after the 1st pass because the ''absoluteness' of values
116596Sbill  *	is unknown until all locally declared symbols have been seen.
117596Sbill  *	Thus, the size of the relocation information is only
118596Sbill  *	known after the second pass is finished.
119596Sbill  *	This obviates the use of the block I/O
120596Sbill  *	library, which requires knowing the exact offsets in a.out.
121596Sbill  *
122596Sbill  *	So, we save the relocation information internally (we don't
123596Sbill  *	go to internal files to minimize overhead).
124596Sbill  *
125596Sbill  *	Empirically, we studied 259 files composing the system,
126596Sbill  *	two compilers and a compiler generator: (all of which have
127596Sbill  *	fairly large source files)
128596Sbill  *
129596Sbill  *	Number of files = 259
130596Sbill  *		Number of non zero text reloc files: 233
131596Sbill  *		Number of non zero data reloc files: 53
132596Sbill  *	Average text relocation = 889
133596Sbill  *	Average data relocation = 346
134596Sbill  *	Number of files > BUFSIZ text relocation = 71
135596Sbill  *	Number of files > BUFSIZ data relocation = 6
136596Sbill  *
137596Sbill  *	For compiled C code, there is usually one text segment and two
138596Sbill  *	data segments; we see that allocating our own buffers and
139596Sbill  *	doing our internal handling of relocation information will,
140596Sbill  *	on the average, not use more memory than taken up by the buffers
141596Sbill  *	allocated for doing file I/O in parallel to a number of file.
142596Sbill  *
143596Sbill  *	If we are assembling with the -V option, we
144596Sbill  *	use the left over token buffers from the 2nd pass,
145596Sbill  *	otherwise, we create our own.
146596Sbill  *
147596Sbill  *	When the 2nd pass is complete, closeoutrel flushes the token
148596Sbill  *	buffers out to a BFILE.
149596Sbill  *
150596Sbill  *	The internals to relbufdesc are known only in assyms.c
151596Sbill  *
152596Sbill  *	outrel constructs the relocation information.
153596Sbill  *	closeoutrel flushes the relocation information to relfil.
154596Sbill  */
155596Sbill struct	relbufdesc	*rusefile[NLOC+NLOC];
156596Sbill struct	relbufdesc 	*relfil;	/* un concatnated relocation info */
157596Sbill BFILE	*relocfile;			/* concatnated relocation info */
158596Sbill /*
159596Sbill  *	Once the relocation information has been written,
160596Sbill  *	we can write out the symbol table using the Block I/O
161596Sbill  *	mechanisms, as we once again know the offsets into
162596Sbill  *	the a.out file.
163596Sbill  *
164596Sbill  *	We use relfil to output the symbol table information.
165596Sbill  */
166596Sbill 
167596Sbill char	*tmpdirprefix =
168596Sbill #ifdef UNIX
169596Sbill 			"/tmp/";
170596Sbill #else VMS
171596Sbill 			"/usr/tmp/";
172596Sbill #endif
173596Sbill 
174596Sbill #define		TMP_SUFFIX	"asXXXXXX"
175596Sbill char		tmpn1[TNAMESIZE];
176596Sbill 
177596Sbill int delexit();
178596Sbill 
179596Sbill main(argc, argv)
180596Sbill 	int	argc;
181596Sbill 	char 	**argv;
182596Sbill {
1835826Srrh 	char	*sbrk();
184596Sbill 
185596Sbill 	tmpn1[0] = 0;
1865826Srrh 	endcore = sbrk(0);
187596Sbill 
188596Sbill 	argprocess(argc, argv);		/* process argument lists */
189596Sbill 	if (anyerrs) exit(1);
190596Sbill 
191596Sbill 	initialize();
192596Sbill 	zeroorigins();			/* set origins to zero */
193596Sbill 	zerolocals();			/* fix local label counters */
194596Sbill 
195596Sbill 	i_pass1();			/* open temp files, etc */
196596Sbill 	pass1();			/* first pass through .s files */
197596Sbill 	testlocals();			/* check for undefined locals */
198596Sbill 	if (anyerrs) delexit();
199596Sbill 
200596Sbill 	pass1_5();			/* resolve jxxx */
201596Sbill 	if (anyerrs) delexit();
202596Sbill 
203596Sbill 	open_a_out();			/* open a.out */
204679Shenry 	roundsegments();		/* round segments to FW */
205596Sbill 	build_hdr();			/* build initial header, and output */
206596Sbill 
207596Sbill 	i_pass2();			/* reopen temporary file, etc */
208596Sbill 	pass2();			/* second pass through the virtual .s */
209596Sbill 	if (anyerrs) delexit();
210596Sbill 
211679Shenry 	fillsegments();			/* fill segments with 0 to FW */
212596Sbill 	reloc_syms();			/* dump relocation and symbol table */
213596Sbill 
214596Sbill 	delete();			/* remove tmp file */
215596Sbill 	bflush();			/* close off block I/O view of a.out */
216596Sbill 	fix_a_out();			/* add in text and data reloc counts */
217596Sbill 
218596Sbill 	if (anyerrs == 0 && orgwarn)
219596Sbill 		yyerror("Caution: absolute origins.\n");
2205826Srrh 
2215826Srrh 	if (nGHnumbers)
2225826Srrh 		yywarning("Caution: G or H format floating point numbers");
2235826Srrh 	if (nGHopcodes)
2245826Srrh 		yywarning("Caution: G or H format floating point operators");
2255826Srrh 	if (nnewopcodes)
2265826Srrh 		yywarning("Caution: New Opcodes");
2275826Srrh 	if (nGHnumbers || nGHopcodes || nnewopcodes)
2285826Srrh 		yywarning("These are not defined for all implementations of the VAX architecture.\n");
2295826Srrh 
230596Sbill 	exit(anyerrs != 0);
231596Sbill }	/*end of UNIX main*/
232596Sbill 
233596Sbill argprocess(argc, argv)
234596Sbill 	int	argc;
235596Sbill 	char	*argv[];
236596Sbill {
237596Sbill 	register	char	*cp;
238596Sbill 
239596Sbill 	ninfiles = 0;
240596Sbill 	silent = 0;
241596Sbill #ifdef DEBUG
242596Sbill 	debug = 0;
243596Sbill #endif
244643Sbill 	innames = (char **)ClearCalloc(argc+1, sizeof (innames[0]));
245596Sbill 	dotsname = "<argv error>";
246596Sbill 	while (argc > 1) {
247643Sbill 		if (argv[1][0] != '-')
248643Sbill 			innames[ninfiles++] = argv[1];
249643Sbill 		else {
250596Sbill 			cp = argv[1] + 1;
251596Sbill 			/*
252596Sbill 			 *	We can throw away single minus signs, so
253596Sbill 			 *	that make scripts for the PDP 11 assembler work
254596Sbill 			 *	on this assembler too
255596Sbill 			 */
256596Sbill 			while (*cp){
257596Sbill 				switch(*cp++){
258596Sbill 				 default:
259596Sbill 					yyerror("Unknown flag: %c", *--cp);
260596Sbill 					cp++;
261596Sbill 					break;
262*6559Srrh 				 case 'v':
263*6559Srrh 					selfwhat(stdout);
264*6559Srrh 					exit(1);
265596Sbill 				 case 'd':
266596Sbill 					d124 = *cp++ - '0';
267596Sbill 					if ( (d124 != 1) && (d124 != 2) &&
268596Sbill 					     (d124 != 4)){
269596Sbill 						yyerror("-d[124] only");
270596Sbill 						exit(1);
271596Sbill 					}
272596Sbill 					break;
273596Sbill 				 case 'o':
274596Sbill 					if (argc < 3){
275596Sbill 						yyerror("-o what???");
276596Sbill 						exit(1);
277596Sbill 					}
278596Sbill 					outfile = argv[2];
279596Sbill 				   bumpone:
280596Sbill 					argc -= 2;
281596Sbill 					argv += 2;
282596Sbill 					goto nextarg;
283596Sbill 
284596Sbill 				 case 't':
285596Sbill 					if (argc < 3){
286596Sbill 						yyerror("-t what???");
287596Sbill 						exit(1);
288596Sbill 					}
289596Sbill 					tmpdirprefix = argv[2];
290596Sbill 					goto bumpone;
291596Sbill 
292596Sbill 				 case 'V':
293596Sbill 					useVM = 1;
294596Sbill 					break;
295596Sbill 				 case 'W':
296596Sbill 					silent = 1;
297596Sbill 					break;
298596Sbill 				 case 'L':
299596Sbill 					savelabels = 1;
300596Sbill 					break;
301636Shenry 				 case 'J':
302636Shenry 					jxxxJUMP = 1;
303636Shenry 					break;
304596Sbill #ifdef DEBUG
305596Sbill 				 case 'D':
306596Sbill 					debug = 1;
307596Sbill 					break;
308596Sbill 				 case 'T':
309596Sbill 					toktrace = 1;
310596Sbill 					break;
311596Sbill #endif
312638Sbill 				 case 'R':
313638Sbill 					readonlydata = 1;
314638Sbill 					break;
315596Sbill 				}	/*end of the switch*/
316596Sbill 			}	/*end of pulling out all arguments*/
317596Sbill 		}	/*end of a flag argument*/
318596Sbill 		--argc; ++argv;
319596Sbill 	   nextarg:;
320596Sbill 	}
321643Sbill 	/* innames[ninfiles] = 0; */
322596Sbill }
323*6559Srrh /*
324*6559Srrh  *	poke through the data space and find all sccs identifiers.
325*6559Srrh  *	We assume:
326*6559Srrh  *	a) that extern char **environ; is the first thing in the bss
327*6559Srrh  *	segment (true, if one is using the new version of cmgt.crt0.c)
328*6559Srrh  *	b) that the sccsid's have not been put into text space.
329*6559Srrh  */
330*6559Srrh selfwhat(place)
331*6559Srrh 	FILE	*place;
332*6559Srrh {
333*6559Srrh 	extern	char **environ;
334*6559Srrh 	register	char	*ub;
335*6559Srrh 	register	char *cp;
336*6559Srrh 	register	char	*pat;
337*6559Srrh 	char	*sbrk();
338596Sbill 
339*6559Srrh 	for (cp = (char *)&environ, ub = sbrk(0); cp < ub; cp++){
340*6559Srrh 		if (cp[0] != '@') continue;
341*6559Srrh 		if (cp[1] != '(') continue;
342*6559Srrh 		if (cp[2] != '#') continue;
343*6559Srrh 		if (cp[3] != ')') continue;
344*6559Srrh 		fputc('\t', place);
345*6559Srrh 		for (cp += 4; cp < ub; cp++){
346*6559Srrh 			if (*cp == 0) break;
347*6559Srrh 			if (*cp == '>') break;
348*6559Srrh 			if (*cp == '\n') break;
349*6559Srrh 			fputc(*cp, place);
350*6559Srrh 		}
351*6559Srrh 		fputc('\n', place);
352*6559Srrh 	}
353*6559Srrh }
354*6559Srrh 
355596Sbill initialize()
356596Sbill {
357596Sbill 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
358596Sbill 		signal(SIGINT, delexit);
359596Sbill 	/*
360596Sbill 	 *	Install symbols in the table
361596Sbill 	 */
362596Sbill 	symtabinit();
363596Sbill 	syminstall();
364596Sbill 	/*
365596Sbill 	 *	Build the expression parser accelerator token sets
366596Sbill 	 */
367596Sbill 	buildtokensets();
368596Sbill }
369596Sbill 
370596Sbill zeroorigins()
371596Sbill {
372596Sbill 	register	int	locindex;
373596Sbill 	/*
374596Sbill 	 *	Mark usedot: the first NLOC slots are for named text segments,
375596Sbill 	 *	the next for named data segments.
376596Sbill 	 */
377596Sbill 	for (locindex = 0; locindex < NLOC; locindex++){
378631Shenry 		usedot[locindex].e_xtype = XTEXT;
379631Shenry 		usedot[NLOC + locindex].e_xtype = XDATA;
380631Shenry 		usedot[locindex].e_xvalue = 0;
381631Shenry 		usedot[NLOC + locindex].e_xvalue = 0;
382596Sbill 	}
383596Sbill }
384596Sbill 
385596Sbill zerolocals()
386596Sbill {
387596Sbill 	register	int	i;
388596Sbill 
389596Sbill 	for (i = 0; i <= 9; i++) {
390596Sbill 		lgensym[i] = 1;
391596Sbill 		genref[i] = 0;
392596Sbill 	}
393596Sbill }
394596Sbill 
395596Sbill i_pass1()
396596Sbill {
397596Sbill 	if (useVM == 0){
398596Sbill 		strcat(tmpn1, tmpdirprefix);
399644Shenry 		if (tmpdirprefix[strlen(tmpdirprefix)-1] != '/')
400644Shenry 			strcat(tmpn1, "/");
4015826Srrh 		(void)strcat(tmpn1, TMP_SUFFIX);
4025826Srrh 		(void)mktemp(tmpn1);
403596Sbill 		tmpfil = fopen(tmpn1, "w");
404596Sbill 		if (tmpfil==NULL) {
405596Sbill 		  yyerror("Bad pass 1 temporary file for writing %s", tmpn1);
406596Sbill 		  delexit();
407596Sbill 		}
408596Sbill 	}
409596Sbill 
410596Sbill 	inittmpfile();
411636Shenry 	initijxxx();
412596Sbill }
413596Sbill 
414596Sbill pass1()
415596Sbill {
416596Sbill 	register	int	i;
417596Sbill 
418596Sbill 	passno = 1;
419596Sbill 	dotp = &usedot[0];
420596Sbill 	txtfil = (BFILE *)0;
421596Sbill 	relfil = (struct relbufdesc *)0;
422596Sbill 
423596Sbill 	if (ninfiles == 0){		/*take the input from stdin directly*/
424596Sbill 		lineno = 1;
425596Sbill 		dotsname = "<stdin>";
426596Sbill 
427596Sbill 		yyparse();
428596Sbill 	} else {		/*we have the names tanked*/
429596Sbill 		for (i = 0; i < ninfiles; i++){
430596Sbill 			new_dot_s(innames[i]);
431596Sbill 			if (freopen(innames[i], "r", stdin) == NULL) {
432596Sbill 				yyerror( "Can't open source file %s\n",
433596Sbill 					innames[i]);
434596Sbill 				exit(2);
435596Sbill 			}
436596Sbill 			/* stdio is NOT used to read the input characters */
437596Sbill 			/* we use read directly, into our own buffers */
438596Sbill 			yyparse();
439596Sbill 		}
440596Sbill 	}
441596Sbill 
442596Sbill 	closetmpfile();		/*kick out the last buffered intermediate text*/
443596Sbill }
444596Sbill 
445596Sbill testlocals()
446596Sbill {
447596Sbill 	register	int	i;
448596Sbill 	for (i = 0; i <= 9; i++) {
449596Sbill 		if (genref[i])
450596Sbill 			yyerror("Reference to undefined local label %df", i);
451596Sbill 		lgensym[i] = 1;
452596Sbill 		genref[i] = 0;
453596Sbill 	}
454596Sbill }
455596Sbill 
456596Sbill pass1_5()
457596Sbill {
458596Sbill 	sortsymtab();
459596Sbill #ifdef DEBUG
460596Sbill 	if (debug) dumpsymtab();
461596Sbill #endif
462596Sbill 	jxxxfix();
463596Sbill #ifdef DEBUG
464596Sbill 	if (debug) dumpsymtab();
465596Sbill #endif
466596Sbill }
467596Sbill 
468596Sbill open_a_out()
469596Sbill {
470596Sbill 	/*
471596Sbill 	 *	Open up the a.out file now, and get set to build
472596Sbill 	 *	up offsets into it for all of the various text,data
473596Sbill 	 *	text relocation and data relocation segments.
474596Sbill 	 */
475596Sbill 	a_out_file = fopen(outfile, "w");
476596Sbill 	if (a_out_file == NULL) {
477596Sbill 		yyerror("Cannot create %s", outfile);
478596Sbill 		delexit();
479596Sbill 	}
480596Sbill 	biofd = a_out_file->_file;
481596Sbill 	a_out_off = 0;
482596Sbill }
483596Sbill 
484596Sbill roundsegments()
485596Sbill {
486596Sbill 	register	int	locindex;
487596Sbill 	register	long	v;
488596Sbill 	/*
489596Sbill 	 *	round and assign text segment origins
490596Sbill 	 *	the exec header always goes in usefile[0]
491596Sbill 	 */
492596Sbill 	tsize = 0;
493596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
494679Shenry 		v = round(usedot[locindex].e_xvalue, FW);
495631Shenry 		usedot[locindex].e_xvalue = tsize;
496596Sbill 		if ((locindex == 0) || (v != 0) ){
497596Sbill 			usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE));
498596Sbill 			bopen(usefile[locindex], a_out_off);
499596Sbill 			if (locindex == 0)
500596Sbill 				a_out_off = sizeof (struct exec);
501596Sbill 		} else {
502596Sbill 			usefile[locindex] = (BFILE *)-1;
503596Sbill 		}
504596Sbill 		tsize += v;
505596Sbill 		a_out_off += v;
506596Sbill 	}
507596Sbill 	/*
508596Sbill 	 *		Round and assign data segment origins.
509596Sbill 	 */
510679Shenry 	datbase = round(tsize, FW);
511596Sbill 	for (locindex=0; locindex<NLOC; locindex++) {
512679Shenry 		v = round(usedot[NLOC+locindex].e_xvalue, FW);
513631Shenry 		usedot[NLOC+locindex].e_xvalue = datbase + dsize;
514596Sbill 		if (v != 0){
515596Sbill 			usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE));
516596Sbill 			bopen(usefile[NLOC + locindex], a_out_off);
517596Sbill 		} else {
518596Sbill 			usefile[NLOC + locindex] = (BFILE *)-1;
519596Sbill 		}
520596Sbill 		dsize += v;
521596Sbill 		a_out_off += v;
522596Sbill 	}
523596Sbill 	/*
524596Sbill 	 *	Assign final values to symbols
525596Sbill 	 */
526596Sbill 	hdr.a_bss = dsize;
527596Sbill 	freezesymtab();		/* this touches hdr.a_bss */
528596Sbill 	stabfix();
529596Sbill 	/*
530596Sbill 	 *	Set up the relocation information "files" to
531596Sbill 	 *	be zero; outrel takes care of the rest
532596Sbill 	 */
533596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++){
534596Sbill 		rusefile[locindex] = (struct relbufdesc *)0;
535596Sbill 	}
536596Sbill }
537596Sbill 
538596Sbill build_hdr()
539596Sbill {
540596Sbill 	/*
541596Sbill 	 *	Except for the text and data relocation sizes,
542596Sbill 	 *	calculate the final values for the header
543596Sbill 	 *
544596Sbill 	 *	Write out the initial copy; we to come
545596Sbill 	 *	back later and patch up a_trsize and a_drsize,
546596Sbill 	 *	and overwrite this first version of the header.
547596Sbill 	 */
548596Sbill 	hdr.a_magic = MAGIC;
549596Sbill 	hdr.a_text = tsize;
550596Sbill 	hdr.a_data = dsize;
551596Sbill 	hdr.a_bss -= dsize;
552596Sbill 	hdr.a_syms = sizesymtab();	/* Does not include string pool length */
553596Sbill 	hdr.a_entry = 0;
554596Sbill 	hdr.a_trsize = 0;
555596Sbill 	hdr.a_drsize = 0;
556596Sbill 
557596Sbill 	bwrite((char *)&hdr, sizeof(hdr), usefile[0]);
558596Sbill }
559596Sbill 
560596Sbill i_pass2()
561596Sbill {
562596Sbill 	if (useVM == 0) {
563596Sbill 		fclose(tmpfil);
564596Sbill 		tmpfil = fopen(tmpn1, "r");
565596Sbill 		if (tmpfil==NULL) {
566596Sbill 		   yyerror("Bad pass 2 temporary file for reading %s", tmpn1);
567596Sbill 		   delexit();
568596Sbill 		}
569596Sbill 	}
570596Sbill }
571596Sbill 
572596Sbill pass2()
573596Sbill {
574596Sbill #ifdef DEBUG
575596Sbill 	if (debug)
576596Sbill 		printf("\n\n\n\t\tPASS 2\n\n\n\n");
577596Sbill #endif DEBUG
578596Sbill 	passno = 2;
579596Sbill 	lineno = 1;
580596Sbill 	dotp = &usedot[0];
581596Sbill 	txtfil = usefile[0];	/* already opened (always!) */
582596Sbill 	relfil = 0;		/* outrel takes care of the rest */
583596Sbill 	initoutrel();
584596Sbill 
585596Sbill 	inittmpfile();
586596Sbill 
587596Sbill 	yyparse();
588596Sbill 
589596Sbill 	closetmpfile();
590596Sbill }
591596Sbill 
592596Sbill fillsegments()
593596Sbill {
594596Sbill 	int	locindex;
595596Sbill 	/*
596679Shenry 	 *	Round text and data segments to FW by appending zeros
597596Sbill 	 */
598596Sbill 	for (locindex = 0; locindex < NLOC + NLOC; locindex++) {
599596Sbill 		if (usefile[locindex]) {
600596Sbill 			txtfil = usefile[locindex];
601596Sbill 			dotp = &usedot[locindex];
602679Shenry 			while (usedot[locindex].e_xvalue & FW)
603596Sbill 				outb(0);
604596Sbill 		}
605596Sbill 	}
606596Sbill }
607596Sbill 
608596Sbill reloc_syms()
609596Sbill {
610596Sbill 	u_long	closerelfil();
611596Sbill 	/*
612596Sbill 	 *	Move the relocation information to a.out
613596Sbill 	 *	a_out_off is the offset so far:
614596Sbill 	 *	exec + text segments + data segments
615596Sbill 	 */
616596Sbill 	relocfile = (BFILE *)Calloc(1,sizeof(BFILE));
617596Sbill 	bopen(relocfile, a_out_off);
618596Sbill 	a_out_off += closeoutrel(relocfile);
619596Sbill 
620596Sbill 	hdr.a_trsize = trsize;
621596Sbill 	hdr.a_drsize = drsize;
622638Sbill 	if (readonlydata) {
623638Sbill 		hdr.a_text += hdr.a_data;
624638Sbill 		hdr.a_data = 0;
625638Sbill 		hdr.a_trsize += hdr.a_drsize;
626638Sbill 		hdr.a_drsize = 0;
627638Sbill 	}
628596Sbill 	/*
629596Sbill 	 *	Output the symbol table
630596Sbill 	 *	and if FLEXNAMES is set, the string pool
631596Sbill 	 */
632596Sbill 	symwrite(relocfile);
633596Sbill }
634596Sbill 
635596Sbill fix_a_out()
636596Sbill {
6375826Srrh 	if (lseek(a_out_file->_file, 0L, 0) < 0L)
638596Sbill 		yyerror("Reposition for header rewrite fails");
639596Sbill 	if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0)
640596Sbill 		yyerror("Rewrite of header fails");
641596Sbill }
642596Sbill 
643596Sbill delexit()
644596Sbill {
645596Sbill 	delete();
646596Sbill 	if (passno == 2){
647596Sbill 		unlink(outfile);
648596Sbill 	}
649596Sbill 	exit(1);
650596Sbill }
651596Sbill 
652596Sbill delete()
653596Sbill {
654596Sbill 	if (useVM == 0 || tmpn1[0])
655596Sbill 		unlink(tmpn1);
656596Sbill }
657596Sbill 
658596Sbill sawabort()
659596Sbill {
660596Sbill 	char	*fillinbuffer();
661596Sbill 	while (fillinbuffer() != (char *)0)
662596Sbill 		continue;
663596Sbill 	delete();
664596Sbill 	exit(1);	/*although the previous pass will also exit non zero*/
665596Sbill }
666596Sbill 
667596Sbill panic(fmt, a1, a2, a3, a4)
668596Sbill 	char	*fmt;
669596Sbill 	/*VARARGS 1*/
670596Sbill {
671596Sbill 	yyerror("Assembler panic: bad internal data structure.");
672596Sbill 	yyerror(fmt, a1, a2, a3, a4);
673596Sbill 	delete();
674596Sbill 	abort();
675596Sbill }
676