home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / ld.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-05-15  |  22.4 KB  |  1,299 lines

  1. /*
  2.  *  link editor
  3.  */
  4.  
  5. #include <signal.h>
  6. #include "sys/types.h"
  7. #include "sys/stat.h"
  8.  
  9. /*    Layout of a.out file :
  10.  *
  11.  *    header of 8 words    magic number 405, 407, 410, 411
  12.  *                text size    )
  13.  *                data size    ) in bytes but even
  14.  *                bss size    )
  15.  *                symbol table size
  16.  *                entry point
  17.  *                {unused}
  18.  *                flag set if no relocation
  19.  *
  20.  *
  21.  *    header:        0
  22.  *    text:        16
  23.  *    data:        16+textsize
  24.  *    relocation:    16+textsize+datasize
  25.  *    symbol table:    16+2*(textsize+datasize) or 16+textsize+datasize
  26.  *
  27.  */
  28. #define TRUE    1
  29. #define FALSE    0
  30.  
  31.  
  32. #define    ARCMAGIC 0177545
  33. #define OMAGIC    0405
  34. #define    FMAGIC    0407
  35. #define    NMAGIC    0410
  36. #define    IMAGIC    0411
  37.  
  38. #define    EXTERN    040
  39. #define    UNDEF    00
  40. #define    ABS    01
  41. #define    TEXT    02
  42. #define    DATA    03
  43. #define    BSS    04
  44. #define    COMM    05    /* internal use only */
  45.  
  46. #define    RABS    00
  47. #define    RTEXT    02
  48. #define    RDATA    04
  49. #define    RBSS    06
  50. #define    REXT    010
  51.  
  52. #define NOVLY    16
  53. #define    RELFLG    01
  54. #define    NROUT    256
  55. #define    NSYM    1103
  56. #define    NSYMPR    1000
  57.  
  58. char    premeof[] = "Premature EOF";
  59. char    goodnm[] = "__.SYMDEF";
  60.  
  61. /* table of contents stuff */
  62. #define TABSZ    700
  63. struct tab
  64. {    char cname[8];
  65.     long cloc;
  66. } tab[TABSZ];
  67. int tnum;
  68.  
  69.  
  70. /* overlay management */
  71. int    vindex;
  72. struct overlay {
  73.     int    argsav;
  74.     int    symsav;
  75.     struct liblist    *libsav;
  76.     char    *vname;
  77.     int    ctsav, cdsav, cbsav;
  78.     int    offt, offd, offb, offs;
  79. } vnodes[NOVLY];
  80.  
  81. /* input management */
  82. struct page {
  83.     int    nuser;
  84.     int    bno;
  85.     int    nibuf;
  86.     int    buff[256];
  87. } page[2];
  88.  
  89. struct {
  90.     int    nuser;
  91.     int    bno;
  92. } fpage;
  93.  
  94. struct stream {
  95.     int    *ptr;
  96.     int    bno;
  97.     int    nibuf;
  98.     int    size;
  99.     struct page    *pno;
  100. };
  101.  
  102. struct stream text;
  103. struct stream reloc;
  104.  
  105. struct {
  106.     char    aname[14];
  107.     long    atime;
  108.     char    auid, agid;
  109.     int    amode;
  110.     long    asize;
  111. } archdr;
  112.  
  113. struct {
  114.     int    fmagic;
  115.     int    tsize;
  116.     int    dsize;
  117.     int    bsize;
  118.     int    ssize;
  119.     int    entry;
  120.     int    pad;
  121.     int    relflg;
  122. } filhdr;
  123.  
  124.  
  125. /* one entry for each archive member referenced;
  126.  * set in first pass; needs restoring for overlays
  127.  */
  128. struct liblist {
  129.     long    loc;
  130. };
  131.  
  132. struct liblist    liblist[NROUT];
  133. struct liblist    *libp = liblist;
  134.  
  135.  
  136. /* symbol management */
  137. struct symbol {
  138.     char    sname[8];
  139.     char    stype;
  140.     char    spare;
  141.     int    svalue;
  142. };
  143.  
  144. struct local {
  145.     int locindex;        /* index to symbol in file */
  146.     struct symbol *locsymbol;    /* ptr to symbol table */
  147. };
  148.  
  149. struct symbol    cursym;            /* current symbol */
  150. struct symbol    symtab[NSYM];        /* actual symbols */
  151. struct symbol    **symhash[NSYM];    /* ptr to hash table entry */
  152. struct symbol    *lastsym;        /* last symbol entered */
  153. int    symindex;        /* next available symbol table entry */
  154. struct symbol    *hshtab[NSYM+2];    /* hash table for symbols */
  155. struct local    local[NSYMPR];
  156.  
  157. /* internal symbols */
  158. struct symbol    *p_etext;
  159. struct symbol    *p_edata;
  160. struct symbol    *p_end;
  161. struct symbol    *entrypt;
  162.  
  163. int    trace;
  164. /* flags */
  165. int    xflag;        /* discard local symbols */
  166. int    Xflag;        /* discard locals starting with 'L' */
  167. int    Sflag;        /* discard all except locals and globals*/
  168. int    rflag;        /* preserve relocation bits, don't define common */
  169. int    arflag;        /* original copy of rflag */
  170. int    sflag;        /* discard all symbols */
  171. int    nflag;        /* pure procedure */
  172. int    Oflag;        /* set magic # to 0405 (overlay) */
  173. int    dflag;        /* define common even with rflag */
  174. int    iflag;        /* I/D space separated */
  175. int    vflag;        /* overlays used */
  176.  
  177. int    ofilfnd;
  178. char    *ofilename = "l.out";
  179. int    infil;
  180. char    *filname;
  181.  
  182. /* cumulative sizes set in pass 1 */
  183. int    tsize;
  184. int    dsize;
  185. int    bsize;
  186. int    ssize;
  187.  
  188. /* symbol relocation; both passes */
  189. int    ctrel;
  190. int    cdrel;
  191. int    cbrel;
  192.  
  193. int    errlev;
  194. int    delarg    = 4;
  195. char    tfname[] = "/tmp/ldaXXXXX";
  196.  
  197.  
  198. /* output management */
  199. struct buf {
  200.     int    fildes;
  201.     int    nleft;
  202.     int    *xnext;
  203.     int    iobuf[256];
  204. };
  205. struct buf    toutb;
  206. struct buf    doutb;
  207. struct buf    troutb;
  208. struct buf    droutb;
  209. struct buf    soutb;
  210.  
  211. struct symbol    **lookup();
  212. struct symbol    **slookup();
  213. struct symbol    *lookloc();
  214.  
  215. delexit()
  216. {
  217.     unlink("l.out");
  218.     if (delarg==0)
  219.         chmod(ofilename, 0777 & ~umask(0));
  220.     exit(delarg);
  221. }
  222.  
  223. main(argc, argv)
  224. char **argv;
  225. {
  226.     register int c, i; 
  227.     int num;
  228.     register char *ap, **p;
  229.     int found; 
  230.     int vscan; 
  231.     char save;
  232.  
  233.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  234.         signal(SIGINT, delexit);
  235.     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  236.         signal(SIGTERM, delexit);
  237.     if (argc == 1)
  238.         exit(4);
  239.     p = argv+1;
  240.  
  241.     /* scan files once to find symdefs */
  242.     for (c=1; c<argc; c++) {
  243.         if (trace) printf("%s:\n", *p);
  244.         filname = 0;
  245.         ap = *p++;
  246.  
  247.         if (*ap == '-') {
  248.             for (i=1; ap[i]; i++) {
  249.             switch (ap[i]) {
  250.             case 'o':
  251.                 if (++c >= argc)
  252.                     error(2, "Bad output file");
  253.                 ofilename = *p++;
  254.                 ofilfnd++;
  255.                 continue;
  256.  
  257.             case 'u':
  258.             case 'e':
  259.                 if (++c >= argc)
  260.                     error(2, "Bad 'use' or 'entry'");
  261.                 enter(slookup(*p++));
  262.                 if (ap[i]=='e')
  263.                     entrypt = lastsym;
  264.                 continue;
  265.  
  266.             case 'v':
  267.                 if (++c >= argc)
  268.                     error(2, "-v: arg missing");
  269.                 vflag=TRUE;
  270.                 vscan = vindex; 
  271.                 found=FALSE;
  272.                 while (--vscan>=0 && found==FALSE)
  273.                     found = eq(vnodes[vscan].vname, *p);
  274.                 if (found) {
  275.                     endload(c, argv);
  276.                     restore(vscan);
  277.                 } else
  278.                     record(c, *p);
  279.                 p++;
  280.                 continue;
  281.  
  282.             case 'D':
  283.                 if (++c >= argc)
  284.                     error(2, "-D: arg missing");
  285.                 num = atoi(*p++);
  286.                 if (dsize>num)
  287.                     error(2, "-D: too small");
  288.                 dsize = num;
  289.                 continue;
  290.  
  291.             case 'l':
  292.                 save = ap[--i]; 
  293.                 ap[i]='-';
  294.                 load1arg(&ap[i]); 
  295.                 ap[i]=save;
  296.                 break;
  297.  
  298.             case 'x':
  299.                 xflag++;
  300.                 continue;
  301.  
  302.             case 'X':
  303.                 Xflag++;
  304.                 continue;
  305.  
  306.             case 'S':
  307.                 Sflag++; 
  308.                 continue;
  309.  
  310.             case 'r':
  311.                 rflag++;
  312.                 arflag++;
  313.                 continue;
  314.  
  315.             case 's':
  316.                 sflag++;
  317.                 xflag++;
  318.                 continue;
  319.  
  320.             case 'n':
  321.                 nflag++;
  322.                 continue;
  323.  
  324.             case 'd':
  325.                 dflag++;
  326.                 continue;
  327.  
  328.             case 'i':
  329.                 iflag++;
  330.                 continue;
  331.  
  332.             case 'O':
  333.                 Oflag++;
  334.                 continue;
  335.  
  336.             case 't':
  337.                 trace++;
  338.                 continue;
  339.  
  340.             default:
  341.                 error(2, "bad flag");
  342.             } /*endsw*/
  343.             break;
  344.             } /*endfor*/
  345.         } else
  346.             load1arg(ap);
  347.     }
  348.     endload(argc, argv);
  349. }
  350.  
  351. /* used after pass 1 */
  352. int    nsym;
  353. int    torigin;
  354. int    dorigin;
  355. int    borigin;
  356.  
  357. endload(argc, argv)
  358. int argc; 
  359. char **argv;
  360. {
  361.     register int c, i; 
  362.     int dnum;
  363.     register char *ap, **p;
  364.     filname = 0;
  365.     middle();
  366.     setupout();
  367.     p = argv+1;
  368.     libp = liblist;
  369.     for (c=1; c<argc; c++) {
  370.         ap = *p++;
  371.         if (trace) printf("%s:\n", ap);
  372.         if (*ap == '-') {
  373.             for (i=1; ap[i]; i++) {
  374.             switch (ap[i]) {
  375.             case 'D':
  376.                 for (dnum = atoi(*p); dorigin<dnum; dorigin += 2) {
  377.                     putw(0, &doutb);
  378.                     if (rflag)
  379.                         putw(0, &droutb);
  380.                 }
  381.             case 'u':
  382.             case 'e':
  383.             case 'o':
  384.             case 'v':
  385.                 ++c; 
  386.                 ++p;
  387.  
  388.             default:
  389.                 continue;
  390.  
  391.             case 'l':
  392.                 ap[--i]='-'; 
  393.                 load2arg(&ap[i]);
  394.                 break;
  395.             } /*endsw*/
  396.             break;
  397.             } /*endfor*/
  398.         } else
  399.             load2arg(ap);
  400.     }
  401.     finishout();
  402. }
  403.  
  404. record(c, nam)
  405. int c; 
  406. char *nam;
  407. {
  408.     register struct overlay *v;
  409.  
  410.     v = &vnodes[vindex++];
  411.     v->argsav = c;
  412.     v->symsav = symindex;
  413.     v->libsav = libp;
  414.     v->vname = nam;
  415.     v->offt = tsize; 
  416.     v->offd = dsize; 
  417.     v->offb = bsize; 
  418.     v->offs = ssize;
  419.     v->ctsav = ctrel; 
  420.     v->cdsav = cdrel; 
  421.     v->cbsav = cbrel;
  422. }
  423.  
  424. restore(vscan)
  425. int vscan;
  426. {
  427.     register struct overlay *v;
  428.     register int saved;
  429.  
  430.     v = &vnodes[vscan];
  431.     vindex = vscan+1;
  432.     libp = v->libsav;
  433.     ctrel = v->ctsav; 
  434.     cdrel = v->cdsav; 
  435.     cbrel = v->cbsav;
  436.     tsize = v->offt; 
  437.     dsize = v->offd; 
  438.     bsize = v->offb; 
  439.     ssize = v->offs;
  440.     saved = v->symsav;
  441.     while (symindex>saved)
  442.         *symhash[--symindex]=0;
  443. }
  444.  
  445. /* scan file to find defined symbols */
  446. load1arg(acp)
  447. char *acp;
  448. {
  449.     register char *cp;
  450.     long nloc;
  451.  
  452.     cp = acp;
  453.     switch ( getfile(cp)) {
  454.     case 0:
  455.         load1(0, 0L);
  456.         break;
  457.  
  458.     /* regular archive */
  459.     case 1:
  460.         nloc = 1;
  461.         while ( step(nloc))
  462.             nloc += (archdr.asize + sizeof(archdr) + 1) >> 1;
  463.         break;
  464.  
  465.     /* table of contents */
  466.     case 2:
  467.         tnum = archdr.asize / sizeof(struct tab);
  468.         if (tnum >= TABSZ) {
  469.             error(2, "fast load buffer too small");
  470.         }
  471.         lseek(infil, (long)(sizeof(filhdr.fmagic)+sizeof(archdr)), 0);
  472.         read(infil, (char *)tab, tnum * sizeof(struct tab));
  473.         while (ldrand());
  474.         libp->loc = -1;
  475.         libp++;
  476.         break;
  477.     /* out of date table of contents */
  478.     case 3:
  479.         error(0, "out of date (warning)");
  480.         for(nloc = 1+((archdr.asize+sizeof(archdr)+1) >> 1); step(nloc);
  481.             nloc += (archdr.asize + sizeof(archdr) + 1) >> 1);
  482.         break;
  483.     }
  484.     close(infil);
  485. }
  486.  
  487. step(nloc)
  488. long nloc;
  489. {
  490.     dseek(&text, nloc, sizeof archdr);
  491.     if (text.size <= 0) {
  492.         libp->loc = -1;
  493.         libp++;
  494.         return(0);
  495.     }
  496.     mget((int *)&archdr, sizeof archdr);
  497.     if (load1(1, nloc + (sizeof archdr) / 2)) {
  498.         libp->loc = nloc;
  499.         libp++;
  500.     }
  501.     return(1);
  502. }
  503.  
  504. ldrand()
  505. {
  506.     int i;
  507.     struct symbol *sp, **pp;
  508.     struct liblist *oldp = libp;
  509.     for(i = 0; i<tnum; i++) {
  510.         if ((pp = slookup(tab[i].cname)) == 0)
  511.             continue;
  512.         sp = *pp;
  513.         if (sp->stype != EXTERN+UNDEF)
  514.             continue;
  515.         step(tab[i].cloc >> 1);
  516.     }
  517.     return(oldp != libp);
  518. }
  519.  
  520. add(a,b,s)
  521. int a, b;
  522. char *s;
  523. {
  524.     long r;
  525.  
  526.     r = (long)(unsigned)a + (unsigned)b;
  527.     if (r >= 0200000)
  528.         error(1,s);
  529.     return(r);
  530. }
  531.  
  532.  
  533. /* single file or archive member */
  534. load1(libflg, loc)
  535. long loc;
  536. {
  537.     register struct symbol *sp;
  538.     int savindex;
  539.     int ndef, nloc, type, mtype;
  540.  
  541.     readhdr(loc);
  542.     ctrel = tsize;
  543.     cdrel += dsize;
  544.     cbrel += bsize;
  545.     ndef = 0;
  546.     nloc = sizeof cursym;
  547.     savindex = symindex;
  548.     if ((filhdr.relflg&RELFLG)==1) {
  549.         error(1, "No relocation bits");
  550.         return(0);
  551.     }
  552.     loc += (sizeof filhdr)/2 + filhdr.tsize + filhdr.dsize;
  553.     dseek(&text, loc, filhdr.ssize);
  554.     while (text.size > 0) {
  555.         mget((int *)&cursym, sizeof cursym);
  556.         type = cursym.stype;
  557.         if (Sflag) {
  558.             mtype = type&037;
  559.             if (mtype==1 || mtype>4) {
  560.                 continue;
  561.             }
  562.         }
  563.         if ((type&EXTERN)==0) {
  564.             if (Xflag==0 || cursym.sname[0]!='L')
  565.                 nloc += sizeof cursym;
  566.             continue;
  567.         }
  568.         symreloc();
  569.         if (enter(lookup()))
  570.             continue;
  571.         if ((sp = lastsym)->stype != EXTERN+UNDEF)
  572.             continue;
  573.         if (cursym.stype == EXTERN+UNDEF) {
  574.             if (cursym.svalue > sp->svalue)
  575.                 sp->svalue = cursym.svalue;
  576.             continue;
  577.         }
  578.         if (sp->svalue != 0 && cursym.stype == EXTERN+TEXT)
  579.             continue;
  580.         ndef++;
  581.         sp->stype = cursym.stype;
  582.         sp->svalue = cursym.svalue;
  583.     }
  584.     if (libflg==0 || ndef) {
  585.         tsize = add(tsize,filhdr.tsize,"text overflow");
  586.         dsize = add(dsize,filhdr.dsize,"data overflow");
  587.         bsize = add(bsize,filhdr.bsize,"bss overflow");
  588.         ssize = add(ssize,nloc,"symbol table overflow");
  589.         return(1);
  590.     }
  591.     /*
  592.      * No symbols defined by this library member.
  593.      * Rip out the hash table entries and reset the symbol table.
  594.      */
  595.     while (symindex>savindex)
  596.         *symhash[--symindex]=0;
  597.     return(0);
  598. }
  599.  
  600. middle()
  601. {
  602.     register struct symbol *sp, *symp;
  603.     register t, csize;
  604.     int nund, corigin;
  605.  
  606.     torigin=0; 
  607.     dorigin=0; 
  608.     borigin=0;
  609.  
  610.     p_etext = *slookup("_etext");
  611.     p_edata = *slookup("_edata");
  612.     p_end = *slookup("_end");
  613.     /*
  614.      * If there are any undefined symbols, save the relocation bits.
  615.      */
  616.     symp = &symtab[symindex];
  617.     if (rflag==0) {
  618.         for (sp = symtab; sp<symp; sp++)
  619.             if (sp->stype==EXTERN+UNDEF && sp->svalue==0
  620.                 && sp!=p_end && sp!=p_edata && sp!=p_etext) {
  621.                 rflag++;
  622.                 dflag = 0;
  623.                 break;
  624.             }
  625.     }
  626.     if (rflag)
  627.         nflag = sflag = iflag = Oflag = 0;
  628.     /*
  629.      * Assign common locations.
  630.      */
  631.     csize = 0;
  632.     if (dflag || rflag==0) {
  633.         ldrsym(p_etext, tsize, EXTERN+TEXT);
  634.         ldrsym(p_edata, dsize, EXTERN+DATA);
  635.         ldrsym(p_end, bsize, EXTERN+BSS);
  636.         for (sp = symtab; sp<symp; sp++)
  637.             if (sp->stype==EXTERN+UNDEF && (t = sp->svalue)!=0) {
  638.                 t = (t+1) & ~01;
  639.                 sp->svalue = csize;
  640.                 sp->stype = EXTERN+COMM;
  641.                 csize = add(csize, t, "bss overflow");
  642.             }
  643.     }
  644.     /*
  645.      * Now set symbols to their final value
  646.      */
  647.     if (nflag || iflag)
  648.         tsize = (tsize + 077) & ~077;
  649.     dorigin = tsize;
  650.     if (nflag)
  651.         dorigin = (tsize+017777) & ~017777;
  652.     if (iflag)
  653.         dorigin = 0;
  654.     corigin = dorigin + dsize;
  655.     borigin = corigin + csize;
  656.     nund = 0;
  657.     for (sp = symtab; sp<symp; sp++) switch (sp->stype) {
  658.     case EXTERN+UNDEF:
  659.         errlev |= 01;
  660.         if (arflag==0 && sp->svalue==0) {
  661.             if (nund==0)
  662.                 printf("Undefined:\n");
  663.             nund++;
  664.             printf("%.8s\n", sp->sname);
  665.         }
  666.         continue;
  667.  
  668.     case EXTERN+ABS:
  669.     default:
  670.         continue;
  671.  
  672.     case EXTERN+TEXT:
  673.         sp->svalue += torigin;
  674.         continue;
  675.  
  676.     case EXTERN+DATA:
  677.         sp->svalue += dorigin;
  678.         continue;
  679.  
  680.     case EXTERN+BSS:
  681.         sp->svalue += borigin;
  682.         continue;
  683.  
  684.     case EXTERN+COMM:
  685.         sp->stype = EXTERN+BSS;
  686.         sp->svalue += corigin;
  687.         continue;
  688.     }
  689.     if (sflag || xflag)
  690.         ssize = 0;
  691.     bsize = add(bsize, csize, "bss overflow");
  692.     nsym = ssize / (sizeof cursym);
  693. }
  694.  
  695. ldrsym(asp, val, type)
  696. struct symbol *asp;
  697. {
  698.     register struct symbol *sp;
  699.  
  700.     if ((sp = asp) == 0)
  701.         return;
  702.     if (sp->stype != EXTERN+UNDEF || sp->svalue) {
  703.         printf("%.8s: ", sp->sname);
  704.         error(1, "Multiply defined");
  705.         return;
  706.     }
  707.     sp->stype = type;
  708.     sp->svalue = val;
  709. }
  710.  
  711. setupout()
  712. {
  713.     tcreat(&toutb, 0);
  714.     mktemp(tfname);
  715.     tcreat(&doutb, 1);
  716.     if (sflag==0 || xflag==0)
  717.         tcreat(&soutb, 1);
  718.     if (rflag) {
  719.         tcreat(&troutb, 1);
  720.         tcreat(&droutb, 1);
  721.     }
  722.     filhdr.fmagic = (Oflag ? OMAGIC :( iflag ? IMAGIC : ( nflag ? NMAGIC : FMAGIC )));
  723.     filhdr.tsize = tsize;
  724.     filhdr.dsize = dsize;
  725.     filhdr.bsize = bsize;
  726.     filhdr.ssize = sflag? 0: (ssize + (sizeof cursym)*symindex);
  727.     if (entrypt) {
  728.         if (entrypt->stype!=EXTERN+TEXT)
  729.             error(1, "Entry point not in text");
  730.         else
  731.             filhdr.entry = entrypt->svalue | 01;
  732.     } else
  733.         filhdr.entry=0;
  734.     filhdr.pad = 0;
  735.     filhdr.relflg = (rflag==0);
  736.     mput(&toutb, (int *)&filhdr, sizeof filhdr);
  737. }
  738.  
  739. tcreat(buf, tempflg)
  740. struct buf *buf;
  741. {
  742.     register int ufd; 
  743.     char *nam;
  744.     nam = (tempflg ? tfname : ofilename);
  745.     if ((ufd = creat(nam, 0666)) < 0)
  746.         error(2, tempflg?"cannot create temp":"cannot create output");
  747.     close(ufd); 
  748.     buf->fildes = open(nam, 2);
  749.     if (tempflg)
  750.         unlink(tfname);
  751.     buf->nleft = sizeof(buf->iobuf)/sizeof(int);
  752.     buf->xnext = buf->iobuf;
  753. }
  754.  
  755. load2arg(acp)
  756. char *acp;
  757. {
  758.     register char *cp;
  759.     register struct liblist *lp;
  760.  
  761.     cp = acp;
  762.     if (getfile(cp) == 0) {
  763.         while (*cp)
  764.             cp++;
  765.         while (cp >= acp && *--cp != '/');
  766.         mkfsym(++cp);
  767.         load2(0L);
  768.     } else {    /* scan archive members referenced */
  769.         for (lp = libp; lp->loc != -1; lp++) {
  770.             dseek(&text, lp->loc, sizeof archdr);
  771.             mget((int *)&archdr, sizeof archdr);
  772.             mkfsym(archdr.aname);
  773.             load2(lp->loc + (sizeof archdr) / 2);
  774.         }
  775.         libp = ++lp;
  776.     }
  777.     close(infil);
  778. }
  779.  
  780. load2(loc)
  781. long loc;
  782. {
  783.     register struct symbol *sp;
  784.     register struct local *lp;
  785.     register int symno;
  786.     int type, mtype;
  787.  
  788.     readhdr(loc);
  789.     ctrel = torigin;
  790.     cdrel += dorigin;
  791.     cbrel += borigin;
  792.     /*
  793.      * Reread the symbol table, recording the numbering
  794.      * of symbols for fixing external references.
  795.      */
  796.     lp = local;
  797.     symno = -1;
  798.     loc += (sizeof filhdr)/2;
  799.     dseek(&text, loc + filhdr.tsize + filhdr.dsize, filhdr.ssize);
  800.     while (text.size > 0) {
  801.         symno++;
  802.         mget((int *)&cursym, sizeof cursym);
  803.         symreloc();
  804.         type = cursym.stype;
  805.         if (Sflag) {
  806.             mtype = type&037;
  807.             if (mtype==1 || mtype>4) continue;
  808.         }
  809.         if ((type&EXTERN) == 0) {
  810.             if (!sflag&&!xflag&&(!Xflag||cursym.sname[0]!='L'))
  811.                 mput(&soutb, (int *)&cursym, sizeof cursym);
  812.             continue;
  813.         }
  814.         if ((sp = *lookup()) == 0)
  815.             error(2, "internal error: symbol not found");
  816.         if (cursym.stype == EXTERN+UNDEF) {
  817.             if (lp >= &local[NSYMPR])
  818.                 error(2, "Local symbol overflow");
  819.             lp->locindex = symno;
  820.             lp++->locsymbol = sp;
  821.             continue;
  822.         }
  823.         if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) {
  824.             printf("%.8s: ", cursym.sname);
  825.             error(1, "Multiply defined");
  826.         }
  827.     }
  828.     dseek(&text, loc, filhdr.tsize);
  829.     dseek(&reloc, loc + half(filhdr.tsize + filhdr.dsize), filhdr.tsize);
  830.     load2td(lp, ctrel, &toutb, &troutb);
  831.     dseek(&text, loc+half(filhdr.tsize), filhdr.dsize);
  832.     dseek(&reloc, loc+filhdr.tsize+half(filhdr.dsize), filhdr.dsize);
  833.     load2td(lp, cdrel, &doutb, &droutb);
  834.     torigin += filhdr.tsize;
  835.     dorigin += filhdr.dsize;
  836.     borigin += filhdr.bsize;
  837. }
  838.  
  839. load2td(lp, creloc, b1, b2)
  840. struct local *lp;
  841. struct buf *b1, *b2;
  842. {
  843.     register r, t;
  844.     register struct symbol *sp;
  845.  
  846.     for (;;) {
  847.         /*
  848.              * The pickup code is copied from "get" for speed.
  849.              */
  850.  
  851.         /* next text or data word */
  852.         if (--text.size <= 0) {
  853.             if (text.size < 0)
  854.                 break;
  855.             text.size++;
  856.             t = get(&text);
  857.         } else if (--text.nibuf < 0) {
  858.             text.nibuf++;
  859.             text.size++;
  860.             t = get(&text);
  861.         } else
  862.             t = *text.ptr++;
  863.  
  864.         /* next relocation word */
  865.         if (--reloc.size <= 0) {
  866.             if (reloc.size < 0)
  867.                 error(2, "Relocation error");
  868.             reloc.size++;
  869.             r = get(&reloc);
  870.         } else if (--reloc.nibuf < 0) {
  871.             reloc.nibuf++;
  872.             reloc.size++;
  873.             r = get(&reloc);
  874.         } else
  875.             r = *reloc.ptr++;
  876.  
  877.         switch (r&016) {
  878.  
  879.         case RTEXT:
  880.             t += ctrel;
  881.             break;
  882.  
  883.         case RDATA:
  884.             t += cdrel;
  885.             break;
  886.  
  887.         case RBSS:
  888.             t += cbrel;
  889.             break;
  890.  
  891.         case REXT:
  892.             sp = lookloc(lp, r);
  893.             if (sp->stype==EXTERN+UNDEF) {
  894.                 r = (r&01) + ((nsym+(sp-symtab))<<4) + REXT;
  895.                 break;
  896.             }
  897.             t += sp->svalue;
  898.             r = (r&01) + ((sp->stype-(EXTERN+ABS))<<1);
  899.             break;
  900.         }
  901.         if (r&01)
  902.             t -= creloc;
  903.         putw(t, b1);
  904.         if (rflag)
  905.             putw(r, b2);
  906.     }
  907. }
  908.  
  909. finishout()
  910. {
  911.     register n, *p;
  912.  
  913.     if (nflag||iflag) {
  914.         n = torigin;
  915.         while (n&077) {
  916.             n += 2;
  917.             putw(0, &toutb);
  918.             if (rflag)
  919.                 putw(0, &troutb);
  920.         }
  921.     }
  922.     copy(&doutb);
  923.     if (rflag) {
  924.         copy(&troutb);
  925.         copy(&droutb);
  926.     }
  927.     if (sflag==0) {
  928.         if (xflag==0)
  929.             copy(&soutb);
  930.         for (p = (int *)symtab; p < (int *)&symtab[symindex];)
  931.             putw(*p++, &toutb);
  932.     }
  933.     flush(&toutb);
  934.     close(toutb.fildes);
  935.     if (!ofilfnd) {
  936.         unlink("a.out");
  937.         link("l.out", "a.out");
  938.         ofilename = "a.out";
  939.     }
  940.     delarg = errlev;
  941.     delexit();
  942. }
  943.  
  944. copy(buf)
  945. struct buf *buf;
  946. {
  947.     register f, *p, n;
  948.  
  949.     flush(buf);
  950.     lseek(f = buf->fildes, (long)0, 0);
  951.     while ((n = read(f, (char *)doutb.iobuf, sizeof(doutb.iobuf))) > 1) {
  952.         n >>= 1;
  953.         p = (int *)doutb.iobuf;
  954.         do
  955.             putw(*p++, &toutb);
  956.         while (--n);
  957.     }
  958.     close(f);
  959. }
  960.  
  961. mkfsym(s)
  962. char *s;
  963. {
  964.  
  965.     if (sflag || xflag)
  966.         return;
  967.     cp8c(s, cursym.sname);
  968.     cursym.stype = 037;
  969.     cursym.svalue = torigin;
  970.     mput(&soutb, (int *)&cursym, sizeof cursym);
  971. }
  972.  
  973. mget(aloc, an)
  974. int *aloc;
  975. {
  976.     register *loc, n;
  977.     register *p;
  978.  
  979.     n = an;
  980.     n >>= 1;
  981.     loc = aloc;
  982.     if ((text.nibuf -= n) >= 0) {
  983.         if ((text.size -= n) > 0) {
  984.             p = text.ptr;
  985.             do
  986.                 *loc++ = *p++;
  987.             while (--n);
  988.             text.ptr = p;
  989.             return;
  990.         } else
  991.             text.size += n;
  992.     }
  993.     text.nibuf += n;
  994.     do {
  995.         *loc++ = get(&text);
  996.     } 
  997.     while (--n);
  998. }
  999.  
  1000. mput(buf, aloc, an)
  1001. struct buf *buf; 
  1002. int *aloc;
  1003. {
  1004.     register *loc;
  1005.     register n;
  1006.  
  1007.     loc = aloc;
  1008.     n = an>>1;
  1009.     do {
  1010.         putw(*loc++, buf);
  1011.     } 
  1012.     while (--n);
  1013. }
  1014.  
  1015. dseek(asp, aloc, s)
  1016. long aloc;
  1017. struct stream *asp;
  1018. {
  1019.     register struct stream *sp;
  1020.     register struct page *p;
  1021.     /* register */ long b, o;
  1022.     int n;
  1023.  
  1024.     b = aloc >> 8;
  1025.     o = aloc & 0377;
  1026.     sp = asp;
  1027.     --sp->pno->nuser;
  1028.     if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b)
  1029.         if (p->nuser==0 || (p = &page[0])->nuser==0) {
  1030.             if (page[0].nuser==0 && page[1].nuser==0)
  1031.                 if (page[0].bno < page[1].bno)
  1032.                     p = &page[0];
  1033.             p->bno = b;
  1034.             lseek(infil, (aloc & ~0377L) << 1, 0);
  1035.             if ((n = read(infil, (char *)p->buff, 512)>>1) < 0)
  1036.                 n = 0;
  1037.             p->nibuf = n;
  1038.     } else
  1039.         error(2, "No pages");
  1040.     ++p->nuser;
  1041.     sp->bno = b;
  1042.     sp->pno = p;
  1043.     sp->ptr = p->buff + o;
  1044.     if (s != -1)
  1045.         sp->size = half(s);
  1046.     if ((sp->nibuf = p->nibuf-o) <= 0)
  1047.         sp->size = 0;
  1048. }
  1049.  
  1050. half(i)
  1051. {
  1052.     return((i>>1)&077777);
  1053. }
  1054.  
  1055. get(asp)
  1056. struct stream *asp;
  1057. {
  1058.     register struct stream *sp;
  1059.  
  1060.     sp = asp;
  1061.     if (--sp->nibuf < 0) {
  1062.         dseek(sp, (long)(sp->bno + 1) << 8, -1);
  1063.         --sp->nibuf;
  1064.     }
  1065.     if (--sp->size <= 0) {
  1066.         if (sp->size < 0)
  1067.             error(2, premeof);
  1068.         ++fpage.nuser;
  1069.         --sp->pno->nuser;
  1070.         sp->pno = (struct page *)&fpage;
  1071.     }
  1072.     return(*sp->ptr++);
  1073. }
  1074.  
  1075. getfile(acp)
  1076. char *acp;
  1077. {
  1078.     register char *cp;
  1079.     register int c;
  1080.     struct stat x;
  1081.  
  1082.     cp = acp; 
  1083.     infil = -1;
  1084.     archdr.aname[0] = '\0';
  1085.     filname = cp;
  1086.     if (cp[0]=='-' && cp[1]=='l') {
  1087.         if(cp[2] == '\0')
  1088.             cp = "-la";
  1089.         filname = "/usr/lib/libxxxxxxxxxxxxxxx";
  1090.         for(c=0; cp[c+2]; c++)
  1091.             filname[c+12] = cp[c+2];
  1092.         filname[c+12] = '.';
  1093.         filname[c+13] = 'a';
  1094.         filname[c+14] = '\0';
  1095.         if ((infil = open(filname+4, 0)) >= 0) {
  1096.             filname += 4;
  1097.         }
  1098.     }
  1099.     if (infil == -1 && (infil = open(filname, 0)) < 0)
  1100.         error(2, "cannot open");
  1101.     page[0].bno = page[1].bno = -1;
  1102.     page[0].nuser = page[1].nuser = 0;
  1103.     text.pno = reloc.pno = (struct page *)&fpage;
  1104.     fpage.nuser = 2;
  1105.     dseek(&text, 0L, 2);
  1106.     if (text.size <= 0)
  1107.         error(2, premeof);
  1108.     if(get(&text) != ARCMAGIC)
  1109.         return(0);    /* regualr file */
  1110.     dseek(&text, 1L, sizeof archdr);    /* word addressing */
  1111.     if(text.size <= 0)
  1112.         return(1);    /* regular archive */
  1113.     mget((int *)&archdr, sizeof archdr);
  1114.     if(strncmp(archdr.aname, goodnm, 14) != 0)
  1115.         return(1);    /* regular archive */
  1116.     else {
  1117.         fstat(infil, &x);
  1118.         if(x.st_mtime > archdr.atime)
  1119.         {
  1120.             return(3);
  1121.         }
  1122.         else return(2);
  1123.     }
  1124. }
  1125.  
  1126. struct symbol **lookup()
  1127. {
  1128.     int i; 
  1129.     int clash;
  1130.     register struct symbol **hp;
  1131.     register char *cp, *cp1;
  1132.  
  1133.     i = 0;
  1134.     for (cp = cursym.sname; cp < &cursym.sname[8];)
  1135.         i = (i<<1) + *cp++;
  1136.     for (hp = &hshtab[(i&077777)%NSYM+2]; *hp!=0;) {
  1137.         cp1 = (*hp)->sname; 
  1138.         clash=FALSE;
  1139.         for (cp = cursym.sname; cp < &cursym.sname[8];)
  1140.             if (*cp++ != *cp1++) {
  1141.                 clash=TRUE; 
  1142.                 break;
  1143.             }
  1144.         if (clash) {
  1145.             if (++hp >= &hshtab[NSYM+2])
  1146.                 hp = hshtab;
  1147.         } else
  1148.             break;
  1149.     }
  1150.     return(hp);
  1151. }
  1152.  
  1153. struct symbol **slookup(s)
  1154. char *s;
  1155. {
  1156.     cp8c(s, cursym.sname);
  1157.     cursym.stype = EXTERN+UNDEF;
  1158.     cursym.svalue = 0;
  1159.     return(lookup());
  1160. }
  1161.  
  1162. enter(hp)
  1163. struct symbol **hp;
  1164. {
  1165.     register struct symbol *sp;
  1166.  
  1167.     if (*hp==0) {
  1168.         if (symindex>=NSYM)
  1169.             error(2, "Symbol table overflow");
  1170.         symhash[symindex] = hp;
  1171.         *hp = lastsym = sp = &symtab[symindex++];
  1172.         cp8c(cursym.sname, sp->sname);
  1173.         sp->stype = cursym.stype;
  1174.         sp->svalue = cursym.svalue;
  1175.         return(1);
  1176.     } else {
  1177.         lastsym = *hp;
  1178.         return(0);
  1179.     }
  1180. }
  1181.  
  1182. symreloc()
  1183. {
  1184.     switch (cursym.stype) {
  1185.  
  1186.     case TEXT:
  1187.     case EXTERN+TEXT:
  1188.         cursym.svalue += ctrel;
  1189.         return;
  1190.  
  1191.     case DATA:
  1192.     case EXTERN+DATA:
  1193.         cursym.svalue += cdrel;
  1194.         return;
  1195.  
  1196.     case BSS:
  1197.     case EXTERN+BSS:
  1198.         cursym.svalue += cbrel;
  1199.         return;
  1200.  
  1201.     case EXTERN+UNDEF:
  1202.         return;
  1203.     }
  1204.     if (cursym.stype&EXTERN)
  1205.         cursym.stype = EXTERN+ABS;
  1206. }
  1207.  
  1208. error(n, s)
  1209. char *s;
  1210. {
  1211.     if (errlev==0)
  1212.         printf("ld:");
  1213.     if (filname) {
  1214.         printf("%s", filname);
  1215.         if (archdr.aname[0])
  1216.             printf("(%.14s)", archdr.aname);
  1217.         printf(": ");
  1218.     }
  1219.     printf("%s\n", s);
  1220.     if (n > 1)
  1221.         delexit();
  1222.     errlev = n;
  1223. }
  1224.  
  1225. struct symbol *
  1226. lookloc(alp, r)
  1227. struct local *alp;
  1228. {
  1229.     register struct local *clp, *lp;
  1230.     register sn;
  1231.  
  1232.     lp = alp;
  1233.     sn = (r>>4) & 07777;
  1234.     for (clp = local; clp<lp; clp++)
  1235.         if (clp->locindex == sn)
  1236.             return(clp->locsymbol);
  1237.     error(2, "Local symbol botch");
  1238. }
  1239.  
  1240. readhdr(loc)
  1241. long loc;
  1242. {
  1243.     register st, sd;
  1244.  
  1245.     dseek(&text, loc, sizeof filhdr);
  1246.     mget((int *)&filhdr, sizeof filhdr);
  1247.     if (filhdr.fmagic != FMAGIC)
  1248.         error(2, "Bad format");
  1249.     st = (filhdr.tsize+01) & ~01;
  1250.     filhdr.tsize = st;
  1251.     cdrel = -st;
  1252.     sd = (filhdr.dsize+01) & ~01;
  1253.     cbrel = - (st+sd);
  1254.     filhdr.bsize = (filhdr.bsize+01) & ~01;
  1255. }
  1256.  
  1257. cp8c(from, to)
  1258. char *from, *to;
  1259. {
  1260.     register char *f, *t, *te;
  1261.  
  1262.     f = from;
  1263.     t = to;
  1264.     te = t+8;
  1265.     while ((*t++ = *f++) && t<te);
  1266.     while (t<te)
  1267.         *t++ = 0;
  1268. }
  1269.  
  1270. eq(s1, s2)
  1271. char *s1; 
  1272. char *s2;
  1273. {
  1274.     while (*s1==*s2++)
  1275.         if ((*s1++)==0)
  1276.             return(TRUE);
  1277.     return(FALSE);
  1278. }
  1279.  
  1280. putw(w, b)
  1281. register struct buf *b;
  1282. {
  1283.     *(b->xnext)++ = w;
  1284.     if (--b->nleft <= 0)
  1285.         flush(b);
  1286. }
  1287.  
  1288. flush(b)
  1289. register struct buf *b;
  1290. {
  1291.     register n;
  1292.  
  1293.     if ((n = (char *)b->xnext - (char *)b->iobuf) > 0)
  1294.         if (write(b->fildes, (char *)b->iobuf, n) != n)
  1295.             error(2, "output error");
  1296.     b->xnext = b->iobuf;
  1297.     b->nleft = sizeof(b->iobuf)/sizeof(int);
  1298. }
  1299.