xref: /csrg-svn/old/as.tahoe/asmain.c (revision 32435)
132434Sbostic /*
232434Sbostic  *	Copyright (c) 1982 Regents of the University of California
332434Sbostic  */
432434Sbostic #ifndef lint
532434Sbostic static char sccsid[] = "@(#)asmain.c 4.13 6/30/83";
632434Sbostic #endif not lint
732434Sbostic 
832434Sbostic #include <stdio.h>
932434Sbostic #include <ctype.h>
1032434Sbostic #include <signal.h>
1132434Sbostic 
1232434Sbostic #include "as.h"
1332434Sbostic #include "assyms.h"
1432434Sbostic #include "asscan.h"
1532434Sbostic #include "asexpr.h"
1632434Sbostic 
1732434Sbostic #define	unix_lang_name "VAX/UNIX Assembler V6/30/83 4.13"
1832434Sbostic /*
1932434Sbostic  *	variables to manage reading the assembly source files
2032434Sbostic  */
2132434Sbostic char	*dotsname;	/*the current file name; managed by the parser*/
2232434Sbostic int	lineno;		/*current line number; managed by the parser*/
2332434Sbostic char	**innames;	/*names of the files being assembled*/
2432434Sbostic int	ninfiles;	/*how many interesting files there are*/
2532434Sbostic FILE	*source;	/*current source file (for listing) */
2632434Sbostic char	layout[400];	/*layout bytes */
2732434Sbostic char	*layoutpos = layout;	/*layout position in listfile */
2832434Sbostic int	ind = 0;	/*innames in-index: 0..minfiles */
2932434Sbostic int	endofsource = 0;
3032434Sbostic long	sourcepos;
3132434Sbostic /*
3232434Sbostic  *	Flags settable from the argv process argument list
3332434Sbostic  */
3432434Sbostic int	silent = 0;	/*don't complain about any errors*/
3532434Sbostic int	savelabels = 0;	/*write the labels to the a.out file*/
3632434Sbostic int 	d124 = 4;	/*default allocate 4 bytes for unknown pointers*/
3732434Sbostic int	anyerrs = 0;	/*no errors yet*/
3832434Sbostic int	anywarnings=0;	/*no warnings yet*/
3932434Sbostic int	orgwarn = 0;	/*Bad origins*/
4032434Sbostic int	passno = 1;	/* current pass*/
4132434Sbostic int	jxxxJUMP = 0;	/* in jxxxes that branch too far, use jmp instead of brw */
4232434Sbostic int	readonlydata = 0;	/* initialzed data -> text space */
4332434Sbostic int	liston = 0;	/* don't produce listing */
4432434Sbostic 
4532434Sbostic 
4632434Sbostic #ifdef DEBUG
4732434Sbostic int 	debug = 0;
4832434Sbostic int	toktrace = 0;
4932434Sbostic #endif
5032434Sbostic 
5132434Sbostic int	useVM =	0;
5232434Sbostic 
5332434Sbostic char	*endcore;	/*where to get more symbol space*/
5432434Sbostic 
5532434Sbostic /*
5632434Sbostic  *	Managers of the a.out file.
5732434Sbostic  */
5832434Sbostic struct	exec	hdr;
5932434Sbostic #define	MAGIC	0407
6032434Sbostic u_long	tsize;		/* total text size */
6132434Sbostic u_long	dsize;		/* total data size */
6232434Sbostic u_long	datbase;	/* base of the data segment */
6332434Sbostic u_long	trsize;		/* total text relocation size */
6432434Sbostic u_long	drsize;		/* total data relocation size */
6532434Sbostic 
6632434Sbostic /*
6732434Sbostic  *	Information about the current segment is accumulated in
6832434Sbostic  *	usedot; the most important information stored is the
6932434Sbostic  *	accumulated size of each of the text and data segments
7032434Sbostic  *
7132434Sbostic  *	dotp points to the correct usedot expression for the current segment
7232434Sbostic  */
7332434Sbostic struct	exp	usedot[NLOC+NLOC];	/* info about all segments */
7432434Sbostic struct	exp	*dotp;			/* data/text location pointer */
7532434Sbostic /*
7632434Sbostic  *	The inter pass temporary token file is opened and closed by stdio, but
7732434Sbostic  *	is written to using direct read/write, as the temporary file
7832434Sbostic  *	is composed of buffers exactly BUFSIZ long.
7932434Sbostic  */
8032434Sbostic FILE	*tokfile;			/* interpass communication file */
8132434Sbostic char	tokfilename[TNAMESIZE];
8232434Sbostic /*
8332434Sbostic  *	The string file is the string table
8432434Sbostic  *	cat'ed to the end of the built up a.out file
8532434Sbostic  */
8632434Sbostic FILE	*strfile;			/* interpass string file */
8732434Sbostic char	strfilename[TNAMESIZE];
8832434Sbostic int	strfilepos = 0;			/* position within the string file */
8932434Sbostic /*
9032434Sbostic  *	a.out is created during the second pass.
9132434Sbostic  *	It is opened by stdio, but is filled with the parallel
9232434Sbostic  *	block I/O library
9332434Sbostic  */
9432434Sbostic char	*outfile = "a.out";
9532434Sbostic FILE	*a_out_file;
9632434Sbostic off_t	a_out_off;			/* cumulative offsets for segments */
9732434Sbostic /*
9832434Sbostic  *	The logical files containing the assembled data for each of
9932434Sbostic  *	the text and data segments are
10032434Sbostic  *	managed by the parallel block I/O library.
10132434Sbostic  *	a.out is logically opened in many places at once to
10232434Sbostic  *	receive the assembled data from the various segments as
10332434Sbostic  *	it all trickles in, but is physically opened only once
10432434Sbostic  *	to minimize file overhead.
10532434Sbostic  */
10632434Sbostic BFILE	*usefile[NLOC+NLOC];		/* text/data files */
10732434Sbostic BFILE	*txtfil;			/* current text/data file */
10832434Sbostic /*
10932434Sbostic  *	Relocation information is accumulated seperately for each
11032434Sbostic  *	segment.  This is required by the old loader (from BTL),
11132434Sbostic  *	but not by the new loader (Bill Joy).
11232434Sbostic  *
11332434Sbostic  *	However, the size of the relocation information can not be computed
11432434Sbostic  *	during or after the 1st pass because the ''absoluteness' of values
11532434Sbostic  *	is unknown until all locally declared symbols have been seen.
11632434Sbostic  *	Thus, the size of the relocation information is only
11732434Sbostic  *	known after the second pass is finished.
11832434Sbostic  *	This obviates the use of the block I/O
11932434Sbostic  *	library, which requires knowing the exact offsets in a.out.
12032434Sbostic  *
12132434Sbostic  *	So, we save the relocation information internally (we don't
12232434Sbostic  *	go to internal files to minimize overhead).
12332434Sbostic  *
12432434Sbostic  *	Empirically, we studied 259 files composing the system,
12532434Sbostic  *	two compilers and a compiler generator: (all of which have
12632434Sbostic  *	fairly large source files)
12732434Sbostic  *
12832434Sbostic  *	Number of files = 259
12932434Sbostic  *		Number of non zero text reloc files: 233
13032434Sbostic  *		Number of non zero data reloc files: 53
13132434Sbostic  *	Average text relocation = 889
13232434Sbostic  *	Average data relocation = 346
13332434Sbostic  *	Number of files > BUFSIZ text relocation = 71
13432434Sbostic  *	Number of files > BUFSIZ data relocation = 6
13532434Sbostic  *
13632434Sbostic  *	For compiled C code, there is usually one text segment and two
13732434Sbostic  *	data segments; we see that allocating our own buffers and
13832434Sbostic  *	doing our internal handling of relocation information will,
13932434Sbostic  *	on the average, not use more memory than taken up by the buffers
14032434Sbostic  *	allocated for doing file I/O in parallel to a number of file.
14132434Sbostic  *
14232434Sbostic  *	If we are assembling with the -V option, we
14332434Sbostic  *	use the left over token buffers from the 2nd pass,
14432434Sbostic  *	otherwise, we create our own.
14532434Sbostic  *
14632434Sbostic  *	When the 2nd pass is complete, closeoutrel flushes the token
14732434Sbostic  *	buffers out to a BFILE.
14832434Sbostic  *
14932434Sbostic  *	The internals to relbufdesc are known only in assyms.c
15032434Sbostic  *
15132434Sbostic  *	outrel constructs the relocation information.
15232434Sbostic  *	closeoutrel flushes the relocation information to relfil.
15332434Sbostic  */
15432434Sbostic struct	relbufdesc	*rusefile[NLOC+NLOC];
15532434Sbostic struct	relbufdesc 	*relfil;	/* un concatnated relocation info */
15632434Sbostic BFILE	*relocfile;			/* concatnated relocation info */
15732434Sbostic /*
15832434Sbostic  *	Once the relocation information has been written,
15932434Sbostic  *	we can write out the symbol table using the Block I/O
16032434Sbostic  *	mechanisms, as we once again know the offsets into
16132434Sbostic  *	the a.out file.
16232434Sbostic  *
16332434Sbostic  *	We use relfil to output the symbol table information.
16432434Sbostic  */
16532434Sbostic char	*tmpdirprefix = "/tmp/";
16632434Sbostic int delexit();
16732434Sbostic 
16832434Sbostic main(argc, argv)
16932434Sbostic 	int	argc;
17032434Sbostic 	char 	**argv;
17132434Sbostic {
17232434Sbostic 	char	*sbrk();
17332434Sbostic 
17432434Sbostic 	tokfilename[0] = 0;
17532434Sbostic 	strfilename[0] = 0;
17632434Sbostic 	endcore = sbrk(0);
17732434Sbostic 
17832434Sbostic 	argprocess(argc, argv);		/* process argument lists */
17932434Sbostic 	if (anyerrs) exit(1);
18032434Sbostic 
18132434Sbostic 	initialize();
18232434Sbostic 	zeroorigins();			/* set origins to zero */
18332434Sbostic 	zerolocals();			/* fix local label counters */
18432434Sbostic 
18532434Sbostic 	i_pass1();			/* open temp files, etc */
18632434Sbostic 	pass1();			/* first pass through .s files */
18732434Sbostic 	testlocals();			/* check for undefined locals */
18832434Sbostic 	if (anyerrs) delexit();
18932434Sbostic 
19032434Sbostic 	pass1_5();			/* resolve jxxx */
19132434Sbostic 	if (anyerrs) delexit();
19232434Sbostic 
19332434Sbostic 	open_a_out();			/* open a.out */
19432434Sbostic 	roundsegments();		/* round segments to FW */
19532434Sbostic 	build_hdr();			/* build initial header, and output */
19632434Sbostic 
19732434Sbostic 	i_pass2();			/* reopen temporary file, etc */
19832434Sbostic 	pass2();			/* second pass through the virtual .s */
19932434Sbostic 	if (anyerrs) delexit();
20032434Sbostic 
20132434Sbostic 	fillsegments();			/* fill segments with 0 to FW */
20232434Sbostic 	reloc_syms();			/* dump relocation and symbol table */
20332434Sbostic 
20432434Sbostic 	delete();			/* remove tmp file */
20532434Sbostic 	bflush();			/* close off block I/O view of a.out */
20632434Sbostic 	fix_a_out();			/* add in text and data reloc counts */
20732434Sbostic 
20832434Sbostic 	if (anyerrs == 0 && orgwarn)
20932434Sbostic 		yyerror("Caution: absolute origins.\n");
21032434Sbostic 
21132434Sbostic 	exit(anyerrs != 0);
21232434Sbostic }
21332434Sbostic 
21432434Sbostic argprocess(argc, argv)
21532434Sbostic 	int	argc;
21632434Sbostic 	char	*argv[];
21732434Sbostic {
21832434Sbostic 	register	char	*cp;
21932434Sbostic 
22032434Sbostic 	ninfiles = 0;
22132434Sbostic 	silent = 0;
22232434Sbostic #ifdef DEBUG
22332434Sbostic 	debug = 0;
22432434Sbostic #endif
22532434Sbostic 	innames = (char **)ClearCalloc(argc+1, sizeof (innames[0]));
22632434Sbostic 	dotsname = "<argv error>";
22732434Sbostic 	while (argc > 1) {
22832434Sbostic 		if (argv[1][0] != '-')
22932434Sbostic 			innames[ninfiles++] = argv[1];
23032434Sbostic 		else {
23132434Sbostic 			cp = argv[1] + 1;
23232434Sbostic 			/*
23332434Sbostic 			 *	We can throw away single minus signs, so
23432434Sbostic 			 *	that make scripts for the PDP 11 assembler work
23532434Sbostic 			 *	on this assembler too
23632434Sbostic 			 */
23732434Sbostic 			while (*cp){
23832434Sbostic 				switch(*cp++){
23932434Sbostic 				 default:
24032434Sbostic 					yyerror("Unknown flag: %c", *--cp);
24132434Sbostic 					cp++;
24232434Sbostic 					break;
24332434Sbostic 				 case 'v':
24432434Sbostic 					selfwhat(stdout);
24532434Sbostic 					exit(1);
24632434Sbostic 				 case 'd':
24732434Sbostic 					d124 = *cp++ - '0';
24832434Sbostic 					if ( (d124 != 1) && (d124 != 2) &&
24932434Sbostic 					     (d124 != 4)){
25032434Sbostic 						yyerror("-d[124] only");
25132434Sbostic 						exit(1);
25232434Sbostic 					}
25332434Sbostic 					break;
25432434Sbostic 				 case 'P':
25532434Sbostic 					liston = 1;
25632434Sbostic 					listfile = stdout;
25732434Sbostic 					break;
25832434Sbostic 				 case 'o':
25932434Sbostic 					if (argc < 3){
26032434Sbostic 						yyerror("-o what???");
26132434Sbostic 						exit(1);
26232434Sbostic 					}
26332434Sbostic 					outfile = argv[2];
26432434Sbostic 				   bumpone:
26532434Sbostic 					argc -= 2;
26632434Sbostic 					argv += 2;
26732434Sbostic 					goto nextarg;
26832434Sbostic 
26932434Sbostic 				 case 't':
27032434Sbostic 					if (argc < 3){
27132434Sbostic 						yyerror("-t what???");
27232434Sbostic 						exit(1);
27332434Sbostic 					}
27432434Sbostic 					tmpdirprefix = argv[2];
27532434Sbostic 					goto bumpone;
27632434Sbostic 
27732434Sbostic 				 case 'V':
27832434Sbostic 					useVM = 1;
27932434Sbostic 					break;
28032434Sbostic 				 case 'W':
28132434Sbostic 					silent = 1;
28232434Sbostic 					break;
28332434Sbostic 				 case 'L':
28432434Sbostic 					savelabels = 1;
28532434Sbostic 					break;
28632434Sbostic 				 case 'J':
28732434Sbostic 					jxxxJUMP = 1;
28832434Sbostic 					break;
28932434Sbostic #ifdef DEBUG
29032434Sbostic 				 case 'D':
29132434Sbostic 					debug = 1;
29232434Sbostic 					break;
29332434Sbostic 				 case 'T':
29432434Sbostic 					toktrace = 1;
29532434Sbostic 					break;
29632434Sbostic #endif
29732434Sbostic 				 case 'R':
29832434Sbostic 					readonlydata = 1;
29932434Sbostic 					break;
30032434Sbostic 				}	/*end of the switch*/
30132434Sbostic 			}	/*end of pulling out all arguments*/
30232434Sbostic 		}	/*end of a flag argument*/
30332434Sbostic 		--argc; ++argv;
30432434Sbostic 	   nextarg:;
30532434Sbostic 	}
30632434Sbostic 	/* innames[ninfiles] = 0; */
30732434Sbostic }
30832434Sbostic /*
30932434Sbostic  *	poke through the data space and find all sccs identifiers.
31032434Sbostic  *	We assume:
31132434Sbostic  *	a) that extern char **environ; is the first thing in the bss
31232434Sbostic  *	segment (true, if one is using the new version of cmgt.crt0.c)
31332434Sbostic  *	b) that the sccsid's have not been put into text space.
31432434Sbostic  */
31532434Sbostic selfwhat(place)
31632434Sbostic 	FILE	*place;
31732434Sbostic {
31832434Sbostic 	extern	char **environ;
31932434Sbostic 	register	char	*ub;
32032434Sbostic 	register	char *cp;
32132434Sbostic 	char	*sbrk();
32232434Sbostic 
32332434Sbostic 	for (cp = (char *)&environ, ub = sbrk(0); cp < ub; cp++){
32432434Sbostic 		if (cp[0] != '@') continue;
32532434Sbostic 		if (cp[1] != '(') continue;
32632434Sbostic 		if (cp[2] != '#') continue;
32732434Sbostic 		if (cp[3] != ')') continue;
32832434Sbostic 		fputc('\t', place);
32932434Sbostic 		for (cp += 4; cp < ub; cp++){
33032434Sbostic 			if (*cp == 0) break;
33132434Sbostic 			if (*cp == '>') break;
33232434Sbostic 			if (*cp == '\n') break;
33332434Sbostic 			fputc(*cp, place);
33432434Sbostic 		}
33532434Sbostic 		fputc('\n', place);
33632434Sbostic 	}
33732434Sbostic }
33832434Sbostic 
33932434Sbostic initialize()
34032434Sbostic {
34132434Sbostic 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
34232434Sbostic 		signal(SIGINT, delexit);
34332434Sbostic 	/*
34432434Sbostic 	 *	Install symbols in the table
34532434Sbostic 	 */
34632434Sbostic 	symtabinit();
34732434Sbostic 	syminstall();
34832434Sbostic 	/*
34932434Sbostic 	 *	Build the expression parser accelerator token sets
35032434Sbostic 	 */
35132434Sbostic 	buildtokensets();
35232434Sbostic }
35332434Sbostic 
35432434Sbostic zeroorigins()
35532434Sbostic {
35632434Sbostic 	register	int	locindex;
35732434Sbostic 	/*
35832434Sbostic 	 *	Mark usedot: the first NLOC slots are for named text segments,
35932434Sbostic 	 *	the next for named data segments.
36032434Sbostic 	 */
36132434Sbostic 	for (locindex = 0; locindex < NLOC; locindex++){
36232434Sbostic 		usedot[locindex].e_xtype = XTEXT;
36332434Sbostic 		usedot[NLOC + locindex].e_xtype = XDATA;
36432434Sbostic 		usedot[locindex].e_xvalue = 0;
36532434Sbostic 		usedot[NLOC + locindex].e_xvalue = 0;
36632434Sbostic 	}
36732434Sbostic }
36832434Sbostic 
36932434Sbostic zerolocals()
37032434Sbostic {
37132434Sbostic 	register	int	i;
37232434Sbostic 
37332434Sbostic 	for (i = 0; i <= 9; i++) {
37432434Sbostic 		lgensym[i] = 1;
37532434Sbostic 		genref[i] = 0;
37632434Sbostic 	}
37732434Sbostic }
37832434Sbostic 
37932434Sbostic i_pass1()
38032434Sbostic {
38132434Sbostic 	FILE	*tempopen();
38232434Sbostic 	if (useVM == 0)
38332434Sbostic 		tokfile = tempopen(tokfilename, "T");
38432434Sbostic 	strfile = tempopen(strfilename, "S");
38532434Sbostic 	/*
38632434Sbostic 	 *	write out the string length.
38732434Sbostic 	 *	This will be overwritten when the
38832434Sbostic 	 *	strings are tacked onto the growing a.out file
38932434Sbostic 	 */
39032434Sbostic 	strfilepos = sizeof(int);
39132434Sbostic 	fwrite(&strfilepos, sizeof(int), 1, strfile);
39232434Sbostic 
39332434Sbostic 	inittokfile();
39432434Sbostic 	initijxxx();
39532434Sbostic }
39632434Sbostic 
39732434Sbostic FILE *tempopen(tname, part)
39832434Sbostic 	char	*tname;
39932434Sbostic 	char	*part;
40032434Sbostic {
40132434Sbostic 	FILE	*file;
402*32435Sbostic 	(void)sprintf(tname, "%s%sas%s%05d",
40332434Sbostic 		tmpdirprefix,
40432434Sbostic 		(tmpdirprefix[strlen(tmpdirprefix)-1] != '/') ? "/" : 0,
40532434Sbostic 		part,
40632434Sbostic 		getpid());
40732434Sbostic 	file = fopen(tname, "w");
40832434Sbostic 	if (file == NULL) {
40932434Sbostic 		yyerror("Bad pass 1 temporary file for writing %s", tname);
41032434Sbostic 		delexit();
41132434Sbostic 	}
41232434Sbostic 	return(file);
41332434Sbostic }
41432434Sbostic 
41532434Sbostic pass1()
41632434Sbostic {
41732434Sbostic 	register	int	i;
41832434Sbostic 
41932434Sbostic 	passno = 1;
42032434Sbostic 	dotp = &usedot[0];
42132434Sbostic 	txtfil = (BFILE *)0;
42232434Sbostic 	relfil = (struct relbufdesc *)0;
42332434Sbostic 
42432434Sbostic 	if (ninfiles == 0){		/*take the input from stdin directly*/
42532434Sbostic 		lineno = 1;
42632434Sbostic 		dotsname = "<stdin>";
42732434Sbostic 
42832434Sbostic 		yyparse();
42932434Sbostic 	} else {		/*we have the names tanked*/
43032434Sbostic 		for (i = 0; i < ninfiles; i++){
43132434Sbostic 			new_dot_s(innames[i]);
43232434Sbostic 			if (freopen(innames[i], "r", stdin) == NULL) {
43332434Sbostic 				yyerror( "Can't open source file %s\n",
43432434Sbostic 					innames[i]);
43532434Sbostic 				exit(2);
43632434Sbostic 			}
43732434Sbostic 			/* stdio is NOT used to read the input characters */
43832434Sbostic 			/* we use read directly, into our own buffers */
43932434Sbostic 			yyparse();
44032434Sbostic 		}
44132434Sbostic 	}
44232434Sbostic 
44332434Sbostic 	closetokfile();		/*kick out the last buffered intermediate text*/
44432434Sbostic }
44532434Sbostic 
44632434Sbostic testlocals()
44732434Sbostic {
44832434Sbostic 	register	int	i;
44932434Sbostic 	for (i = 0; i <= 9; i++) {
45032434Sbostic 		if (genref[i])
45132434Sbostic 			yyerror("Reference to undefined local label %df", i);
45232434Sbostic 		lgensym[i] = 1;
45332434Sbostic 		genref[i] = 0;
45432434Sbostic 	}
45532434Sbostic }
45632434Sbostic 
45732434Sbostic pass1_5()
45832434Sbostic {
45932434Sbostic 	sortsymtab();
46032434Sbostic #ifdef DEBUG
46132434Sbostic 	if (debug) dumpsymtab();
46232434Sbostic #endif
46332434Sbostic 	jxxxfix();
46432434Sbostic #ifdef DEBUG
46532434Sbostic 	if (debug) dumpsymtab();
46632434Sbostic #endif
46732434Sbostic }
46832434Sbostic 
46932434Sbostic open_a_out()
47032434Sbostic {
47132434Sbostic 	/*
47232434Sbostic 	 *	Open up the a.out file now, and get set to build
47332434Sbostic 	 *	up offsets into it for all of the various text,data
47432434Sbostic 	 *	text relocation and data relocation segments.
47532434Sbostic 	 */
47632434Sbostic 	a_out_file = fopen(outfile, "w");
47732434Sbostic 	if (a_out_file == NULL) {
47832434Sbostic 		yyerror("Cannot create %s", outfile);
47932434Sbostic 		delexit();
48032434Sbostic 	}
48132434Sbostic 	biofd = a_out_file->_file;
48232434Sbostic 	a_out_off = 0;
48332434Sbostic }
48432434Sbostic 
48532434Sbostic roundsegments()
48632434Sbostic {
48732434Sbostic 	register	int	locindex;
48832434Sbostic 	register	long	v;
48932434Sbostic 	/*
49032434Sbostic 	 *	round and assign text segment origins
49132434Sbostic 	 *	the exec header always goes in usefile[0]
49232434Sbostic 	 */
49332434Sbostic 	tsize = 0;
49432434Sbostic 	for (locindex=0; locindex<NLOC; locindex++) {
49532434Sbostic 		v = round(usedot[locindex].e_xvalue, FW);
49632434Sbostic 		usedot[locindex].e_xvalue = tsize;
49732434Sbostic 		if ((locindex == 0) || (v != 0) ){
49832434Sbostic 			usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE));
49932434Sbostic 			bopen(usefile[locindex], a_out_off);
50032434Sbostic 			if (locindex == 0)
50132434Sbostic 				a_out_off = sizeof (struct exec);
50232434Sbostic 		} else {
50332434Sbostic 			usefile[locindex] = (BFILE *)-1;
50432434Sbostic 		}
50532434Sbostic 		tsize += v;
50632434Sbostic 		a_out_off += v;
50732434Sbostic 	}
50832434Sbostic 	/*
50932434Sbostic 	 *		Round and assign data segment origins.
51032434Sbostic 	 */
51132434Sbostic 	datbase = round(tsize, FW);
51232434Sbostic 	for (locindex=0; locindex<NLOC; locindex++) {
51332434Sbostic 		v = round(usedot[NLOC+locindex].e_xvalue, FW);
51432434Sbostic 		usedot[NLOC+locindex].e_xvalue = datbase + dsize;
51532434Sbostic 		if (v != 0){
51632434Sbostic 			usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE));
51732434Sbostic 			bopen(usefile[NLOC + locindex], a_out_off);
51832434Sbostic 		} else {
51932434Sbostic 			usefile[NLOC + locindex] = (BFILE *)-1;
52032434Sbostic 		}
52132434Sbostic 		dsize += v;
52232434Sbostic 		a_out_off += v;
52332434Sbostic 	}
52432434Sbostic 	/*
52532434Sbostic 	 *	Assign final values to symbols
52632434Sbostic 	 */
52732434Sbostic 	hdr.a_bss = dsize;
52832434Sbostic 	freezesymtab();		/* this touches hdr.a_bss */
52932434Sbostic 	stabfix();
53032434Sbostic 	/*
53132434Sbostic 	 *	Set up the relocation information "files" to
53232434Sbostic 	 *	be zero; outrel takes care of the rest
53332434Sbostic 	 */
53432434Sbostic 	for (locindex = 0; locindex < NLOC + NLOC; locindex++){
53532434Sbostic 		rusefile[locindex] = (struct relbufdesc *)0;
53632434Sbostic 	}
53732434Sbostic }
53832434Sbostic 
53932434Sbostic build_hdr()
54032434Sbostic {
54132434Sbostic 	/*
54232434Sbostic 	 *	Except for the text and data relocation sizes,
54332434Sbostic 	 *	calculate the final values for the header
54432434Sbostic 	 *
54532434Sbostic 	 *	Write out the initial copy; we to come
54632434Sbostic 	 *	back later and patch up a_trsize and a_drsize,
54732434Sbostic 	 *	and overwrite this first version of the header.
54832434Sbostic 	 */
54932434Sbostic 	hdr.a_magic = MAGIC;
55032434Sbostic 	hdr.a_text = tsize;
55132434Sbostic 	hdr.a_data = dsize;
55232434Sbostic 	hdr.a_bss -= dsize;
55332434Sbostic 	hdr.a_syms = sizesymtab();	/* Does not include string pool length */
55432434Sbostic 	hdr.a_entry = 0;
55532434Sbostic 	hdr.a_trsize = 0;
55632434Sbostic 	hdr.a_drsize = 0;
55732434Sbostic 
55832434Sbostic 	bwrite((char *)&hdr, sizeof(hdr), usefile[0]);
55932434Sbostic }
56032434Sbostic 
56132434Sbostic i_pass2()
56232434Sbostic {
56332434Sbostic 	if (useVM == 0) {
56432434Sbostic 		fclose(tokfile);
56532434Sbostic 		tokfile = fopen(tokfilename, "r");
56632434Sbostic 		if (tokfile==NULL) {
56732434Sbostic 		   yyerror("Bad pass 2 temporary file for reading %s", tokfilename);
56832434Sbostic 		   delexit();
56932434Sbostic 		}
57032434Sbostic 	}
57132434Sbostic 	fclose(strfile);
57232434Sbostic 	strfile = fopen(strfilename, "r");
57332434Sbostic }
57432434Sbostic 
57532434Sbostic pass2()
57632434Sbostic {
57732434Sbostic #ifdef DEBUG
57832434Sbostic 	if (debug)
57932434Sbostic 		printf("\n\n\n\t\tPASS 2\n\n\n\n");
58032434Sbostic #endif DEBUG
58132434Sbostic 	passno = 2;
58232434Sbostic 	lineno = 1;
58332434Sbostic 	if (liston && ninfiles != 0)
58432434Sbostic 	{
58532434Sbostic 		char ch;
58632434Sbostic 		source = fopen (innames[ind++], "r");
587*32435Sbostic 		(void)sprintf (layoutpos, "%4ld  00000000    ", lineno);
58832434Sbostic 		layoutpos += LHEAD;
58932434Sbostic 		ch = getc (source);
59032434Sbostic 		if (ch == EOF)
59132434Sbostic 		{
59232434Sbostic 			if (ind == ninfiles)
59332434Sbostic 				endofsource = 1;
59432434Sbostic 			else
59532434Sbostic 				source = fopen (innames[ind++], "r");
59632434Sbostic 		}
59732434Sbostic 		else
59832434Sbostic 			ungetc (ch, source);
59932434Sbostic 	}
60032434Sbostic 	else
60132434Sbostic 		endofsource = 1;
60232434Sbostic 	dotp = &usedot[0];
60332434Sbostic 	txtfil = usefile[0];	/* already opened (always!) */
60432434Sbostic 	relfil = 0;		/* outrel takes care of the rest */
60532434Sbostic 	initoutrel();
60632434Sbostic 
60732434Sbostic 	inittokfile();
60832434Sbostic 
60932434Sbostic 	yyparse();
61032434Sbostic 
61132434Sbostic 	closetokfile();
61232434Sbostic }
61332434Sbostic 
61432434Sbostic fillsegments()
61532434Sbostic {
61632434Sbostic 	int	locindex;
61732434Sbostic 	/*
61832434Sbostic 	 *	Round text and data segments to FW by appending zeros
61932434Sbostic 	 */
62032434Sbostic 	for (locindex = 0; locindex < NLOC + NLOC; locindex++) {
62132434Sbostic 		if (usefile[locindex]) {
62232434Sbostic 			txtfil = usefile[locindex];
62332434Sbostic 			dotp = &usedot[locindex];
62432434Sbostic 			while (usedot[locindex].e_xvalue & FW)
62532434Sbostic 				outb(0);
62632434Sbostic 		}
62732434Sbostic 	}
62832434Sbostic }
62932434Sbostic 
63032434Sbostic reloc_syms()
63132434Sbostic {
63232434Sbostic 	u_long	closerelfil();
63332434Sbostic 	/*
63432434Sbostic 	 *	Move the relocation information to a.out
63532434Sbostic 	 *	a_out_off is the offset so far:
63632434Sbostic 	 *	exec + text segments + data segments
63732434Sbostic 	 */
63832434Sbostic 	relocfile = (BFILE *)Calloc(1,sizeof(BFILE));
63932434Sbostic 	bopen(relocfile, a_out_off);
64032434Sbostic 	a_out_off += closeoutrel(relocfile);
64132434Sbostic 
64232434Sbostic 	hdr.a_trsize = trsize;
64332434Sbostic 	hdr.a_drsize = drsize;
64432434Sbostic 	if (readonlydata) {
64532434Sbostic 		hdr.a_text += hdr.a_data;
64632434Sbostic 		hdr.a_data = 0;
64732434Sbostic 		hdr.a_trsize += hdr.a_drsize;
64832434Sbostic 		hdr.a_drsize = 0;
64932434Sbostic 	}
65032434Sbostic 	/*
65132434Sbostic 	 *	Output the symbol table and the string pool
65232434Sbostic 	 *
65332434Sbostic 	 *	We must first rewind the string pool file to its beginning,
65432434Sbostic 	 *	in case it was seek'ed into for fetching ascii and asciz
65532434Sbostic 	 *	strings.
65632434Sbostic 	 */
65732434Sbostic 	fseek(strfile, 0, 0);
65832434Sbostic 	symwrite(relocfile);
65932434Sbostic }
66032434Sbostic 
66132434Sbostic fix_a_out()
66232434Sbostic {
66332434Sbostic 	if (lseek(a_out_file->_file, 0L, 0) < 0L)
66432434Sbostic 		yyerror("Reposition for header rewrite fails");
66532434Sbostic 	if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0)
66632434Sbostic 		yyerror("Rewrite of header fails");
66732434Sbostic }
66832434Sbostic 
66932434Sbostic delexit()
67032434Sbostic {
67132434Sbostic 	delete();
67232434Sbostic 	if (passno == 2){
67332434Sbostic 		unlink(outfile);
67432434Sbostic 	}
67532434Sbostic 	exit(1);
67632434Sbostic }
67732434Sbostic 
67832434Sbostic delete()
67932434Sbostic {
68032434Sbostic 	if (useVM == 0 || tokfilename[0])
68132434Sbostic 		unlink(tokfilename);
68232434Sbostic 	if (strfilename[0])
68332434Sbostic 		unlink(strfilename);
68432434Sbostic }
68532434Sbostic 
68632434Sbostic sawabort()
68732434Sbostic {
68832434Sbostic 	char	*fillinbuffer();
68932434Sbostic 	while (fillinbuffer() != (char *)0)
69032434Sbostic 		continue;
69132434Sbostic 	delete();
69232434Sbostic 	exit(1);	/*although the previous pass will also exit non zero*/
69332434Sbostic }
69432434Sbostic 
69532434Sbostic panic(fmt, a1, a2, a3, a4)
69632434Sbostic 	char	*fmt;
69732434Sbostic 	/*VARARGS 1*/
69832434Sbostic {
69932434Sbostic 	yyerror("Assembler panic: bad internal data structure.");
70032434Sbostic 	yyerror(fmt, a1, a2, a3, a4);
70132434Sbostic 	delete();
70232434Sbostic 	abort();
70332434Sbostic }
704