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