1: # include "link.h" 2: # define MAXREG 8 3: WORD getword(); 4: char *sprintf(); 5: 6: 7: /******************** variables with global scope ************************/ 8: 9: 10: extern struct objfile *File_root; /* root of object file link-list */ 11: extern struct symbol *Sym_root; /* root of symbol table */ 12: extern struct g_sect *Gsect_root; /* root of global psect tree */ 13: WORD Maxabs; /* maximum size of absolute files, 14: ** also low limit of relocatable code */ 15: extern WORD R_counter; /* relocation counter, used in 16: ** assigning relocation constants, 17: ** also high limit of relocatable 18: ** code after relocation */ 19: extern long Seekoff; /* offset for seeking in out file */ 20: extern char Do_410; /* out file format boolean */ 21: extern char Do_411; /* out file format boolean */ 22: extern char Do_map; /* boolean for printing load map */ 23: extern char Do_lpr_map; /* boolean for line printing map */ 24: extern char Do_bits; /* boolean for including relocation 25: ** bits in .out file */ 26: extern char Do_kludge; /* boolean to write global symbols in 27: ** out file table with underscore */ 28: extern char Do_silent; /* boolean for not printing zero 29: ** errors message */ 30: extern char Do_table; /* boolean for including symbol table 31: ** in out file */ 32: extern char No_locals; /* boolean for not including local 33: ** symbols in out table */ 34: extern WORD Transadd; /* transfer address */ 35: int T_counter; /* used for assigning numbers to the 36: ** global symbols so that they may be 37: ** referenced in relocation bits */ 38: int Glc; /* global location counter */ 39: struct outword Curr; /* Curr.val is the current relocation 40: ** constant, and Curr.rbits is the 41: ** current relocation bits */ 42: WORD Tex_size; /* for out file */ 43: WORD Dat_size; /* for out file */ 44: WORD Bss_size; /* for out file */ 45: char *Outname; /* name of out file */ 46: FILE *Outp = NULL; /* pointer for out file */ 47: extern char Erstring[80]; /* buffer for error messages */ 48: extern int Nerrors; /* the number of user errors */ 49: FILE *Bitp = NULL; /* temporary file for relocation bits */ 50: char Bitname[20]; /* name of temporary bit file */ 51: FILE *Symp = NULL; /* temporary file for symbol table */ 52: char Symname[20]; /* name of temporary file for symbol table */ 53: char *Mapname; /* name of the map file */ 54: FILE *Mapp; /* pointer for map file */ 55: char No_out; /* boolean for no out file */ 56: char Undefineds = 0; /* boolean, set if there are any 57: ** references to undefined global 58: ** symbols in the out file */ 59: struct outword Vreg[MAXREG]; /* virtual registers */ 60: 61: /************************** warmup ****************************************/ 62: 63: 64: warmup() /* get ready for pass 2: open out file and write header, 65: ** open temporary file for out file 66: ** symbol table and write global variables to it */ 67: 68: { 69: WORD h[8]; 70: 71: Outp = fopen(Outname, "w"); 72: if (Outp == NULL) 73: { 74: sprintf(Erstring, "%s not accessible\n", Outname); 75: lerror(Erstring); 76: } 77: fseek(Outp, 15L+(long)Tex_size+(long)Dat_size, 0); 78: putc(0, Outp); 79: 80: /* write header for out file */ 81: if (Do_410) 82: h[0] = 0410; 83: else if (Do_411) 84: h[0] = 0411; 85: else 86: h[0] = 0407; 87: h[1] = Tex_size; 88: h[2] = Dat_size; 89: h[3] = Bss_size; 90: h[4] = 0; 91: h[5] = Transadd; 92: h[6] = 0; 93: h[7] = Do_bits ? 0 : 1; 94: 95: fseek(Outp, 0L, 0); 96: fwrite(h, 8, 2, Outp); 97: 98: if (Do_table) 99: { 100: sprintf(Symname, "/tmp/l11.sym.%d", getpid()); 101: Symp = fopen(Symname, "w"); 102: if (Symp == NULL) 103: lerror("can't open symbol table file"); 104: else 105: { 106: T_counter = 0; /* initialize counter for numbering global 107: ** symbols */ 108: dump_tree(Sym_root); 109: } 110: } 111: 112: if (Do_bits) 113: { 114: sprintf(Bitname, "/tmp/l11.bit.%d", getpid()); 115: Bitp = fopen(Bitname, "w"); 116: if (Bitp == NULL) 117: lerror("can't open relocation bits file"); 118: } 119: } 120: 121: 122: /************************* dump_tree **************************************/ 123: 124: 125: dump_tree(sym) /* dump the sub-tree of symbols pointed to by *sym and 126: ** number its contents for future reference to 127: ** undefined symbols */ 128: 129: register struct symbol *sym; 130: { 131: if (sym == NULL) 132: return; 133: 134: dump_tree(sym->left); 135: 136: write_sym(sym->name, Do_kludge); 137: if (sym->type & DEF) /* if the symbol is defined */ 138: Putw(040 | get_type(sym->prsect->type), Symp); 139: else /* undefined */ 140: Putw(040, Symp); 141: Putw(sym->value, Symp); 142: sym->t_numb = T_counter++; 143: 144: dump_tree(sym->right); 145: } 146: 147: 148: /************************** write_sym ***********************************/ 149: 150: 151: write_sym(sname, flag) /* write the given symbol as 8 bytes (null padded) 152: ** in the symbol file , if flag then write the symbol 153: ** with an underscore */ 154: register char *sname; 155: register int flag; 156: { 157: if (flag) 158: putc('_', Symp); 159: while (*sname) 160: { 161: if (*sname == ' ') 162: putc(0, Symp); 163: else 164: putc(*sname, Symp); 165: sname++; 166: } 167: putc(0, Symp); 168: if (!flag) 169: putc(0, Symp); 170: } 171: 172: 173: /**************************** pass2 ****************************************/ 174: 175: 176: pass2() /* translate code and write local symbols */ 177: 178: { 179: struct objfile *obj; /* which object file */ 180: 181: obj = File_root; 182: while (obj != NULL) 183: { 184: transcode(obj); 185: if (Do_table && !No_locals) 186: dump_locals(obj); 187: obj = obj->nextfile; 188: } 189: } 190: 191: 192: /************************ transcode ****************************************/ 193: 194: 195: transcode(obj) /* translate code */ 196: 197: struct objfile *obj; /* object file to translate code from */ 198: { 199: register int drctv; /* directive from obj file */ 200: register int value; /* temporary variable */ 201: int vrd; /* possible virtual register directive */ 202: static struct outword wbuff; 203: 204: 205: ch_input(obj->fname, CODE); 206: while (morebytes()) /* continue reading code section until 207: ** empty */ 208: { 209: switch (drctv = getbyte()) 210: { 211: case 000: 212: abswrite((WORD)0, (WORD)0); 213: break; 214: 215: case 002: 216: relwrite((WORD)0, (WORD)0); 217: break; 218: 219: case 004: 220: abswrite(getword(), (WORD)0); 221: break; 222: 223: case 006: 224: relwrite(getword(), (WORD)0); 225: break; 226: 227: case 010: 228: abswrite(Curr.val, Curr.rbits); 229: break; 230: 231: case 014: 232: abswrite(Curr.val + getword(), Curr.rbits); 233: break; 234: 235: case 020: 236: get_sym(&wbuff); 237: abswrite(wbuff.val, wbuff.rbits); 238: break; 239: 240: case 022: 241: get_sym(&wbuff); 242: relwrite(wbuff.val, wbuff.rbits); 243: break; 244: 245: case 030: 246: get_rc(&wbuff, obj, (char *)NULL); 247: abswrite(wbuff.val, wbuff.rbits); 248: break; 249: 250: case 032: 251: get_rc(&wbuff, obj, (char *)NULL); 252: relwrite(wbuff.val, wbuff.rbits); 253: break; 254: 255: case 034: 256: get_rc(&wbuff, obj, (char *)NULL); 257: abswrite(wbuff.val + getword(), wbuff.rbits); 258: break; 259: 260: case 036: 261: get_rc(&wbuff, obj, (char *)NULL); 262: relwrite(wbuff.val + getword(), wbuff.rbits); 263: break; 264: 265: case 040: 266: do040(obj); 267: break; 268: 269: case 044: 270: wbuff.val = getword(); 271: wbuff.rbits = 0; 272: vreg_oper(getbyte(), &wbuff); 273: break; 274: 275: case 050: 276: if ((vrd = getbyte()) == 0) 277: linkseek(Curr.val, Curr.rbits); 278: else 279: vreg_oper(vrd, &Curr); 280: break; 281: 282: case 054: 283: value = getword(); 284: if ((vrd = getbyte()) == 0) 285: linkseek(Curr.val + value, Curr.rbits); 286: else 287: { 288: wbuff.val = Curr.val + value; 289: wbuff.rbits = Curr.rbits; 290: vreg_oper(vrd, &wbuff); 291: } 292: break; 293: 294: case 060: 295: get_sym(&wbuff); 296: vreg_oper(getbyte(), &wbuff); 297: break; 298: 299: case 070: 300: get_rc(&wbuff, obj, (char *)NULL); 301: if ((vrd = getbyte()) == 0) 302: { 303: linkseek(wbuff.val, wbuff.rbits); 304: Curr.val = wbuff.val; 305: Curr.rbits = wbuff.rbits; 306: } 307: else 308: vreg_oper(vrd, &wbuff); 309: break; 310: 311: case 074: 312: get_rc(&wbuff, obj, (char *)NULL); 313: value = getword(); 314: if ((vrd = getbyte()) == 0) 315: { 316: linkseek(wbuff.val + value, wbuff.rbits); 317: Curr.val = wbuff.val; 318: Curr.rbits = wbuff.rbits; 319: } 320: else 321: { 322: wbuff.val += value; 323: vreg_oper(vrd, &wbuff); 324: } 325: break; 326: 327: case 0200: 328: bytewrite((char)0); 329: break; 330: 331: case 0204: 332: bytewrite((char)getbyte()); 333: break; 334: 335: case 0220: 336: get_sym(&wbuff); 337: if (Do_bits && wbuff.rbits != 0) 338: uerror("unrelocatable byte expression"); 339: bytewrite((char)(0377 & wbuff.val)); 340: break; 341: 342: default: 343: sprintf(Erstring, "bad code directive %03o", drctv); 344: lerror(Erstring); 345: } 346: } 347: } 348: 349: 350: /************************* abswrite *****************************************/ 351: 352: 353: abswrite(value, rbits) /* write value in the out file */ 354: register WORD value; 355: register WORD rbits; /* relocation bits */ 356: { 357: Putw(value, Outp); 358: Glc += 2; 359: if (Do_bits) 360: Putw(rbits, Bitp); 361: } 362: 363: 364: /************************ relwrite ****************************************/ 365: 366: 367: relwrite(value, rbits) /* write value in out file relative to 368: ** global location counter */ 369: register WORD value; 370: register WORD rbits; 371: { 372: Putw(value - Glc - 2, Outp); 373: Glc += 2; 374: if (Do_bits) 375: Putw((rbits == Curr.rbits) ? 0 : (rbits | 01), Bitp); 376: /* if the relocation bits for the word being written are 377: ** the same as the current psect's then the word is an 378: ** absolute offset, otherwise add 1 to the relocation 379: ** bits to indicate relativity to the PC */ 380: } 381: 382: 383: /************************* bytewrite *************************************/ 384: 385: 386: bytewrite(value) /* write the byte in the out file */ 387: char value; 388: { 389: putc(0377&value, Outp); 390: Glc++ ; 391: } 392: 393: 394: /************************* get_rc *****************************************/ 395: 396: 397: get_rc(wbuff, obj, psname) /* place in wbuff the relocation constant and 398: ** relocation bits of psname 399: ** or if psname is NULL the psect whose 400: ** name is in the input stream, and whose object 401: ** file is pointed to by 'obj'. */ 402: 403: register struct outword *wbuff; 404: struct objfile *obj; 405: register char *psname; 406: 407: { 408: char name[7]; /* the name of the psect */ 409: register struct psect *ps; 410: 411: /* if psname is NULL get name from input stream */ 412: if (psname == NULL) 413: { 414: psname = name; 415: dc_symbol(psname); 416: } 417: 418: ps = obj->psect_list; 419: 420: while (strcmp(ps->name, psname)) /* while the strings are 421: ** not equal */ 422: { 423: ps = ps->obsame; 424: if (ps == NULL) 425: { 426: sprintf(Erstring, "rc not found for %s", psname); 427: lerror(Erstring); 428: } 429: } 430: wbuff->val = ps->rc; 431: wbuff->rbits = get_bits(ps->type); 432: } 433: 434: 435: /***************************** get_bits **********************************/ 436: 437: 438: get_bits(attributes) /* get the out file symbol table bits and convert 439: ** to relocation table bits */ 440: 441: register int attributes; /* the M11 attributes of a psect */ 442: { 443: return (2 * (get_type(attributes) - 1)); 444: } 445: 446: 447: /***************************** get_type ***********************************/ 448: 449: 450: get_type(attr) /* decode the psect type into out file symbol table 451: ** attribute word format */ 452: register int attr; 453: { 454: if (!(attr & REL)) /* absolute */ 455: return (01); 456: else if (attr & INS) /* text */ 457: return (02); 458: else if (attr & BSS) /* bss */ 459: return (04); 460: else /* data */ 461: return (03); 462: } 463: 464: 465: /*************************** get_sym ***************************************/ 466: 467: 468: get_sym(wbuff) /* get the value of the symbol in the input stream */ 469: register struct outword *wbuff; 470: 471: { 472: char sname[7]; /* the name of the symbol */ 473: register struct symbol *sym; 474: register int cond; /* used for branching left 475: ** or right */ 476: int index; /* virtual register index */ 477: 478: dc_symbol(sname); 479: if (*sname != ' ') 480: { 481: sym = Sym_root; 482: while (sym != NULL) 483: { 484: if ((cond = strcmp(sname, sym->name)) == 0) 485: { 486: if (sym->type & DEF) /* if defined */ 487: { 488: wbuff->val = sym->value; 489: wbuff->rbits = get_bits(sym->prsect->type); 490: return; 491: } 492: else if (Do_bits) /* set relocation bits 493: ** for undefined symbol 494: ** and return zero */ 495: { 496: Undefineds = 1; 497: wbuff->val = 0; 498: wbuff->rbits = 020 * sym->t_numb + 010; 499: return; 500: } 501: else 502: { 503: sprintf(Erstring, "undefined symbol: %s", sname); 504: uerror(Erstring); 505: wbuff->val = 0; 506: wbuff->rbits = 0; 507: return; 508: } 509: } 510: else if (cond < 0) 511: sym = sym->left; 512: else 513: sym = sym->right; 514: } 515: /* symbol has not been found */ 516: sprintf(Erstring, "%s not found", sname); 517: lerror(Erstring); 518: wbuff->val = 0; 519: wbuff->rbits = 0; 520: } 521: else /* virtual register */ 522: { 523: index = sname[5] - 'a'; 524: wbuff->val = Vreg[index].val; 525: wbuff->rbits = Vreg[index].rbits; 526: } 527: } 528: 529: 530: /*************************** vreg_oper *************************************/ 531: 532: vreg_oper(drctv, wbuff) /* preform an operation on a virtual register */ 533: 534: register int drctv; /* directive (operation) */ 535: register struct outword *wbuff; /* source value and relocation bits */ 536: { 537: register int index; /* index of destination register */ 538: static char mess[] = "unrelocatable arithmetic expression"; 539: 540: index = getbyte() - 1; 541: if (index >= MAXREG) 542: { 543: uerror("expression involving global symbols too large"); 544: index %= MAXREG; 545: } 546: 547: switch(drctv) 548: { 549: case 0200: 550: Vreg[index].val = wbuff->val; 551: Vreg[index].rbits = wbuff->rbits; 552: break; 553: 554: case 0201: 555: Vreg[index].val += wbuff->val; 556: if (Do_bits && Vreg[index].rbits && wbuff->rbits) 557: uerror(mess); 558: else 559: Vreg[index].rbits |= wbuff->rbits; 560: break; 561: 562: case 0202: 563: Vreg[index].val -= wbuff->val; 564: if (Do_bits && wbuff->rbits) 565: if (Vreg[index].rbits == wbuff->rbits) 566: Vreg[index].rbits = 0; 567: else 568: uerror(mess); 569: break; 570: 571: case 0203: 572: Vreg[index].val *= wbuff->val; 573: if (Do_bits) 574: uerror(mess); 575: break; 576: 577: case 0204: 578: Vreg[index].val /= wbuff->val; 579: if (Do_bits) 580: uerror(mess); 581: break; 582: 583: case 0205: 584: Vreg[index].val &= wbuff->val; 585: if (Do_bits) 586: uerror(mess); 587: break; 588: 589: case 0206: 590: Vreg[index].val |= wbuff->val; 591: if (Do_bits) 592: uerror(mess); 593: break; 594: 595: default: 596: sprintf(Erstring, "bad v.r. directive: %03o", drctv); 597: lerror(Erstring); 598: } 599: } 600: 601: 602: /************************** do040 ***************************************/ 603: 604: 605: do040(obj) /* do 040 code directive */ 606: 607: register struct objfile *obj; 608: { 609: register int drctv; 610: register int index; 611: 612: switch (drctv = getbyte()) 613: { 614: case 001: /* low limit */ 615: index = getbyte() - 1; 616: Vreg[index].val = Maxabs; 617: Vreg[index].rbits = 0; 618: if (Do_bits) 619: uerror("'.limit' directive not relocatable"); 620: break; 621: 622: case 002: /* high limit */ 623: index = getbyte() - 1; 624: Vreg[index].val = R_counter; 625: Vreg[index].rbits = 0; 626: break; 627: 628: case 003: /* ^pl */ 629: case 004: /* ^ph */ 630: p_limit(obj, drctv); 631: break; 632: 633: case 0200: /* clear */ 634: index = getbyte() - 1; 635: Vreg[index].val = Vreg[index].rbits = 0; 636: break; 637: 638: case 0201: /* add zero */ 639: index = getbyte(); 640: break; 641: 642: default: 643: sprintf(Erstring, "bad 040 directive %03o", drctv); 644: lerror(Erstring); 645: } 646: } 647: 648: 649: /************************* p_limit **************************************/ 650: 651: 652: p_limit(obj, drctv) /* find the low or high limit of a psect */ 653: struct objfile *obj; 654: int drctv; 655: { 656: register struct psect *ps; 657: register struct g_sect *gptr; 658: int cond; 659: register int index; 660: char pname[7]; 661: 662: dc_symbol(pname); 663: index = getbyte() - 1; 664: 665: ps = obj->psect_list; 666: 667: while (ps != NULL) /* try to find the psect in local link-list */ 668: { 669: if ( !strcmp(pname, ps->name)) 670: break; 671: ps = ps->obsame; 672: } 673: 674: if (ps != NULL) /* if it was found in the local list */ 675: { 676: while (ps->pssame != NULL) /* find bottom of sames, if any. 677: ** see relocate() */ 678: ps = ps->pssame; 679: } 680: else /* psect not a local so check global tree */ 681: { 682: gptr = Gsect_root; 683: while (gptr != NULL) 684: { 685: if ( !(cond = strcmp(pname, gptr->name))) 686: { 687: if (gptr->last_sect->pssame == NULL) 688: /* the psect is solitary */ 689: ps = gptr->last_sect; 690: else 691: /* last_psect points to the last psect 692: ** in a plural link-list of sames. 693: ** there is a psect after last_sect 694: ** which contains the conglomeration 695: ** of all the sames. 696: ** see relocate() */ 697: ps = gptr->last_sect->pssame; 698: break; 699: } 700: else if (cond < 0) 701: gptr = gptr->leftt; 702: else 703: gptr = gptr->rightt; 704: } 705: 706: if (ps == NULL) /* psect not found */ 707: { 708: sprintf(Erstring, "%s not found in ^p reference", pname); 709: uerror(Erstring); 710: Vreg[index].val = Vreg[index].rbits = 0; 711: return; 712: } 713: } 714: 715: if (drctv == 003) /* low */ 716: Vreg[index].val = ps->rc; 717: else /* high */ 718: Vreg[index].val = ps->rc + ps->nbytes; 719: 720: Vreg[index].rbits = get_bits(ps->type); 721: } 722: 723: 724: /*************************** linkseek *************************************/ 725: 726: 727: linkseek(nlc, nrbits) 728: 729: register WORD nlc; /* new location counter */ 730: register WORD nrbits; /* new relocation bits */ 731: { 732: long where; 733: 734: Glc = nlc; 735: 736: if (nrbits == 04) /* if data section add offset */ 737: where = nlc + Seekoff + 020; 738: else 739: where = nlc + 020; 740: 741: if (fseek(Outp, where, 0) == -1) 742: { 743: skerr: fprintf(stderr, "Fseek error\n"); 744: bail_out(); 745: } 746: if (Do_bits) 747: if (fseek(Bitp, where - 020L, 0) == -1) 748: goto skerr; 749: 750: if (nrbits == 06) /* bss section about to be writen */ 751: uerror("error: initialized data in bss psect"); 752: } 753: 754: 755: /**************************** dump_locals ********************************/ 756: 757: 758: # define MAXCONSTS 10 759: 760: 761: dump_locals(obj) /* dump local symbols */ 762: 763: struct objfile *obj; 764: { 765: int rconst[MAXCONSTS]; /* relocation constants */ 766: int segment[MAXCONSTS]; /* segment type for out file */ 767: struct psect *last; 768: struct psect *temp; 769: char sname[7]; /* symbol name */ 770: char index; 771: char type; 772: int value; 773: int i; 774: 775: /* fill rconst and segment arrays from the first MAXCONSTS psects */ 776: temp = obj->psect_list; 777: i = 0; 778: while (temp != NULL && i < MAXCONSTS) 779: { 780: rconst[i] = temp->rc; 781: segment[i++] = get_type(temp->type); 782: temp = temp->obsame; 783: } 784: last = temp; /* (in case there are more psects than MAXCONSTS) */ 785: 786: /* write 'em */ 787: 788: ch_input(obj->fname, SYMBOLS); 789: while (morebytes()) 790: { 791: dc_symbol(sname); 792: type = getbyte(); 793: index = getbyte(); 794: value = getword(); 795: 796: if (type & 001) /* if internal m11 symbol, forget it */ 797: continue; 798: 799: write_sym(sname, 0); 800: if (index >= MAXCONSTS) 801: { 802: temp = last; 803: for (i = MAXCONSTS; i < index; i++) 804: temp = temp->obsame; 805: Putw(get_type(temp->type), Symp); 806: Putw(value + temp->rc, Symp); 807: } 808: else 809: { 810: Putw(segment[index], Symp); 811: Putw(value + rconst[index], Symp); 812: } 813: } 814: } 815: 816: 817: /************************ uerror ******************************************/ 818: 819: 820: uerror(mess) /* print user error message and increment Nerrors */ 821: 822: register char *mess; 823: { 824: Nerrors++; 825: fprintf(stderr, "%s\n", mess); 826: if (Do_map) 827: fprintf(Mapp, "%s\n", mess); 828: } 829: 830: 831: /************************** loose_ends ************************************/ 832: 833: 834: loose_ends() 835: { 836: register c; 837: register int nbytes; /* number of bytes in out file symbol table */ 838: 839: 840: if (Do_bits) 841: { 842: if (ferror(Bitp)) 843: werror(Bitname); 844: 845: Bitp = freopen(Bitname, "r", Bitp); 846: if (Bitp == NULL) 847: lerror("can't reopen relocation bits file"); 848: 849: fseek(Outp, (long) (Tex_size + Dat_size + 020L), 0); 850: 851: while ((c = getc(Bitp)) != EOF) 852: putc(0377&c, Outp); 853: 854: unlink(Bitname); 855: } 856: 857: if (Do_table) 858: { 859: if (ferror(Symp)) 860: werror(Symname); 861: 862: Symp = freopen(Symname, "r", Symp); 863: if (Symp == NULL) 864: lerror("can't reopen symbol table file"); 865: 866: /* send r/w head to end of rbits or code section in out file */ 867: 868: fseek(Outp, (long) ((Tex_size + Dat_size) * (Do_bits + 1) + 020L), 0); 869: 870: nbytes = 0; 871: while ((c = getc(Symp)) != EOF) 872: { 873: nbytes++; 874: putc(0377&c, Outp); 875: } 876: 877: /* write size of symbol table */ 878: fseek(Outp, 010L, 0); 879: Putw(nbytes, Outp); 880: 881: unlink(Symname); 882: } 883: 884: if (Do_map) 885: { 886: fprintf(Mapp, "errors detected: %d\n", Nerrors); 887: if (ferror(Mapp)) 888: werror(Mapname); 889: fclose(Mapp); 890: if (Do_lpr_map) 891: execl("/usr/bin/lpr", "lpr", Mapname, 0); 892: } 893: 894: if (ferror(Outp)) 895: werror(Outname); 896: 897: /* change out file to be executable if no errors */ 898: chmod(Outname, Nerrors ? 0644 : 0755); 899: 900: if (Nerrors || !Do_silent) 901: fprintf(stderr, "errors detected: %d\n", Nerrors); 902: 903: exit(Nerrors ? 1 : 0); 904: } 905: 906: 907: /**************************** bail_out ***********************************/ 908: 909: 910: bail_out() /* unlink any opened output file then exit */ 911: 912: { 913: if (Outp != NULL) 914: unlink(Outname); 915: if (Mapp != NULL) 916: unlink(Mapname); 917: if (Symp != NULL) 918: unlink(Symname); 919: if (Bitp != NULL) 920: unlink(Bitname); 921: exit(1); 922: } 923: 924: 925: /******************************** werror **********************************/ 926: 927: 928: werror(fname) /* write error handler */ 929: char *fname; 930: 931: { 932: perror(fname); 933: if (Symp != NULL) 934: unlink(Symname); 935: if (Bitp != NULL) 936: unlink(Bitname); 937: exit(1); 938: } 939: Putw(x, p) 940: FILE *p; 941: { 942: putc(x & 0377, p); 943: x >>= 8; 944: putc(x & 0377, p); 945: }