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