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*25246Smckusick static char sccsid[] = "@(#)asmain.c 5.2 (Berkeley) 10/21/85"; 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" 25596Sbill 2616071Sralph #include <sys/stat.h> 2716071Sralph 28*25246Smckusick #define unix_lang_name "VAX/UNIX Assembler V10/21/85 5.2" 29596Sbill /* 30596Sbill * variables to manage reading the assembly source files 31596Sbill */ 32596Sbill char *dotsname; /*the current file name; managed by the parser*/ 33596Sbill int lineno; /*current line number; managed by the parser*/ 34643Sbill char **innames; /*names of the files being assembled*/ 35596Sbill int ninfiles; /*how many interesting files there are*/ 36596Sbill /* 37596Sbill * Flags settable from the argv process argument list 38596Sbill */ 39596Sbill int silent = 0; /*don't complain about any errors*/ 40596Sbill int savelabels = 0; /*write the labels to the a.out file*/ 41596Sbill int d124 = 4; /*default allocate 4 bytes for unknown pointers*/ 4215560Srrh int maxalign = 2; /*default .align maximum*/ 43596Sbill int anyerrs = 0; /*no errors yet*/ 445826Srrh int anywarnings=0; /*no warnings yet*/ 45596Sbill int orgwarn = 0; /*Bad origins*/ 46596Sbill int passno = 1; /* current pass*/ 47636Shenry int jxxxJUMP = 0; /* in jxxxes that branch too far, use jmp instead of brw */ 48638Sbill int readonlydata = 0; /* initialzed data -> text space */ 49596Sbill 505826Srrh int nGHnumbers = 0; /* GH numbers used */ 515826Srrh int nGHopcodes = 0; /* GH opcodes used */ 525826Srrh int nnewopcodes = 0; /* new opcodes used */ 535826Srrh 54596Sbill #ifdef DEBUG 55596Sbill int debug = 0; 56596Sbill int toktrace = 0; 57596Sbill #endif 58596Sbill 5913518Srrh int useVM = 0; 60596Sbill 61596Sbill char *endcore; /*where to get more symbol space*/ 62596Sbill 63596Sbill /* 64596Sbill * Managers of the a.out file. 65596Sbill */ 66596Sbill struct exec hdr; 67638Sbill #define MAGIC 0407 68596Sbill u_long tsize; /* total text size */ 69596Sbill u_long dsize; /* total data size */ 70596Sbill u_long datbase; /* base of the data segment */ 71596Sbill u_long trsize; /* total text relocation size */ 72596Sbill u_long drsize; /* total data relocation size */ 73596Sbill 74596Sbill /* 75596Sbill * Information about the current segment is accumulated in 76596Sbill * usedot; the most important information stored is the 77596Sbill * accumulated size of each of the text and data segments 78596Sbill * 79596Sbill * dotp points to the correct usedot expression for the current segment 80596Sbill */ 81596Sbill struct exp usedot[NLOC+NLOC]; /* info about all segments */ 82596Sbill struct exp *dotp; /* data/text location pointer */ 83596Sbill /* 8413512Srrh * The inter pass temporary token file is opened and closed by stdio, but 85596Sbill * is written to using direct read/write, as the temporary file 86596Sbill * is composed of buffers exactly BUFSIZ long. 87596Sbill */ 8813512Srrh FILE *tokfile; /* interpass communication file */ 8913512Srrh char tokfilename[TNAMESIZE]; 90596Sbill /* 9113512Srrh * The string file is the string table 9213512Srrh * cat'ed to the end of the built up a.out file 9313512Srrh */ 9413512Srrh FILE *strfile; /* interpass string file */ 9513512Srrh char strfilename[TNAMESIZE]; 9613512Srrh int strfilepos = 0; /* position within the string file */ 9713512Srrh /* 98596Sbill * a.out is created during the second pass. 99596Sbill * It is opened by stdio, but is filled with the parallel 100596Sbill * block I/O library 101596Sbill */ 102596Sbill char *outfile = "a.out"; 103596Sbill FILE *a_out_file; 104596Sbill off_t a_out_off; /* cumulative offsets for segments */ 105596Sbill /* 106596Sbill * The logical files containing the assembled data for each of 107596Sbill * the text and data segments are 108596Sbill * managed by the parallel block I/O library. 109596Sbill * a.out is logically opened in many places at once to 110596Sbill * receive the assembled data from the various segments as 111596Sbill * it all trickles in, but is physically opened only once 112596Sbill * to minimize file overhead. 113596Sbill */ 114596Sbill BFILE *usefile[NLOC+NLOC]; /* text/data files */ 115596Sbill BFILE *txtfil; /* current text/data file */ 116596Sbill /* 117596Sbill * Relocation information is accumulated seperately for each 118596Sbill * segment. This is required by the old loader (from BTL), 119596Sbill * but not by the new loader (Bill Joy). 120596Sbill * 121596Sbill * However, the size of the relocation information can not be computed 122596Sbill * during or after the 1st pass because the ''absoluteness' of values 123596Sbill * is unknown until all locally declared symbols have been seen. 124596Sbill * Thus, the size of the relocation information is only 125596Sbill * known after the second pass is finished. 126596Sbill * This obviates the use of the block I/O 127596Sbill * library, which requires knowing the exact offsets in a.out. 128596Sbill * 129596Sbill * So, we save the relocation information internally (we don't 130596Sbill * go to internal files to minimize overhead). 131596Sbill * 132596Sbill * Empirically, we studied 259 files composing the system, 133596Sbill * two compilers and a compiler generator: (all of which have 134596Sbill * fairly large source files) 135596Sbill * 136596Sbill * Number of files = 259 137596Sbill * Number of non zero text reloc files: 233 138596Sbill * Number of non zero data reloc files: 53 139596Sbill * Average text relocation = 889 140596Sbill * Average data relocation = 346 141596Sbill * Number of files > BUFSIZ text relocation = 71 142596Sbill * Number of files > BUFSIZ data relocation = 6 143596Sbill * 144596Sbill * For compiled C code, there is usually one text segment and two 145596Sbill * data segments; we see that allocating our own buffers and 146596Sbill * doing our internal handling of relocation information will, 147596Sbill * on the average, not use more memory than taken up by the buffers 148596Sbill * allocated for doing file I/O in parallel to a number of file. 149596Sbill * 150596Sbill * If we are assembling with the -V option, we 151596Sbill * use the left over token buffers from the 2nd pass, 152596Sbill * otherwise, we create our own. 153596Sbill * 154596Sbill * When the 2nd pass is complete, closeoutrel flushes the token 155596Sbill * buffers out to a BFILE. 156596Sbill * 157596Sbill * The internals to relbufdesc are known only in assyms.c 158596Sbill * 159596Sbill * outrel constructs the relocation information. 160596Sbill * closeoutrel flushes the relocation information to relfil. 161596Sbill */ 162596Sbill struct relbufdesc *rusefile[NLOC+NLOC]; 163596Sbill struct relbufdesc *relfil; /* un concatnated relocation info */ 164596Sbill BFILE *relocfile; /* concatnated relocation info */ 165596Sbill /* 166596Sbill * Once the relocation information has been written, 167596Sbill * we can write out the symbol table using the Block I/O 168596Sbill * mechanisms, as we once again know the offsets into 169596Sbill * the a.out file. 170596Sbill * 171596Sbill * We use relfil to output the symbol table information. 172596Sbill */ 17313518Srrh char *tmpdirprefix = "/tmp/"; 174596Sbill int delexit(); 175596Sbill 176596Sbill main(argc, argv) 177596Sbill int argc; 178596Sbill char **argv; 179596Sbill { 1805826Srrh char *sbrk(); 181596Sbill 18213512Srrh tokfilename[0] = 0; 18313512Srrh strfilename[0] = 0; 1845826Srrh endcore = sbrk(0); 185596Sbill 186596Sbill argprocess(argc, argv); /* process argument lists */ 187596Sbill if (anyerrs) exit(1); 188596Sbill 189596Sbill initialize(); 190596Sbill zeroorigins(); /* set origins to zero */ 191596Sbill zerolocals(); /* fix local label counters */ 192596Sbill 193596Sbill i_pass1(); /* open temp files, etc */ 194596Sbill pass1(); /* first pass through .s files */ 195596Sbill testlocals(); /* check for undefined locals */ 196596Sbill if (anyerrs) delexit(); 197596Sbill 198596Sbill pass1_5(); /* resolve jxxx */ 199596Sbill if (anyerrs) delexit(); 200596Sbill 201596Sbill open_a_out(); /* open a.out */ 202679Shenry roundsegments(); /* round segments to FW */ 203596Sbill build_hdr(); /* build initial header, and output */ 204596Sbill 205596Sbill i_pass2(); /* reopen temporary file, etc */ 206596Sbill pass2(); /* second pass through the virtual .s */ 207596Sbill if (anyerrs) delexit(); 208596Sbill 209679Shenry fillsegments(); /* fill segments with 0 to FW */ 210596Sbill reloc_syms(); /* dump relocation and symbol table */ 211596Sbill 212596Sbill delete(); /* remove tmp file */ 213596Sbill bflush(); /* close off block I/O view of a.out */ 214596Sbill fix_a_out(); /* add in text and data reloc counts */ 215596Sbill 216596Sbill if (anyerrs == 0 && orgwarn) 217596Sbill yyerror("Caution: absolute origins.\n"); 2185826Srrh 2195826Srrh if (nGHnumbers) 2205826Srrh yywarning("Caution: G or H format floating point numbers"); 2215826Srrh if (nGHopcodes) 2225826Srrh yywarning("Caution: G or H format floating point operators"); 2235826Srrh if (nnewopcodes) 2245826Srrh yywarning("Caution: New Opcodes"); 2255826Srrh if (nGHnumbers || nGHopcodes || nnewopcodes) 2265826Srrh yywarning("These are not defined for all implementations of the VAX architecture.\n"); 2275826Srrh 228596Sbill exit(anyerrs != 0); 22913518Srrh } 230596Sbill 231596Sbill argprocess(argc, argv) 232596Sbill int argc; 233596Sbill char *argv[]; 234596Sbill { 235596Sbill register char *cp; 236596Sbill 237596Sbill ninfiles = 0; 238596Sbill silent = 0; 239596Sbill #ifdef DEBUG 240596Sbill debug = 0; 241596Sbill #endif 242643Sbill innames = (char **)ClearCalloc(argc+1, sizeof (innames[0])); 243596Sbill dotsname = "<argv error>"; 244596Sbill while (argc > 1) { 245643Sbill if (argv[1][0] != '-') 246643Sbill innames[ninfiles++] = argv[1]; 247643Sbill else { 248596Sbill cp = argv[1] + 1; 249596Sbill /* 250596Sbill * We can throw away single minus signs, so 251596Sbill * that make scripts for the PDP 11 assembler work 252596Sbill * on this assembler too 253596Sbill */ 254596Sbill while (*cp){ 255596Sbill switch(*cp++){ 256596Sbill default: 257596Sbill yyerror("Unknown flag: %c", *--cp); 258596Sbill cp++; 259596Sbill break; 2606559Srrh case 'v': 2616559Srrh selfwhat(stdout); 2626559Srrh exit(1); 263596Sbill case 'd': 264596Sbill d124 = *cp++ - '0'; 265596Sbill if ( (d124 != 1) && (d124 != 2) && 266596Sbill (d124 != 4)){ 267596Sbill yyerror("-d[124] only"); 268596Sbill exit(1); 269596Sbill } 270596Sbill break; 27115560Srrh case 'a': 27215560Srrh maxalign = atoi(cp+1); 27315560Srrh for (cp++; isdigit(*cp); cp++) 27415560Srrh /*VOID*/; 27515560Srrh if ( (maxalign > 16) || (maxalign < 0)){ 27615560Srrh yyerror("-a: 0<=align<=16"); 27715560Srrh exit(1); 27815560Srrh } 27915560Srrh break; 280596Sbill case 'o': 281596Sbill if (argc < 3){ 282596Sbill yyerror("-o what???"); 283596Sbill exit(1); 284596Sbill } 285596Sbill outfile = argv[2]; 286596Sbill bumpone: 287596Sbill argc -= 2; 288596Sbill argv += 2; 289596Sbill goto nextarg; 290596Sbill 291596Sbill case 't': 292596Sbill if (argc < 3){ 293596Sbill yyerror("-t what???"); 294596Sbill exit(1); 295596Sbill } 296596Sbill tmpdirprefix = argv[2]; 297596Sbill goto bumpone; 298596Sbill 299596Sbill case 'V': 300596Sbill useVM = 1; 301596Sbill break; 302596Sbill case 'W': 303596Sbill silent = 1; 304596Sbill break; 305596Sbill case 'L': 306596Sbill savelabels = 1; 307596Sbill break; 308636Shenry case 'J': 309636Shenry jxxxJUMP = 1; 310636Shenry break; 311596Sbill #ifdef DEBUG 312596Sbill case 'D': 313596Sbill debug = 1; 314596Sbill break; 315596Sbill case 'T': 316596Sbill toktrace = 1; 317596Sbill break; 318596Sbill #endif 319638Sbill case 'R': 320638Sbill readonlydata = 1; 321638Sbill break; 322596Sbill } /*end of the switch*/ 323596Sbill } /*end of pulling out all arguments*/ 324596Sbill } /*end of a flag argument*/ 325596Sbill --argc; ++argv; 326596Sbill nextarg:; 327596Sbill } 328643Sbill /* innames[ninfiles] = 0; */ 329596Sbill } 3306559Srrh /* 3316559Srrh * poke through the data space and find all sccs identifiers. 3326559Srrh * We assume: 3336559Srrh * a) that extern char **environ; is the first thing in the bss 3346559Srrh * segment (true, if one is using the new version of cmgt.crt0.c) 3356559Srrh * b) that the sccsid's have not been put into text space. 3366559Srrh */ 3376559Srrh selfwhat(place) 3386559Srrh FILE *place; 3396559Srrh { 3406559Srrh extern char **environ; 3416559Srrh register char *ub; 3426559Srrh register char *cp; 3436559Srrh register char *pat; 3446559Srrh char *sbrk(); 345596Sbill 3466559Srrh for (cp = (char *)&environ, ub = sbrk(0); cp < ub; cp++){ 3476559Srrh if (cp[0] != '@') continue; 3486559Srrh if (cp[1] != '(') continue; 3496559Srrh if (cp[2] != '#') continue; 3506559Srrh if (cp[3] != ')') continue; 3516559Srrh fputc('\t', place); 3526559Srrh for (cp += 4; cp < ub; cp++){ 3536559Srrh if (*cp == 0) break; 3546559Srrh if (*cp == '>') break; 3556559Srrh if (*cp == '\n') break; 3566559Srrh fputc(*cp, place); 3576559Srrh } 3586559Srrh fputc('\n', place); 3596559Srrh } 3606559Srrh } 3616559Srrh 362596Sbill initialize() 363596Sbill { 364596Sbill if (signal(SIGINT, SIG_IGN) != SIG_IGN) 365596Sbill signal(SIGINT, delexit); 366596Sbill /* 367596Sbill * Install symbols in the table 368596Sbill */ 369596Sbill symtabinit(); 370596Sbill syminstall(); 371596Sbill /* 372596Sbill * Build the expression parser accelerator token sets 373596Sbill */ 374596Sbill buildtokensets(); 375596Sbill } 376596Sbill 377596Sbill zeroorigins() 378596Sbill { 379596Sbill register int locindex; 380596Sbill /* 381596Sbill * Mark usedot: the first NLOC slots are for named text segments, 382596Sbill * the next for named data segments. 383596Sbill */ 384596Sbill for (locindex = 0; locindex < NLOC; locindex++){ 385631Shenry usedot[locindex].e_xtype = XTEXT; 386631Shenry usedot[NLOC + locindex].e_xtype = XDATA; 387631Shenry usedot[locindex].e_xvalue = 0; 388631Shenry usedot[NLOC + locindex].e_xvalue = 0; 389596Sbill } 390596Sbill } 391596Sbill 392596Sbill zerolocals() 393596Sbill { 394596Sbill register int i; 395596Sbill 396596Sbill for (i = 0; i <= 9; i++) { 397596Sbill lgensym[i] = 1; 398596Sbill genref[i] = 0; 399596Sbill } 400596Sbill } 401596Sbill 402596Sbill i_pass1() 403596Sbill { 40413512Srrh FILE *tempopen(); 40513512Srrh if (useVM == 0) 40613512Srrh tokfile = tempopen(tokfilename, "T"); 40713512Srrh strfile = tempopen(strfilename, "S"); 40813512Srrh /* 40913512Srrh * write out the string length. 41013512Srrh * This will be overwritten when the 41113512Srrh * strings are tacked onto the growing a.out file 41213512Srrh */ 41313512Srrh strfilepos = sizeof(int); 41413512Srrh fwrite(&strfilepos, sizeof(int), 1, strfile); 415596Sbill 41613512Srrh inittokfile(); 417636Shenry initijxxx(); 418596Sbill } 419596Sbill 42013512Srrh FILE *tempopen(tname, part) 42113512Srrh char *tname; 42213512Srrh char *part; 42313512Srrh { 42413512Srrh FILE *file; 42513512Srrh sprintf(tname, "%s%sas%s%05d", 42613512Srrh tmpdirprefix, 427*25246Smckusick (tmpdirprefix[strlen(tmpdirprefix)-1] != '/') ? "/" : "", 42813512Srrh part, 42913512Srrh getpid()); 43013512Srrh file = fopen(tname, "w"); 43113512Srrh if (file == NULL) { 43213512Srrh yyerror("Bad pass 1 temporary file for writing %s", tname); 43313512Srrh delexit(); 43413512Srrh } 43513512Srrh return(file); 43613512Srrh } 43713512Srrh 438596Sbill pass1() 439596Sbill { 440596Sbill register int i; 441596Sbill 442596Sbill passno = 1; 443596Sbill dotp = &usedot[0]; 444596Sbill txtfil = (BFILE *)0; 445596Sbill relfil = (struct relbufdesc *)0; 446596Sbill 447596Sbill if (ninfiles == 0){ /*take the input from stdin directly*/ 448596Sbill lineno = 1; 449596Sbill dotsname = "<stdin>"; 450596Sbill 451596Sbill yyparse(); 452596Sbill } else { /*we have the names tanked*/ 453596Sbill for (i = 0; i < ninfiles; i++){ 454596Sbill new_dot_s(innames[i]); 455596Sbill if (freopen(innames[i], "r", stdin) == NULL) { 456596Sbill yyerror( "Can't open source file %s\n", 457596Sbill innames[i]); 458596Sbill exit(2); 459596Sbill } 460596Sbill /* stdio is NOT used to read the input characters */ 461596Sbill /* we use read directly, into our own buffers */ 462596Sbill yyparse(); 463596Sbill } 464596Sbill } 465596Sbill 46613512Srrh closetokfile(); /*kick out the last buffered intermediate text*/ 467596Sbill } 468596Sbill 469596Sbill testlocals() 470596Sbill { 471596Sbill register int i; 472596Sbill for (i = 0; i <= 9; i++) { 473596Sbill if (genref[i]) 474596Sbill yyerror("Reference to undefined local label %df", i); 475596Sbill lgensym[i] = 1; 476596Sbill genref[i] = 0; 477596Sbill } 478596Sbill } 479596Sbill 480596Sbill pass1_5() 481596Sbill { 482596Sbill sortsymtab(); 483596Sbill #ifdef DEBUG 484596Sbill if (debug) dumpsymtab(); 485596Sbill #endif 486596Sbill jxxxfix(); 487596Sbill #ifdef DEBUG 488596Sbill if (debug) dumpsymtab(); 489596Sbill #endif 490596Sbill } 491596Sbill 492596Sbill open_a_out() 493596Sbill { 49416071Sralph struct stat stb; 49516071Sralph 496596Sbill /* 497596Sbill * Open up the a.out file now, and get set to build 498596Sbill * up offsets into it for all of the various text,data 499596Sbill * text relocation and data relocation segments. 500596Sbill */ 501596Sbill a_out_file = fopen(outfile, "w"); 502596Sbill if (a_out_file == NULL) { 503596Sbill yyerror("Cannot create %s", outfile); 504596Sbill delexit(); 505596Sbill } 506596Sbill biofd = a_out_file->_file; 50716071Sralph fstat(biofd, &stb); 50816071Sralph biobufsize = stb.st_blksize; 509596Sbill a_out_off = 0; 510596Sbill } 511596Sbill 512596Sbill roundsegments() 513596Sbill { 514596Sbill register int locindex; 515596Sbill register long v; 516596Sbill /* 517596Sbill * round and assign text segment origins 518596Sbill * the exec header always goes in usefile[0] 519596Sbill */ 520596Sbill tsize = 0; 521596Sbill for (locindex=0; locindex<NLOC; locindex++) { 522679Shenry v = round(usedot[locindex].e_xvalue, FW); 523631Shenry usedot[locindex].e_xvalue = tsize; 524596Sbill if ((locindex == 0) || (v != 0) ){ 525596Sbill usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE)); 526596Sbill bopen(usefile[locindex], a_out_off); 527596Sbill if (locindex == 0) 528596Sbill a_out_off = sizeof (struct exec); 529596Sbill } else { 530596Sbill usefile[locindex] = (BFILE *)-1; 531596Sbill } 532596Sbill tsize += v; 533596Sbill a_out_off += v; 534596Sbill } 535596Sbill /* 536596Sbill * Round and assign data segment origins. 537596Sbill */ 538679Shenry datbase = round(tsize, FW); 539596Sbill for (locindex=0; locindex<NLOC; locindex++) { 540679Shenry v = round(usedot[NLOC+locindex].e_xvalue, FW); 541631Shenry usedot[NLOC+locindex].e_xvalue = datbase + dsize; 542596Sbill if (v != 0){ 543596Sbill usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE)); 544596Sbill bopen(usefile[NLOC + locindex], a_out_off); 545596Sbill } else { 546596Sbill usefile[NLOC + locindex] = (BFILE *)-1; 547596Sbill } 548596Sbill dsize += v; 549596Sbill a_out_off += v; 550596Sbill } 551596Sbill /* 552596Sbill * Assign final values to symbols 553596Sbill */ 554596Sbill hdr.a_bss = dsize; 555596Sbill freezesymtab(); /* this touches hdr.a_bss */ 556596Sbill stabfix(); 557596Sbill /* 558596Sbill * Set up the relocation information "files" to 559596Sbill * be zero; outrel takes care of the rest 560596Sbill */ 561596Sbill for (locindex = 0; locindex < NLOC + NLOC; locindex++){ 562596Sbill rusefile[locindex] = (struct relbufdesc *)0; 563596Sbill } 564596Sbill } 565596Sbill 566596Sbill build_hdr() 567596Sbill { 568596Sbill /* 569596Sbill * Except for the text and data relocation sizes, 570596Sbill * calculate the final values for the header 571596Sbill * 572596Sbill * Write out the initial copy; we to come 573596Sbill * back later and patch up a_trsize and a_drsize, 574596Sbill * and overwrite this first version of the header. 575596Sbill */ 576596Sbill hdr.a_magic = MAGIC; 577596Sbill hdr.a_text = tsize; 578596Sbill hdr.a_data = dsize; 579596Sbill hdr.a_bss -= dsize; 580596Sbill hdr.a_syms = sizesymtab(); /* Does not include string pool length */ 581596Sbill hdr.a_entry = 0; 582596Sbill hdr.a_trsize = 0; 583596Sbill hdr.a_drsize = 0; 584596Sbill 585596Sbill bwrite((char *)&hdr, sizeof(hdr), usefile[0]); 586596Sbill } 587596Sbill 588596Sbill i_pass2() 589596Sbill { 590596Sbill if (useVM == 0) { 59113512Srrh fclose(tokfile); 59213512Srrh tokfile = fopen(tokfilename, "r"); 59313512Srrh if (tokfile==NULL) { 59413512Srrh yyerror("Bad pass 2 temporary file for reading %s", tokfilename); 595596Sbill delexit(); 596596Sbill } 597596Sbill } 59813512Srrh fclose(strfile); 59913512Srrh strfile = fopen(strfilename, "r"); 600596Sbill } 601596Sbill 602596Sbill pass2() 603596Sbill { 604596Sbill #ifdef DEBUG 605596Sbill if (debug) 606596Sbill printf("\n\n\n\t\tPASS 2\n\n\n\n"); 607596Sbill #endif DEBUG 608596Sbill passno = 2; 609596Sbill lineno = 1; 610596Sbill dotp = &usedot[0]; 611596Sbill txtfil = usefile[0]; /* already opened (always!) */ 612596Sbill relfil = 0; /* outrel takes care of the rest */ 613596Sbill initoutrel(); 614596Sbill 61513512Srrh inittokfile(); 616596Sbill 617596Sbill yyparse(); 618596Sbill 61913512Srrh closetokfile(); 620596Sbill } 621596Sbill 622596Sbill fillsegments() 623596Sbill { 624596Sbill int locindex; 625596Sbill /* 626679Shenry * Round text and data segments to FW by appending zeros 627596Sbill */ 628596Sbill for (locindex = 0; locindex < NLOC + NLOC; locindex++) { 629596Sbill if (usefile[locindex]) { 630596Sbill txtfil = usefile[locindex]; 631596Sbill dotp = &usedot[locindex]; 632679Shenry while (usedot[locindex].e_xvalue & FW) 633596Sbill outb(0); 634596Sbill } 635596Sbill } 636596Sbill } 637596Sbill 638596Sbill reloc_syms() 639596Sbill { 640596Sbill u_long closerelfil(); 641596Sbill /* 642596Sbill * Move the relocation information to a.out 643596Sbill * a_out_off is the offset so far: 644596Sbill * exec + text segments + data segments 645596Sbill */ 646596Sbill relocfile = (BFILE *)Calloc(1,sizeof(BFILE)); 647596Sbill bopen(relocfile, a_out_off); 648596Sbill a_out_off += closeoutrel(relocfile); 649596Sbill 650596Sbill hdr.a_trsize = trsize; 651596Sbill hdr.a_drsize = drsize; 652638Sbill if (readonlydata) { 653638Sbill hdr.a_text += hdr.a_data; 654638Sbill hdr.a_data = 0; 655638Sbill hdr.a_trsize += hdr.a_drsize; 656638Sbill hdr.a_drsize = 0; 657638Sbill } 658596Sbill /* 65913521Srrh * Output the symbol table and the string pool 66013512Srrh * 66113512Srrh * We must first rewind the string pool file to its beginning, 66213512Srrh * in case it was seek'ed into for fetching ascii and asciz 66313512Srrh * strings. 664596Sbill */ 66513512Srrh fseek(strfile, 0, 0); 666596Sbill symwrite(relocfile); 667596Sbill } 668596Sbill 669596Sbill fix_a_out() 670596Sbill { 6715826Srrh if (lseek(a_out_file->_file, 0L, 0) < 0L) 672596Sbill yyerror("Reposition for header rewrite fails"); 673596Sbill if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0) 674596Sbill yyerror("Rewrite of header fails"); 675596Sbill } 676596Sbill 677596Sbill delexit() 678596Sbill { 679596Sbill delete(); 680596Sbill if (passno == 2){ 681596Sbill unlink(outfile); 682596Sbill } 683596Sbill exit(1); 684596Sbill } 685596Sbill 686596Sbill delete() 687596Sbill { 68813512Srrh if (useVM == 0 || tokfilename[0]) 68913512Srrh unlink(tokfilename); 69013512Srrh if (strfilename[0]) 69113512Srrh unlink(strfilename); 692596Sbill } 693596Sbill 694596Sbill sawabort() 695596Sbill { 696596Sbill char *fillinbuffer(); 697596Sbill while (fillinbuffer() != (char *)0) 698596Sbill continue; 699596Sbill delete(); 700596Sbill exit(1); /*although the previous pass will also exit non zero*/ 701596Sbill } 702596Sbill 703596Sbill panic(fmt, a1, a2, a3, a4) 704596Sbill char *fmt; 705596Sbill /*VARARGS 1*/ 706596Sbill { 707596Sbill yyerror("Assembler panic: bad internal data structure."); 708596Sbill yyerror(fmt, a1, a2, a3, a4); 709596Sbill delete(); 710596Sbill abort(); 711596Sbill } 712