home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V6 / usr / source / s1 / ld.c < prev    next >
Encoding:
C/C++ Source or Header  |  1975-07-17  |  15.2 KB  |  922 lines

  1. #
  2. /*
  3.  *  link editor
  4.  */
  5.  
  6. #define    SIGINT    2
  7. #define    ARCMAGIC 0177555
  8. #define    FMAGIC    0407
  9. #define    NMAGIC    0410
  10. #define    IMAGIC    0411
  11.  
  12. #define    EXTERN    040
  13. #define    UNDEF    00
  14. #define    ABS    01
  15. #define    TEXT    02
  16. #define    DATA    03
  17. #define    BSS    04
  18. #define    COMM    05    /* internal use only */
  19.  
  20. #define    RABS    00
  21. #define    RTEXT    02
  22. #define    RDATA    04
  23. #define    RBSS    06
  24. #define    REXT    010
  25.  
  26. #define    RELFLG    01
  27. #define    NROUT    256
  28. #define    NSYM    501
  29. #define    NSYMPR    500
  30.  
  31. #define    RONLY    0400
  32.  
  33. char    premeof[] "Premature EOF on %s";
  34.  
  35. struct    page {
  36.     int    nuser;
  37.     int    bno;
  38.     int    nibuf;
  39.     int    buff[256];
  40. } page[2];
  41.  
  42. struct    {
  43.     int    nuser;
  44.     int    bno;
  45. } fpage;
  46.  
  47. struct    stream {
  48.     int    *ptr;
  49.     int    bno;
  50.     int    nibuf;
  51.     int    size;
  52.     struct    page *pno;
  53. };
  54.  
  55. struct    stream text;
  56. struct    stream reloc;
  57.  
  58. struct    archdr {
  59.     char    aname[8];
  60.     int    atime[2];
  61.     char    auid, amode;
  62.     int    asize;
  63. } archdr;
  64.  
  65. struct    filhdr {
  66.     int    fmagic;
  67.     int    tsize;
  68.     int    dsize;
  69.     int    bsize;
  70.     int    ssize;
  71.     int    entry;
  72.     int    pad;
  73.     int    relflg;
  74. } filhdr;
  75.  
  76. struct    liblist {
  77.     int    off;
  78.     int    bno;
  79. };
  80.  
  81. struct    liblist    liblist[NROUT];
  82. struct    liblist    *libp { &liblist[0] };
  83.  
  84. struct    symbol {
  85.     char    sname[8];
  86.     char    stype;
  87.     char    spad;
  88.     int    svalue;
  89. };
  90.  
  91. struct    symbol    cursym;
  92. struct    symbol    symtab[NSYM];
  93. struct    symbol    *hshtab[NSYM+2];
  94. struct    symbol    *symp { symtab };
  95. struct    symbol    **local[NSYMPR];
  96. struct    symbol    *p_etext;
  97. struct    symbol    *p_edata;
  98. struct    symbol    *p_end;
  99.  
  100. int    xflag;        /* discard local symbols */
  101. int    Xflag;        /* discard locals starting with 'L' */
  102. int    rflag;        /* preserve relocation bits, don't define common */
  103. int    arflag;        /* original copy of rflag */
  104. int    sflag;        /* discard all symbols */
  105. int    nflag;        /* pure procedure */
  106. int    dflag;        /* define common even with rflag */
  107. int    iflag;        /* I/D space separated */
  108.  
  109. int    infil;
  110. char    *filname;
  111.  
  112. int    tsize;
  113. int    dsize;
  114. int    bsize;
  115. int    ssize;
  116. int    nsym;
  117.  
  118. int    torigin;
  119. int    dorigin;
  120. int    borigin;
  121.  
  122. int    ctrel;
  123. int    cdrel;
  124. int    cbrel;
  125.  
  126. int    errlev;
  127. int    delarg    4;
  128. char    tfname[]    "/tmp/lxyyyyy";
  129. int    toutb[259];
  130. int    doutb[259];
  131. int    troutb[259];
  132. int    droutb[259];
  133. int    soutb[259];
  134.  
  135. struct    symbol    **lookup();
  136. struct    symbol    **slookup();
  137.  
  138. main(argc, argv)
  139. char **argv;
  140. {
  141.     extern int delexit();
  142.     register c;
  143.     register char *ap, **p;
  144.     struct symbol **hp;
  145.  
  146.     if ((signal(SIGINT, 1) & 01) == 0)
  147.         signal(SIGINT, delexit);
  148.     if (argc == 1)
  149.         exit(4);
  150.     p = argv + 1;
  151.     for (c = 1; c<argc; c++) {
  152.         filname = 0;
  153.         ap = *p++;
  154.         if (*ap == '-') switch (ap[1]) {
  155.  
  156.         case 'u':
  157.             if (++c >= argc)
  158.                 error(1, "Bad 'use'");
  159.             if (*(hp = slookup(*p++)) == 0) {
  160.                 *hp = symp;
  161.                 enter();
  162.             }
  163.             continue;
  164.  
  165.         case 'l':
  166.             break;
  167.  
  168.         case 'x':
  169.             xflag++;
  170.             continue;
  171.  
  172.         case 'X':
  173.             Xflag++;
  174.             continue;
  175.  
  176.         case 'r':
  177.             rflag++;
  178.             arflag++;
  179.             continue;
  180.  
  181.         case 's':
  182.             sflag++;
  183.             xflag++;
  184.             continue;
  185.  
  186.         case 'n':
  187.             nflag++;
  188.             continue;
  189.  
  190.         case 'd':
  191.             dflag++;
  192.             continue;
  193.  
  194.         case 'i':
  195.             iflag++;
  196.             continue;
  197.         }
  198.         load1arg(ap);
  199.         close(infil);
  200.     }
  201.     middle();
  202.     setupout();
  203.     p = argv+1;
  204.     libp = liblist;
  205.     for (c=1; c<argc; c++) {
  206.         ap = *p++;
  207.         if (*ap == '-') switch (ap[1]) {
  208.  
  209.         case 'u':
  210.             ++c;
  211.             ++p;
  212.         default:
  213.             continue;
  214.  
  215.         case 'l':
  216.             break;
  217.         }
  218.         load2arg(ap);
  219.         close(infil);
  220.     }
  221.     finishout();
  222. }
  223.  
  224. load1arg(acp)
  225. char *acp;
  226. {
  227.     register char *cp;
  228.     register noff, nbno;
  229.  
  230.     cp = acp;
  231.     if (getfile(cp)==0) {
  232.         load1(0, 0, 0);
  233.         return;
  234.     }
  235.     nbno = 0;
  236.     noff = 1;
  237.     for (;;) {
  238.         dseek(&text, nbno, noff, sizeof archdr);
  239.         if (text.size <= 0) {
  240.             libp->bno = -1;
  241.             libp++;
  242.             return;
  243.         }
  244.         mget(&archdr, sizeof archdr);
  245.         if (load1(1, nbno, noff + (sizeof archdr) / 2)) {
  246.             libp->bno = nbno;
  247.             libp->off = noff;
  248.             libp++;
  249.         }
  250.         noff =+ (archdr.asize + sizeof archdr)>>1;
  251.         nbno =+ (noff >> 8) & 0377;
  252.         noff =& 0377;
  253.     }
  254. }
  255.  
  256. load1(libflg, bno, off)
  257. {
  258.     register struct symbol *sp, **hp, ***cp;
  259.     struct symbol *ssymp;
  260.     int ndef, nloc;
  261.  
  262.     readhdr(bno, off);
  263.     ctrel = tsize;
  264.     cdrel =+ dsize;
  265.     cbrel =+ bsize;
  266.     ndef = 0;
  267.     nloc = sizeof cursym;
  268.     cp = local;
  269.     ssymp = symp;
  270.     if ((filhdr.relflg&RELFLG)==1) {
  271.         error(0, "No relocation bits");
  272.         return(0);
  273.     }
  274.     off =+ (sizeof filhdr)/2 + filhdr.tsize + filhdr.dsize;
  275.     dseek(&text, bno, off, filhdr.ssize);
  276.     while (text.size > 0) {
  277.         mget(&cursym, sizeof cursym);
  278.         if ((cursym.stype&EXTERN)==0) {
  279.             if (Xflag==0 || cursym.sname[0]!='L')
  280.                 nloc =+ sizeof cursym;
  281.             continue;
  282.         }
  283.         symreloc();
  284.         hp = lookup();
  285.         if ((sp = *hp) == 0) {
  286.             *hp = enter();
  287.             *cp++ = hp;
  288.             continue;
  289.         }
  290.         if (sp->stype != EXTERN+UNDEF)
  291.             continue;
  292.         if (cursym.stype == EXTERN+UNDEF) {
  293.             if (cursym.svalue > sp->svalue)
  294.                 sp->svalue = cursym.svalue;
  295.             continue;
  296.         }
  297.         if (sp->svalue != 0 && cursym.stype == EXTERN+TEXT)
  298.             continue;
  299.         ndef++;
  300.         sp->stype = cursym.stype;
  301.         sp->svalue = cursym.svalue;
  302.     }
  303.     if (libflg==0 || ndef) {
  304.         tsize =+ filhdr.tsize;
  305.         dsize =+ filhdr.dsize;
  306.         bsize =+ filhdr.bsize;
  307.         ssize =+ nloc;
  308.         return(1);
  309.     }
  310. /*
  311.  * No symbols defined by this library member.
  312.  * Rip out the hash table entries and reset the symbol table.
  313.  */
  314.     symp = ssymp;
  315.     while (cp > local)
  316.         **--cp = 0;
  317.     return(0);
  318. }
  319.  
  320. middle()
  321. {
  322.     register struct symbol *sp;
  323.     register t, csize;
  324.     int nund, corigin;
  325.  
  326.     p_etext = *slookup("_etext");
  327.     p_edata = *slookup("_edata");
  328.     p_end = *slookup("_end");
  329. /*
  330.  * If there are any undefined symbols, save the relocation bits.
  331.  */
  332.     if (rflag==0) for (sp=symtab; sp<symp; sp++)
  333.         if (sp->stype==EXTERN+UNDEF && sp->svalue==0
  334.          && sp!=p_end && sp!=p_edata && sp!=p_etext) {
  335.             rflag++;
  336.             dflag = 0;
  337.             nflag = 0;
  338.             iflag = 0;
  339.             sflag = 0;
  340.             break;
  341.         }
  342. /*
  343.  * Assign common locations.
  344.  */
  345.     csize = 0;
  346.     if (dflag || rflag==0) {
  347.         for (sp=symtab; sp<symp; sp++)
  348.             if (sp->stype==EXTERN+UNDEF && (t=sp->svalue)!=0) {
  349.                 t = (t+1) & ~01;
  350.                 sp->svalue = csize;
  351.                 sp->stype = EXTERN+COMM;
  352.                 csize =+ t;
  353.             }
  354.         if (p_etext && p_etext->stype==EXTERN+UNDEF) {
  355.             p_etext->stype = EXTERN+TEXT;
  356.             p_etext->svalue = tsize;
  357.         }
  358.         if (p_edata && p_edata->stype==EXTERN+UNDEF) {
  359.             p_edata->stype = EXTERN+DATA;
  360.             p_edata->svalue = dsize;
  361.         }
  362.         if (p_end && p_end->stype==EXTERN+UNDEF) {
  363.             p_end->stype = EXTERN+BSS;
  364.             p_end->svalue = bsize;
  365.         }
  366.     }
  367. /*
  368.  * Now set symbols to their final value
  369.  */
  370.     if (nflag || iflag)
  371.         tsize = (tsize + 077) & ~077;
  372.     dorigin = tsize;
  373.     if (nflag)
  374.         dorigin = (tsize+017777) & ~017777;
  375.     if (iflag)
  376.         dorigin = 0;
  377.     corigin = dorigin + dsize;
  378.     borigin = corigin + csize;
  379.     nund = 0;
  380.     for (sp=symtab; sp<symp; sp++) switch (sp->stype) {
  381.     case EXTERN+UNDEF:
  382.         errlev =| 01;
  383.         if (arflag==0 && sp->svalue==0) {
  384.             if (nund==0)
  385.                 printf("Undefined:\n");
  386.             nund++;
  387.             printf("%.8s\n", sp->sname);
  388.         }
  389.         continue;
  390.  
  391.     case EXTERN+ABS:
  392.     default:
  393.         continue;
  394.  
  395.     case EXTERN+TEXT:
  396.         sp->svalue =+ torigin;
  397.         continue;
  398.  
  399.     case EXTERN+DATA:
  400.         sp->svalue =+ dorigin;
  401.         continue;
  402.  
  403.     case EXTERN+BSS:
  404.         sp->svalue =+ borigin;
  405.         continue;
  406.  
  407.     case EXTERN+COMM:
  408.         sp->stype = EXTERN+BSS;
  409.         sp->svalue =+ corigin;
  410.         continue;
  411.     }
  412.     if (sflag || xflag)
  413.         ssize = 0;
  414.     bsize =+ csize;
  415.     nsym = ssize / (sizeof cursym);
  416. }
  417.  
  418. setupout()
  419. {
  420.     register char *p;
  421.     register pid;
  422.  
  423.     if ((toutb[0] = creat("l.out", 0666)) < 0)
  424.         error(1, "Can't create l.out");
  425.     pid = getpid();
  426.     for (p = &tfname[12]; p > &tfname[7];) {
  427.         *--p = (pid&07) + '0';
  428.         pid =>> 3;
  429.     }
  430.     tcreat(doutb, 'a');
  431.     if (sflag==0 || xflag==0)
  432.         tcreat(soutb, 'b');
  433.     if (rflag) {
  434.         tcreat(troutb, 'c');
  435.         tcreat(droutb, 'd');
  436.     }
  437.     filhdr.fmagic = FMAGIC;
  438.     if (nflag)
  439.         filhdr.fmagic = NMAGIC;
  440.     if (iflag)
  441.         filhdr.fmagic = IMAGIC;
  442.     filhdr.tsize = tsize;
  443.     filhdr.dsize = dsize;
  444.     filhdr.bsize = bsize;
  445.     filhdr.ssize = sflag? 0: (ssize + (sizeof cursym)*(symp-symtab));
  446.     filhdr.entry = 0;
  447.     filhdr.pad = 0;
  448.     filhdr.relflg = (rflag==0);
  449.     mput(toutb, &filhdr, sizeof filhdr);
  450.     return;
  451. }
  452.  
  453. tcreat(buf, letter)
  454. int *buf;
  455. {
  456.     tfname[6] = letter;
  457.     if ((buf[0] = creat(tfname, RONLY)) < 0)
  458.         error(1, "Can't create temp");
  459. }
  460.  
  461. load2arg(acp)
  462. char *acp;
  463. {
  464.     register char *cp;
  465.     register struct liblist *lp;
  466.  
  467.     cp = acp;
  468.     if (getfile(cp) == 0) {
  469.         while (*cp)
  470.             cp++;
  471.         while (cp >= acp && *--cp != '/');
  472.         mkfsym(++cp);
  473.         load2(0, 0);
  474.         return;
  475.     }
  476.     for (lp = libp; lp->bno != -1; lp++) {
  477.         dseek(&text, lp->bno, lp->off, sizeof archdr);
  478.         mget(&archdr, sizeof archdr);
  479.         mkfsym(archdr.aname);
  480.         load2(lp->bno, lp->off + (sizeof archdr) / 2);
  481.     }
  482.     libp = ++lp;
  483. }
  484.  
  485. load2(bno, off)
  486. {
  487.     register struct symbol *sp;
  488.     register int *lp, symno;
  489.  
  490.     readhdr(bno, off);
  491.     ctrel = torigin;
  492.     cdrel =+ dorigin;
  493.     cbrel =+ borigin;
  494. /*
  495.  * Reread the symbol table, recording the numbering
  496.  * of symbols for fixing external references.
  497.  */
  498.     lp = local;
  499.     symno = -1;
  500.     off =+ (sizeof filhdr)/2;
  501.     dseek(&text, bno, off+filhdr.tsize+filhdr.dsize, filhdr.ssize);
  502.     while (text.size > 0) {
  503.         symno++;
  504.         mget(&cursym, sizeof cursym);
  505.         symreloc();
  506.         if ((cursym.stype&EXTERN) == 0) {
  507.             if (!sflag&&!xflag&&(!Xflag||cursym.sname[0]!='L'))
  508.                 mput(soutb, &cursym, sizeof cursym);
  509.             continue;
  510.         }
  511.         if ((sp = *lookup()) == 0)
  512.             error(1, "internal error: symbol not found");
  513.         if (cursym.stype == EXTERN+UNDEF) {
  514.             if (lp >= &local[NSYMPR])
  515.                 error(1, "Local symbol overflow");
  516.             *lp++ = symno;
  517.             *lp++ = sp;
  518.             continue;
  519.         }
  520.         if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) {
  521.             printf("%.8s: ", cursym.sname);
  522.             error(0, "Multiply defined");
  523.         }
  524.     }
  525.     dseek(&text, bno, off, filhdr.tsize);
  526.     dseek(&reloc, bno, off+(filhdr.tsize+filhdr.dsize)/2, filhdr.tsize);
  527.     load2td(lp, ctrel, toutb, troutb);
  528.     dseek(&text, bno, off+(filhdr.tsize/2), filhdr.dsize);
  529.     dseek(&reloc, bno, off+filhdr.tsize+(filhdr.dsize/2), filhdr.dsize);
  530.     load2td(lp, cdrel, doutb, droutb);
  531.     torigin =+ filhdr.tsize;
  532.     dorigin =+ filhdr.dsize;
  533.     borigin =+ filhdr.bsize;
  534. }
  535.  
  536. load2td(lp, creloc, b1, b2)
  537. int *lp;
  538. {
  539.     register r, t;
  540.     register struct symbol *sp;
  541.  
  542.     for (;;) {
  543.     /*
  544.      * The pickup code is copied from "get" for speed.
  545.      */
  546.         if (--text.size <= 0) {
  547.             if (text.size < 0)
  548.                 break;
  549.             text.size++;
  550.             t = get(&text);
  551.         } else if (--text.nibuf < 0) {
  552.             text.nibuf++;
  553.             text.size++;
  554.             t = get(&text);
  555.         } else
  556.             t = *text.ptr++;
  557.         if (--reloc.size <= 0) {
  558.             if (reloc.size < 0)
  559.                 error(1, "Relocation error");
  560.             reloc.size++;
  561.             r = get(&reloc);
  562.         } else if (--reloc.nibuf < 0) {
  563.             reloc.nibuf++;
  564.             reloc.size++;
  565.             r = get(&reloc);
  566.         } else
  567.             r = *reloc.ptr++;
  568.         switch (r&016) {
  569.  
  570.         case RTEXT:
  571.             t =+ ctrel;
  572.             break;
  573.  
  574.         case RDATA:
  575.             t =+ cdrel;
  576.             break;
  577.  
  578.         case RBSS:
  579.             t =+ cbrel;
  580.             break;
  581.  
  582.         case REXT:
  583.             sp = lookloc(lp, r);
  584.             if (sp->stype==EXTERN+UNDEF) {
  585.                 r = (r&01) + ((nsym+(sp-symtab))<<4) + REXT;
  586.                 break;
  587.             }
  588.             t =+ sp->svalue;
  589.             r = (r&01) + ((sp->stype-(EXTERN+ABS))<<1);
  590.             break;
  591.         }
  592.         if (r&01)
  593.             t =- creloc;
  594.         putw(t, b1);
  595.         if (rflag)
  596.             putw(r, b2);
  597.     }
  598. }
  599.  
  600. finishout()
  601. {
  602.     register n, *p;
  603.  
  604.     if (nflag||iflag) {
  605.         n = torigin;
  606.         while (n&077) {
  607.             n =+ 2;
  608.             putw(0, toutb);
  609.             if (rflag)
  610.                 putw(0, troutb);
  611.         }
  612.     }
  613.     copy(doutb, 'a');
  614.     if (rflag) {
  615.         copy(troutb, 'c');
  616.         copy(droutb, 'd');
  617.     }
  618.     if (sflag==0) {
  619.         if (xflag==0)
  620.             copy(soutb, 'b');
  621.         for (p=symtab; p < symp;)
  622.             putw(*p++, toutb);
  623.     }
  624.     fflush(toutb);
  625.     close(toutb[0]);
  626.     unlink("a.out");
  627.     link("l.out", "a.out");
  628.     delarg = errlev;
  629.     delexit();
  630. }
  631.  
  632. delexit()
  633. {
  634.     register c;
  635.  
  636.     unlink("l.out");
  637.     for (c = 'a'; c <= 'd'; c++) {
  638.         tfname[6] = c;
  639.         unlink(tfname);
  640.     }
  641.     if (delarg==0)
  642.         chmod("a.out", 0777);
  643.     exit(delarg);
  644. }
  645.  
  646. copy(buf, c)
  647. int *buf;
  648. {
  649.     register f, *p, n;
  650.  
  651.     fflush(buf);
  652.     close(buf[0]);
  653.     tfname[6] = c;
  654.     f = open(tfname, 0);
  655.     while ((n = read(f, doutb, 512)) > 1) {
  656.         n =>> 1;
  657.         p = doutb;
  658.         do
  659.             putw(*p++, toutb);
  660.         while (--n);
  661.     }
  662.     close(f);
  663. }
  664.  
  665. mkfsym(s)
  666. char *s;
  667. {
  668.  
  669.     if (sflag || xflag)
  670.         return;
  671.     cp8c(s, cursym.sname);
  672.     cursym.stype = 037;
  673.     cursym.svalue = torigin;
  674.     mput(soutb, &cursym, sizeof cursym);
  675. }
  676.  
  677. mget(aloc, an)
  678. int *aloc;
  679. {
  680.     register *loc, n;
  681.     register *p;
  682.  
  683.     n = an;
  684.     n =>> 1;
  685.     loc = aloc;
  686.     if ((text.nibuf =- n) >= 0) {
  687.         if ((text.size =- n) > 0) {
  688.             p = text.ptr;
  689.             do
  690.                 *loc++ = *p++;
  691.             while (--n);
  692.             text.ptr = p;
  693.             return;
  694.         } else
  695.             text.size =+ n;
  696.     }
  697.     text.nibuf =+ n;
  698.     do {
  699.         *loc++ = get(&text);
  700.     } while (--n);
  701. }
  702.  
  703. mput(buf, aloc, an)
  704. int *aloc;
  705. {
  706.     register *loc;
  707.     register n;
  708.  
  709.     loc = aloc;
  710.     n = an>>1;
  711.     do {
  712.         putw(*loc++, buf);
  713.     } while (--n);
  714. }
  715.  
  716. dseek(asp, ab, o, s)
  717. {
  718.     register struct stream *sp;
  719.     register struct page *p;
  720.     register b;
  721.     int n;
  722.  
  723.     sp = asp;
  724.     b = ab + ((o>>8) & 0377);
  725.     o =& 0377;
  726.     --sp->pno->nuser;
  727.     if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b)
  728.         if (p->nuser==0 || (p = &page[0])->nuser==0) {
  729.             if (page[0].nuser==0 && page[1].nuser==0)
  730.                 if (page[0].bno < page[1].bno)
  731.                     p = &page[0];
  732.             p->bno = b;
  733.             seek(infil, b, 3);
  734.             if ((n = read(infil, p->buff, 512)>>1) < 0)
  735.                 n = 0;
  736.             p->nibuf = n;
  737.         } else
  738.             error(1, "No pages");
  739.     ++p->nuser;
  740.     sp->bno = b;
  741.     sp->pno = p;
  742.     sp->ptr = p->buff + o;
  743.     if (s != -1)
  744.         sp->size = (s>>1) & 077777;
  745.     if ((sp->nibuf = p->nibuf-o) <= 0)
  746.         sp->size = 0;
  747. }
  748.  
  749. get(asp)
  750. struct stream *asp;
  751. {
  752.     register struct stream *sp;
  753.  
  754.     sp = asp;
  755.     if (--sp->nibuf < 0) {
  756.         dseek(sp, sp->bno+1, 0, -1);
  757.         --sp->nibuf;
  758.     }
  759.     if (--sp->size <= 0) {
  760.         if (sp->size < 0)
  761.             error(1, premeof);
  762.         ++fpage.nuser;
  763.         --sp->pno->nuser;
  764.         sp->pno = &fpage;
  765.     }
  766.     return(*sp->ptr++);
  767. }
  768.  
  769. getfile(acp)
  770. char *acp;
  771. {
  772.     register char *cp;
  773.     register c;
  774.  
  775.     cp = acp;
  776.     archdr.aname[0] = '\0';
  777.     if (cp[0]=='-' && cp[1]=='l') {
  778.         if ((c = cp[2]) == '\0')
  779.             c = 'a';
  780.         cp = "/lib/lib?.a";
  781.         cp[8] = c;
  782.     }
  783.     filname = cp;
  784.     if ((infil = open(cp, 0)) < 0)
  785.         error(1, "cannot open");
  786.     page[0].bno = page[1].bno = -1;
  787.     page[0].nuser = page[1].nuser = 0;
  788.     text.pno = reloc.pno = &fpage;
  789.     fpage.nuser = 2;
  790.     dseek(&text, 0, 0, 2);
  791.     if (text.size <= 0)
  792.         error(1, premeof);
  793.     return(get(&text) == ARCMAGIC);
  794. }
  795.  
  796. struct symbol **lookup()
  797. {
  798.     int i;
  799.     register struct symbol **hp;
  800.     register char *cp, *cp1;
  801.  
  802.     i = 0;
  803.     for (cp=cursym.sname; cp < &cursym.sname[8];)
  804.         i = (i<<1) + *cp++;
  805.     for (hp = &hshtab[(i&077777)%NSYM+2]; *hp!=0;) {
  806.         cp1 = (*hp)->sname;
  807.         for (cp=cursym.sname; cp < &cursym.sname[8];)
  808.             if (*cp++ != *cp1++)
  809.                 goto no;
  810.         break;
  811.         no:
  812.         if (++hp >= &hshtab[NSYM+2])
  813.             hp = hshtab;
  814.     }
  815.     return(hp);
  816. }
  817.  
  818. struct symbol **slookup(s)
  819. char *s;
  820. {
  821.     cp8c(s, cursym.sname);
  822.     cursym.stype = EXTERN+UNDEF;
  823.     cursym.svalue = 0;
  824.     return(lookup());
  825. }
  826.  
  827. enter()
  828. {
  829.     register struct symbol *sp;
  830.     
  831.     if ((sp=symp) >= &symtab[NSYM])
  832.         error(1, "Symbol table overflow");
  833.     cp8c(cursym.sname, sp->sname);
  834.     sp->stype = cursym.stype;
  835.     sp->svalue = cursym.svalue;
  836.     symp++;
  837.     return(sp);
  838. }
  839.  
  840. symreloc()
  841. {
  842.     switch (cursym.stype) {
  843.  
  844.     case TEXT:
  845.     case EXTERN+TEXT:
  846.         cursym.svalue =+ ctrel;
  847.         return;
  848.  
  849.     case DATA:
  850.     case EXTERN+DATA:
  851.         cursym.svalue =+ cdrel;
  852.         return;
  853.  
  854.     case BSS:
  855.     case EXTERN+BSS:
  856.         cursym.svalue =+ cbrel;
  857.         return;
  858.  
  859.     case EXTERN+UNDEF:
  860.         return;
  861.     }
  862.     if (cursym.stype&EXTERN)
  863.         cursym.stype = EXTERN+ABS;
  864. }
  865.  
  866. error(n, s)
  867. char *s;
  868. {
  869.     if (filname) {
  870.         printf("%s", filname);
  871.         if (archdr.aname[0])
  872.             printf("(%.8s)", archdr.aname);
  873.         printf(": ");
  874.     }
  875.     printf("%s\n", s);
  876.     if (n)
  877.         delexit();
  878.     errlev = 2;
  879. }
  880.  
  881. lookloc(alp, r)
  882. {
  883.     register int *clp, *lp;
  884.     register sn;
  885.  
  886.     lp = alp;
  887.     sn = (r>>4) & 07777;
  888.     for (clp=local; clp<lp; clp =+ 2)
  889.         if (clp[0] == sn)
  890.             return(clp[1]);
  891.     error(1, "Local symbol botch");
  892. }
  893.  
  894. readhdr(bno, off)
  895. {
  896.     register st, sd;
  897.  
  898.     dseek(&text, bno, off, sizeof filhdr);
  899.     mget(&filhdr, sizeof filhdr);
  900.     if (filhdr.fmagic != FMAGIC)
  901.         error(1, "Bad format");
  902.     st = (filhdr.tsize+01) & ~01;
  903.     filhdr.tsize = st;
  904.     cdrel = -st;
  905.     sd = (filhdr.dsize+01) & ~01;
  906.     cbrel = - (st+sd);
  907.     filhdr.bsize = (filhdr.bsize+01) & ~01;
  908. }
  909.  
  910. cp8c(from, to)
  911. char *from, *to;
  912. {
  913.     register char *f, *t, *te;
  914.  
  915.     f = from;
  916.     t = to;
  917.     te = t+8;
  918.     while ((*t++ = *f++) && t<te);
  919.     while (t<te)
  920.         *t++ = 0;
  921. }
  922.