|
|
1.1 ! root 1: /* ld/main.c */ ! 2: ! 3: #include "data.h" ! 4: ! 5: extern char *mktemp(); ! 6: ! 7: main( argc, argv ) ! 8: int argc; ! 9: char *argv[]; ! 10: { ! 11: flag_t dcomm = 0, /* define commons even if reloc out */ ! 12: nosym = 0, /* do not output symbol table */ ! 13: memld = 0, /* do in-memory load */ ! 14: reloc = 0; /* output relocation info */ ! 15: char *ofname = "l.out", ! 16: *entrys = NULL, ! 17: *mfn, ! 18: *lp; ! 19: seg_t *sgp; ! 20: sym_t *sp; ! 21: mod_t *mp; ! 22: FILE *ofp; ! 23: struct stat statbuf; ! 24: int i, segn; ! 25: unsigned int symno; ! 26: fsize_t daddr; ! 27: uaddr_t addr; ! 28: #if BREADBOX ! 29: int abort(); ! 30: #endif ! 31: ! 32: setbuf( stdout, NULL ); ! 33: setbuf( stderr, NULL ); ! 34: ! 35: /* ! 36: * set separate code/data flag (required for 286 protected mode) ! 37: */ ! 38: oldh.l_flag |= LF_SEP; ! 39: ! 40: nmod = mxmsym = mdisk = 0; ! 41: ! 42: if ( argc <= 1 ) ! 43: usage( "no args" ); ! 44: ! 45: /* ! 46: * Pass 1: Scan argument list. ! 47: */ ! 48: for ( i = 1; i < argc; i++ ) { ! 49: ! 50: /* ! 51: * Not -option; attempt to read file ! 52: */ ! 53: if ( *argv[i] != '-' ) { ! 54: if ( !rdfile(argv[i]) ) ! 55: fatal( "can't open %s", argv[i] ); ! 56: } ! 57: ! 58: /* ! 59: * Decode options ! 60: */ ! 61: else switch ( argv[i][1] ) { ! 62: ! 63: default: ! 64: usage( "unknown option %s", argv[i] ); ! 65: continue; ! 66: ! 67: case 'b': ! 68: /* ! 69: * -b: undocumented option ! 70: * big link stores module structs on disk ! 71: */ ! 72: mdisk++; ! 73: ! 74: if ( (mfp = fopen(mfn=mktemp("/tmp/ldXXXXXX"),"wr") ) ! 75: ==NULL) { ! 76: unlink( mfn ); ! 77: fatal( "can't open temp file" ); ! 78: } ! 79: ! 80: mtemp = malloc( sizeof(mod_t) ); ! 81: continue; ! 82: ! 83: case 'd': ! 84: /* ! 85: * -d: Define commons (even if undefined symbols). ! 86: */ ! 87: dcomm++; ! 88: continue; ! 89: ! 90: case 'e': ! 91: /* ! 92: * -e ent: Set entry point to given symbol/octal number. ! 93: */ ! 94: if ( ++i >= argc ) ! 95: usage( "Bad -e option" ); ! 96: ! 97: else { ! 98: undef( argv[i] ); ! 99: entrys = argv[i]; ! 100: } ! 101: continue; ! 102: ! 103: case 'i': ! 104: continue; ! 105: ! 106: case 'k': ! 107: /* ! 108: * -k[sys]: Kernel process - use system symbol table. ! 109: */ ! 110: oldh.l_flag |= LF_KER; ! 111: ! 112: if ( argv[i][2] != '\0' ) ! 113: rdsystem( &argv[i][2] ); ! 114: else ! 115: rdsystem( "/coherent" ); ! 116: continue; ! 117: ! 118: case 'l': ! 119: /* ! 120: * -l<lib>: Use standard library <lib>. ! 121: */ ! 122: lp = malloc( strlen(argv[i])+16 ); ! 123: sprintf( lp, "/lib/lib%s.a", &argv[i][2] ); ! 124: ! 125: if ( rdfile(lp) ) ! 126: ; ! 127: ! 128: else { ! 129: sprintf( lp, "/usr/lib/lib%s.a", &argv[i][2] ); ! 130: if ( rdfile(lp) ) ! 131: ; ! 132: else ! 133: fatal( "can't open lib%s.a", ! 134: &argv[i][2]); ! 135: } ! 136: continue; ! 137: ! 138: case 'm': ! 139: /* ! 140: * -m: Perform in-memory load if possible. ! 141: */ ! 142: memld++; ! 143: continue; ! 144: ! 145: case 'n': ! 146: /* ! 147: * -n: Bind output shared. ! 148: */ ! 149: oldh.l_flag |= LF_SHR; ! 150: #ifdef IAPX86 ! 151: /* ! 152: * Special case, no -n without -i on IBM PC ! 153: */ ! 154: oldh.l_flag |= LF_SEP; ! 155: #endif ! 156: continue; ! 157: ! 158: case 'o': ! 159: /* ! 160: * -o file: Place output in named file (default l.out). ! 161: */ ! 162: if ( ++i >= argc ) ! 163: usage( "bad -o option" ); ! 164: else ! 165: ofname = argv[i]; ! 166: continue; ! 167: ! 168: case 'r': ! 169: /* ! 170: * -r: Retain relocation information. ! 171: */ ! 172: reloc++; ! 173: #ifdef IAPX86 ! 174: /* ! 175: * Special case, -r disables -i. ! 176: */ ! 177: oldh.l_flag &= ~LF_SEP; ! 178: #endif ! 179: continue; ! 180: ! 181: case 's': ! 182: /* ! 183: * -s: Discard symbol table. ! 184: */ ! 185: nosym++; ! 186: continue; ! 187: ! 188: case 'u': ! 189: /* ! 190: * -u sym: Undefine 'sym' (forcing library search). ! 191: */ ! 192: if ( ++i >= argc ) ! 193: usage( "bad -u option" ); ! 194: else ! 195: undef( argv[i] ); ! 196: continue; ! 197: ! 198: case 'w': ! 199: /* ! 200: * -w: Watch everything happen. ! 201: */ ! 202: watch++; ! 203: message( "watch!" ); ! 204: continue; ! 205: ! 206: case 'X': ! 207: /* ! 208: * -X: Discard C internal local symbols. ! 209: */ ! 210: noilcl++; ! 211: continue; ! 212: ! 213: case 'x': ! 214: /* ! 215: * -x: Discard all local symbols. ! 216: */ ! 217: nolcl++; ! 218: continue; ! 219: ! 220: case 'C': ! 221: /* ! 222: * -C: Bind output combined code/data. ! 223: * (otherwise it will be separate code/data as ! 224: * required in 286 protected mode) ! 225: */ ! 226: oldh.l_flag &= ~LF_SEP; ! 227: continue; ! 228: } ! 229: } ! 230: ! 231: if ( oldh.l_machine == 0 ) ! 232: fatal( "no input found" ); ! 233: ! 234: /* ! 235: * all modules have been read ! 236: * resolve meanings of various flags ! 237: */ ! 238: ! 239: /* ! 240: * Relocation or undefined symbols... ! 241: */ ! 242: if ( reloc || nundef ) { ! 243: ! 244: /* ! 245: * Requires symbol table be retained ! 246: */ ! 247: nosym = 0; ! 248: ! 249: if ( oldh.l_flag & LF_SEP ) { ! 250: ! 251: message("link failed, the following symbols are undefined:"); ! 252: ! 253: for ( i = 0; i < NHASH; i++ ) { ! 254: for ( sp=symtable[i]; sp!=NULL; sp=sp->next ) { ! 255: if(sp->s.ls_type==(L_GLOBAL|L_REF) ! 256: && sp->s.ls_addr==0) ! 257: spmsg(sp,""); ! 258: } ! 259: } ! 260: ! 261: if ( nundef ) ! 262: exit( 1 ); ! 263: } ! 264: } ! 265: ! 266: /* ! 267: * No relocation, no undefined symbols ! 268: */ ! 269: else { ! 270: /* ! 271: * Must define commons ! 272: */ ! 273: dcomm++; ! 274: ! 275: /* ! 276: * Discarding reloc info ! 277: */ ! 278: if ( oseg[L_REL].size != 0 ) { ! 279: oldh.l_flag |= LF_NRB; /* make note */ ! 280: oseg[L_REL].size = 0; ! 281: } ! 282: } ! 283: ! 284: /* ! 285: * To define common symbols... ! 286: */ ! 287: if ( dcomm ) ! 288: oseg[L_BSSD].size += commons; /* we need this much room */ ! 289: ! 290: /* ! 291: * Discard symbol table. ! 292: */ ! 293: if ( nosym ) ! 294: oseg[L_SYM].size = 0; ! 295: ! 296: if ( watch ) ! 297: message( "# undefined=%d", nundef ); ! 298: ! 299: /* ! 300: * Set segment bases ! 301: */ ! 302: baseall( oseg, &oldh ); ! 303: ! 304: #ifdef IAPX86 ! 305: if ( oldh.l_machine == M_8086 ) { ! 306: if ( (oseg[L_SHRI].size + ! 307: oseg[L_PRVI].size + ! 308: oseg[L_BSSI].size) >= MAXSEG86 ) ! 309: fatal("FATAL: code segment too large"); ! 310: ! 311: if ( (oseg[L_SHRD].size + ! 312: oseg[L_PRVD].size + ! 313: oseg[L_BSSD].size) >= (MAXSEG86 - DEFSTACK) ) ! 314: fatal("FATAL: data segment too large"); ! 315: ! 316: if ( (oseg[L_SHRD].size + ! 317: oseg[L_PRVD].size + ! 318: oseg[L_BSSD].size) >= (MAXSEG86 - DEFSTACK - WARNSIZE) ) ! 319: message( ! 320: "Warning: data segment may be too large to execute"); ! 321: } ! 322: #endif ! 323: ! 324: /* ! 325: * Open output file ! 326: */ ! 327: if ( ((ofp = fopen(ofname, "w")) == NULL) ! 328: && ((unlink(ofname) != 0) || ((ofp = fopen(ofname, "w")) == NULL)) ) ! 329: fatal( "cannot create %s", ofname ); ! 330: ! 331: stat( ofname, &statbuf ); ! 332: chmod( ofname, statbuf.st_mode & ~(S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))); ! 333: setbuf( ofp, NULL ); ! 334: ! 335: /* ! 336: * set disk offsets of segments ! 337: * if not bigger than a breadbox, build output file in memory; ! 338: * otherwise, open the file for each segment, ! 339: * to get independent buffering ! 340: */ ! 341: daddr = segoffs( oseg, 0L ); ! 342: ! 343: if ( watch ) ! 344: message( "size: %ld", daddr ); ! 345: ! 346: #if BREADBOX ! 347: if ( memld || (daddr < BREADBOX) ) ! 348: outbuf = malloc( (int) daddr ); ! 349: #endif ! 350: for ( i = 0; i < NLSEG; i++ ) { ! 351: ! 352: if ( (i == L_BSSI) || (i == L_BSSD) ) ! 353: continue; ! 354: ! 355: sgp = &oseg[i]; ! 356: ! 357: if ( sgp->size == 0 ) ! 358: continue; ! 359: ! 360: #if BREADBOX ! 361: if ( outbuf != NULL ) { ! 362: if ( (outputf[i] = malloc(sizeof(FILE))) == NULL ) ! 363: fatal("out of space"); ! 364: ! 365: outputf[i]->_cc = sgp->size; ! 366: outputf[i]->_cp = &outbuf[sgp->daddr]; ! 367: outputf[i]->_pt = &abort; ! 368: } ! 369: else ! 370: #endif ! 371: { ! 372: if ( (outputf[i] = fopen(ofname, "r+w")) == NULL ) ! 373: fatal( "cannot open %s (seg %d)", ofname, i ); ! 374: ! 375: fseek( outputf[i], sgp->daddr, 0 ); ! 376: ! 377: if ( i == L_SHRI ) ! 378: setbuf( outputf[i], pbuf1 ); ! 379: ! 380: if ( i == L_PRVD ) ! 381: setbuf( outputf[i], pbuf2 ); ! 382: } ! 383: } ! 384: ! 385: /* ! 386: * Define internal symbols which have been referenced ! 387: */ ! 388: if ( dcomm ) { ! 389: i = oldh.l_flag & LF_KER; ! 390: endbind( etext_s, L_PRVI, i ); ! 391: endbind( edata_s, L_PRVD, i ); ! 392: endbind( end_s, L_BSSD, i ); ! 393: } ! 394: ! 395: /* ! 396: * Run through symbol table fixing everything up ! 397: */ ! 398: symno = 0; ! 399: for ( i=0; i < NHASH; i++ ) { ! 400: ! 401: for ( sp = symtable[i]; sp != NULL; sp = sp->next ) { ! 402: ! 403: /* ! 404: * Make defined symbol relative to virtual 0 ! 405: */ ! 406: if ( (segn = sp->s.ls_type & ~L_GLOBAL) < L_SYM ) { ! 407: sp->s.ls_addr += oseg[segn].vbase; ! 408: } ! 409: ! 410: else if ( segn == L_SYM ) { ! 411: spmsg( sp, "references symbol segment" ); ! 412: } ! 413: ! 414: /* ! 415: * Leave absolutes alone ! 416: */ ! 417: else if ( sp->s.ls_type != (L_GLOBAL|L_REF) ) { ! 418: ; ! 419: } ! 420: ! 421: /* ! 422: * Undefined global ! 423: */ ! 424: else if ( sp->s.ls_addr == 0 ) { ! 425: if ( ! reloc ) ! 426: spmsg( sp, "undefined" ); ! 427: } ! 428: ! 429: /* ! 430: * Define commons ! 431: */ ! 432: else if ( dcomm ) { ! 433: addr = sp->s.ls_addr; ! 434: sp->s.ls_addr = oseg[L_BSSD].vbase ! 435: +oseg[L_BSSD].size ! 436: -commons; ! 437: commons -= addr; ! 438: sp->s.ls_type = L_GLOBAL | L_BSSD; ! 439: } ! 440: ! 441: /* ! 442: * Assign symbol number ! 443: */ ! 444: sp->symno = symno++; ! 445: ! 446: /* ! 447: * Output to symbol segment ! 448: */ ! 449: if ( ! nosym ) { ! 450: canint( sp->s.ls_type ); ! 451: canvaddr( sp->s.ls_addr ); ! 452: putstruc( &sp->s, sizeof(sp->s), ! 453: outputf[L_SYM], &oseg[L_SYM] ); ! 454: canint( sp->s.ls_type ); ! 455: canvaddr( sp->s.ls_addr ); ! 456: } ! 457: } ! 458: } ! 459: ! 460: /* ! 461: * get entry point (cannot precede symbol table fixup) ! 462: */ ! 463: oldh.l_entry = (entrys != NULL) ! 464: ? lentry(entrys) ! 465: : (oldh.l_flag & LF_KER) ? drvbase[oldh.l_machine] : 0; ! 466: /* ! 467: * Pass 2 ! 468: */ ! 469: if ( mdisk ) { ! 470: ! 471: free( mtemp ); ! 472: ! 473: if ((mp=malloc(sizeof(mod_t)+ mxmsym*sizeof(sym_t *))) == NULL) ! 474: fatal("out of space - M"); ! 475: ! 476: rewind( mfp ); ! 477: ! 478: for ( i = 0; i < nmod; i++ ) { ! 479: ! 480: if ( fread( mp, sizeof(mod_t), 1 ,mfp ) != 1 ) ! 481: baddisk: fatal( "disk error" ); ! 482: ! 483: if ( fread( mp->sym, sizeof(sym_t *), mp->nsym, mfp ) ! 484: != mp->nsym) ! 485: goto baddisk; ! 486: ! 487: loadmod( mp ); ! 488: } ! 489: ! 490: unlink( mfn ); ! 491: } ! 492: ! 493: else { ! 494: for ( mp = modhead; mp != NULL; mp = mp->next ) ! 495: loadmod( mp ); ! 496: } ! 497: ! 498: /* ! 499: * All over but the flushing ! 500: */ ! 501: canint( oldh.l_magic ); ! 502: canint( oldh.l_flag ); ! 503: canint( oldh.l_machine ); ! 504: canvaddr( oldh.l_entry ); ! 505: ! 506: for ( i = 0; i < NLSEG; i++ ) { ! 507: oldh.l_ssize[i] = oseg[i].size; ! 508: cansize(oldh.l_ssize[i]); ! 509: } ! 510: ! 511: if ( outbuf == NULL ) ! 512: fwrite(&oldh, sizeof(oldh), 1, ofp); ! 513: ! 514: else { ! 515: for ( i = 0; i < sizeof(oldh); i++ ) ! 516: outbuf[i] = *((char *)&oldh + i); ! 517: fwrite( outbuf, 1, (int)daddr, ofp ); ! 518: } ! 519: ! 520: /* ! 521: * Make executable if no undefined symbols, and common storage defined. ! 522: */ ! 523: if ( (nundef == 0) || (dcomm != 0) ) { ! 524: chmod(ofname, statbuf.st_mode|S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)); ! 525: return( 0 ); ! 526: } ! 527: ! 528: /* ! 529: * Supposed to be left relocatable. ! 530: */ ! 531: else if ( reloc ) ! 532: return( 0 ); ! 533: ! 534: /* ! 535: * Undefined symbols left. ! 536: */ ! 537: else ! 538: return( nundef ); ! 539: } ! 540: ! 541: /* ! 542: * Set virtual bases in array of segments ! 543: * according to flags in header. ! 544: */ ! 545: void ! 546: baseall( sega, ldhp ) ! 547: register seg_t sega[]; ! 548: register ldh_t *ldhp; ! 549: { ! 550: register uaddr_t addr; ! 551: ! 552: addr = (ldhp->l_flag & LF_KER) ? drvbase[ldhp->l_machine] : 0; ! 553: ! 554: /* ! 555: * Shared code segment first. ! 556: */ ! 557: addr = setbase( &sega[L_SHRI], ldhp, addr ); ! 558: ! 559: /* ! 560: * Shared data segment next if shared but not separate. ! 561: */ ! 562: if ( (ldhp->l_flag & (LF_SHR|LF_SEP)) == LF_SHR ) ! 563: addr = setbase( &sega[L_SHRD], ldhp, addr ); ! 564: ! 565: /* ! 566: * Round up to page boundary if shared. ! 567: */ ! 568: if ( ldhp->l_flag & LF_SHR ) ! 569: addr = newpage(ldhp, addr); ! 570: ! 571: /* ! 572: * Private code segment next. ! 573: */ ! 574: addr = setbase( &sega[L_PRVI], ldhp, addr ); ! 575: ! 576: /* ! 577: * Private data segment next if shared but not separate. ! 578: */ ! 579: if ( (ldhp->l_flag & (LF_SHR|LF_SEP)) == LF_SHR ) ! 580: addr = setbase( &sega[L_PRVD], ldhp, addr ); ! 581: ! 582: /* ! 583: * Uninitialized code segment next. ! 584: */ ! 585: addr = setbase( &sega[L_BSSI], ldhp, addr ); ! 586: ! 587: /* ! 588: * Set data offset if separate code/data. ! 589: */ ! 590: if ( ldhp->l_flag & LF_SEP ) ! 591: addr = (ldhp->l_flag & LF_KER) ? drvbase[ldhp->l_machine] : 0; ! 592: ! 593: /* ! 594: * Shared data segment next if not shared. ! 595: */ ! 596: if ( (ldhp->l_flag & (LF_SHR|LF_SEP)) != LF_SHR ) ! 597: addr = setbase( &sega[L_SHRD], ldhp, addr ); ! 598: ! 599: /* ! 600: * Round up to page boundary if shared and separate. ! 601: */ ! 602: if ( (ldhp->l_flag & (LF_SHR|LF_SEP)) == (LF_SHR|LF_SEP) ) ! 603: addr = newpage( ldhp, addr ); ! 604: ! 605: /* ! 606: * Private data segment next unless shared and not separate. ! 607: */ ! 608: if ( (ldhp->l_flag & (LF_SHR|LF_SEP)) != LF_SHR ) ! 609: addr = setbase( &sega[L_PRVD], ldhp, addr ); ! 610: ! 611: /* ! 612: * Uninitialized data segment next. ! 613: */ ! 614: setbase( &sega[L_BSSD], ldhp, addr ); ! 615: } ! 616: ! 617: /* ! 618: * Set virtual base in given segment and return next address ! 619: * Check for wraparound and driver space overflow ! 620: */ ! 621: uaddr_t ! 622: setbase( segp, ldhp, addr ) ! 623: register seg_t *segp; ! 624: register ldh_t *ldhp; ! 625: register uaddr_t addr; ! 626: { ! 627: segp->vbase = addr; ! 628: addr += segp->size; ! 629: ! 630: /* ! 631: * Address wrap-around. ! 632: */ ! 633: if ( addr < segp->vbase ) { ! 634: fatal("address wraparound"); ! 635: } ! 636: ! 637: /* ! 638: * User process. ! 639: */ ! 640: else if ( ! (ldhp->l_flag & LF_KER) ) { ! 641: ; ! 642: } ! 643: ! 644: /* ! 645: * Invalid kernel process. ! 646: */ ! 647: else if (addr > drvtop[ldhp->l_machine]) { ! 648: fatal("driver larger than %dKb", ! 649: (drvtop[ldhp->l_machine] ! 650: -drvbase[ldhp->l_machine])/1024); ! 651: } ! 652: ! 653: return (addr); ! 654: } ! 655: ! 656: /* ! 657: * Set segment disk offsets, given sizes ! 658: * return size of module ! 659: */ ! 660: fsize_t ! 661: segoffs(sega, offs) ! 662: seg_t sega[]; ! 663: register fsize_t offs; ! 664: { ! 665: register seg_t *sgp; ! 666: ! 667: offs += sizeof(ldh_t); ! 668: ! 669: for ( sgp = &sega[0]; sgp < &sega[NLSEG]; sgp++ ) { ! 670: ! 671: /* ! 672: * Uninitialized code/data do not affect module size. ! 673: */ ! 674: if ( (sgp == &sega[L_BSSI]) || (sgp == &sega[L_BSSD]) ) ! 675: continue; ! 676: ! 677: /* ! 678: * Record segment address. ! 679: * Calculate module size. ! 680: */ ! 681: else { ! 682: sgp->daddr = offs; ! 683: offs += sgp->size; ! 684: } ! 685: } ! 686: ! 687: /* ! 688: * Return module size. ! 689: */ ! 690: return (offs); ! 691: } ! 692: ! 693: /* ! 694: * Bump address to next hardware segment boundary ! 695: */ ! 696: uaddr_t ! 697: newpage( ldhp, addr ) ! 698: ldh_t *ldhp; ! 699: uaddr_t addr; ! 700: { ! 701: register uaddr_t inc = segsize[ldhp->l_machine]-1; ! 702: ! 703: return ((addr+inc)&~inc); ! 704: } ! 705: ! 706: /* ! 707: * Determine entry point; either octal address or symbol name. ! 708: */ ! 709: uaddr_t ! 710: lentry(str) ! 711: char *str; ! 712: { ! 713: char id[NCPLN], *s = &id[0]; ! 714: uaddr_t oaddr=0; ! 715: int notoct=0; ! 716: register sym_t *sp; ! 717: ! 718: /* ! 719: * Scan string. ! 720: */ ! 721: for ( ; *str; str++ ) { ! 722: ! 723: if ( s < &id[NCPLN] ) ! 724: *s++ = *str; ! 725: ! 726: /* ! 727: * Accumulate octal digits. ! 728: */ ! 729: if ( ('0' <= *str) && (*str <= '7') ) ! 730: oaddr = oaddr*8 + *str - '0'; ! 731: ! 732: /* ! 733: * Not an octal digit. ! 734: */ ! 735: else ! 736: ++notoct; ! 737: } ! 738: ! 739: /* ! 740: * Octal string: return numeric value. ! 741: */ ! 742: if (!notoct) ! 743: return (oaddr); ! 744: ! 745: /* ! 746: * Extend string with nulls. ! 747: */ ! 748: while ( s < &id[NCPLN] ) ! 749: *s++ = 0; ! 750: ! 751: /* ! 752: * Search for string in symbol table. ! 753: */ ! 754: for ( sp = symtable[hash(id)]; sp != NULL; sp = sp->next ) { ! 755: if ( (sp->s.ls_type & L_GLOBAL) ! 756: && (sp->s.ls_type != (L_GLOBAL|L_REF)) ! 757: && eq(sp->s.ls_id, id) ) ! 758: return( sp->s.ls_addr ); ! 759: } ! 760: ! 761: /* ! 762: * Symbol not found. ! 763: */ ! 764: message("entry point %.*s undefined", NCPLN, id); ! 765: return (0); ! 766: } ! 767: ! 768: /* ! 769: * Define referenced internal symbol (as end of given segment) ! 770: */ ! 771: void ! 772: endbind( sp, sn, ldrv ) ! 773: register sym_t *sp; ! 774: int sn, ldrv; ! 775: { ! 776: if ( sp == NULL ) { ! 777: return; ! 778: } ! 779: ! 780: else if ((sp->s.ls_type == (L_GLOBAL|L_REF)) && (sp->s.ls_addr == 0)) { ! 781: sp->s.ls_type = L_GLOBAL|sn; ! 782: sp->s.ls_addr = oseg[sn].size; ! 783: } ! 784: ! 785: else if ( ldrv ) { ! 786: return; ! 787: } ! 788: ! 789: else { ! 790: spmsg(sp, "redefines builtin"); ! 791: } ! 792: } ! 793: ! 794: /* ! 795: * Add reference to symbol table ! 796: */ ! 797: void ! 798: undef( s ) ! 799: char * s; ! 800: { ! 801: lds_t lds; ! 802: int i; ! 803: ! 804: /* ! 805: * Copy reference, extending with NULL. ! 806: */ ! 807: for ( i = 0; i < NCPLN; i++ ) { ! 808: lds.ls_id[i] = *s; ! 809: if ( *s != '\0' ) ! 810: s++; ! 811: } ! 812: ! 813: /* ! 814: * Define symbol as global reference. ! 815: */ ! 816: lds.ls_type = L_GLOBAL|L_REF; ! 817: lds.ls_addr = 0; ! 818: ! 819: /* ! 820: * Add [undefined] to symbol table. ! 821: */ ! 822: addsym(&lds, NULL); ! 823: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.