home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / 68kdisassem / part2 / libmtch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  7.1 KB  |  311 lines

  1. /*
  2.  *    SCCS:    @(#)libmtch.c    1.2    11/2/84    14:18:55
  3.  *    Read library files.
  4.  *
  5.  ***********************************************************************
  6.  *    This software is copyright of
  7.  *
  8.  *        John M Collins
  9.  *        47 Cedarwood Drive
  10.  *        St Albans
  11.  *        Herts, AL4 0DN
  12.  *        England            +44 727 57267
  13.  *
  14.  *    and is released into the public domain on the following conditions:
  15.  *
  16.  *        1.  No free maintenance will be guaranteed.
  17.  *        2.  Nothing may be based on this software without
  18.  *            acknowledgement, including incorporation of this
  19.  *            notice.
  20.  *
  21.  *    Notwithstanding the above, the author welcomes correspondence and bug
  22.  *    fixes.
  23.  ***********************************************************************
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <fcntl.h>
  28. #include <a.out.h>
  29. #include <ar.h>
  30. #include <setjmp.h>
  31. #include "unc.h"
  32.  
  33. long    lseek();
  34. void    bfopen(), bfclose(), nomem();
  35. void    rrell2(), markmatch();
  36. char    *strchr(), *strrchr(), *strncpy(), *strcat(), *strcpy(), *malloc();
  37. int    matchup();
  38. long    findstart();
  39.  
  40. char    verbose;        /*  Tell the world what we are doing  */
  41. char    *tfnam;
  42. char    *cfile;
  43. ef_fids    mainfile;
  44. struct    commit    dreltab;
  45. int    donedrel, donebrel;
  46. long    trelpos, drelpos, brelpos;
  47. static    struct    libit    currlib = {-1, 0, -1, ""};
  48.  
  49. void    lclash(str)
  50. char    *str;
  51. {
  52.     (void) fprintf(stderr, "Library scan failure - %s\n", str);
  53.     (void) fprintf(stderr, "Searching %s\n", cfile);
  54.     if  (currlib.lf_name[0])
  55.         (void) fprintf(stderr, "Member is %s\n", currlib.lf_name);
  56.     exit(255);
  57. }
  58.  
  59. /*
  60.  *    Find next member.
  61.  */
  62.  
  63. long    nextmemb(lfd)
  64. register  struct  libit     *lfd;
  65. {
  66.     struct    ar_hdr    arbuf;
  67.     
  68.     if  (lfd->lf_next < 0)
  69.         return    -1;
  70.     
  71.     (void) lseek(lfd->lf_fd, lfd->lf_next, 0);
  72.     if  (read(lfd->lf_fd, (char *)&arbuf, sizeof(arbuf)) != sizeof(arbuf))  {
  73.         lfd->lf_next = -1;
  74.         return    -1;
  75.     }
  76.     (void) strncpy(lfd->lf_name, arbuf.ar_name, sizeof(lfd->lf_name));
  77.     lfd->lf_offset = lfd->lf_next + sizeof(arbuf);
  78.     lfd->lf_next = (lfd->lf_offset + arbuf.ar_size + 1) & ~1;
  79.     return    lfd->lf_offset;
  80. }
  81.  
  82. /*
  83.  *    Decode a file name thus -
  84.  *
  85.  *    -lxxx decode as /lib/libxxx.a /usr/lib/libxxx.a etc
  86.  *    -Lxxx forget "lib" ".a" bit thus -Lcrt0.o
  87.  *    or read LDPATH environment var to give list of directories as sh
  88.  *    (default /lib:/usr/lib).
  89.  *
  90.  *    Alternatively treat as normal pathname.
  91.  *
  92.  *    File names may be followed by (membername) if the file is an archive,
  93.  *    thus
  94.  *
  95.  *        -lc(printf.o)
  96.  *
  97.  *    in which case the specified module is fetched.
  98.  */
  99.  
  100. struct    libit    *getfnam(str)
  101. char    *str;
  102. {
  103.     char    *bp, *ep = NULL, *pathb, *pathe, *fullpath = NULL;
  104.     static    char    *pathn;
  105.     extern    char    *getenv();
  106.     long    magic;
  107.     struct    ar_hdr    arhdr;
  108.     int    fd;
  109.  
  110.     if  ((bp = strrchr(str, '(')) != NULL &&
  111.          (ep = strrchr(str, ')')) != NULL)
  112.         *ep = *bp = '\0';
  113.  
  114.     if  (str[0] == '-'  &&  (str[1] == 'l' || str[1] == 'L'))  {
  115.         if  (pathn == NULL)  {
  116.             if  ((pathn = getenv("LDPATH")) == NULL)
  117.                 pathn = "/lib:/usr/lib";
  118.         }
  119.         fullpath = malloc((unsigned)(strlen(pathn) + strlen(str) + 1));
  120.         if  (fullpath == NULL)
  121.             nomem();
  122.         pathb = pathn;
  123.         do  {
  124.             pathe = strchr(pathb, ':');
  125.             if  (*pathb == ':')
  126.                 fullpath[0] = '\0';
  127.             else  {
  128.                 if  (pathe != NULL)
  129.                     *pathe = '\0';
  130.                 (void) strcpy(fullpath, pathb);
  131.                 (void) strcat(fullpath, "/");
  132.                 if  (pathe != NULL)
  133.                     *pathe = ':';
  134.             }
  135.             if  (str[1] == 'l')
  136.                 (void) strcat(fullpath, "lib");
  137.             (void) strcat(fullpath, &str[2]);
  138.             if  (str[1] == 'l')
  139.                 (void) strcat(fullpath, ".a");
  140.             if  ((fd = open(fullpath, O_RDONLY)) >= 0)
  141.                 goto  found;
  142.             pathb = pathe + 1;
  143.         }   while  (pathe != NULL);
  144.         
  145.         (void) fprintf(stderr, "Unable to locate lib%s.a in %s\n",
  146.             &str[2], pathn);
  147.         exit(101);
  148.     }
  149.     else  if  ((fd = open(str, O_RDONLY)) < 0)  {
  150.         (void) fprintf(stderr, "Cannot open %s\n", str);
  151.         exit(102);
  152.     }
  153.     
  154. found:
  155.  
  156.     if  ((read(fd, (char *) &magic, sizeof(magic)) != sizeof(magic)  ||
  157.         magic != ARMAG))  {
  158.         if  (ep != NULL)  {
  159.             (void) fprintf(stderr, "%s is not library file\n",
  160.                     fullpath != NULL? fullpath: str);
  161.             exit(103);
  162.         }
  163.         if  (fullpath != NULL)
  164.             free(fullpath);
  165.         currlib.lf_fd = fd;
  166.         currlib.lf_offset = 0;
  167.         currlib.lf_next = -1;
  168.         currlib.lf_name[0] = '\0';
  169.         return  &currlib;
  170.     }
  171.     
  172.     /*
  173.      *    It appears to be a library file - see if we want a specific
  174.      *    one.
  175.      */
  176.     
  177.     if  (ep != NULL)  {
  178.         currlib.lf_offset = sizeof(magic) + sizeof(struct ar_hdr);
  179.         for  (;;)  {
  180.             if  (read(fd, &arhdr, sizeof(arhdr)) != sizeof(arhdr))  {
  181.                 (void) fprintf(stderr, "Cannot find member %s in %s\n",
  182.                     bp+1, fullpath?fullpath: str);
  183.                 exit(103);
  184.             }
  185.             if  (strncmp(bp+1, arhdr.ar_name, sizeof(arhdr.ar_name)) == 0)
  186.                 break;
  187.             currlib.lf_offset += arhdr.ar_size + sizeof(arhdr) + 1;
  188.             currlib.lf_offset &= ~ 1;
  189.             (void) lseek(fd, (long)(currlib.lf_offset - sizeof(arhdr)), 0);
  190.         }
  191.         if  (fullpath != NULL)
  192.             free(fullpath);
  193.         currlib.lf_fd = fd;
  194.         currlib.lf_next = -1;
  195.         currlib.lf_name[0] = '\0';
  196.         *bp = '(';
  197.         *ep = ')';
  198.         return    &currlib;
  199.     }
  200.     
  201.     /*
  202.      *    Otherwise point to 1st member in library.
  203.      */
  204.     
  205.     if  (read(fd, &arhdr, sizeof(arhdr)) != sizeof(arhdr))  {
  206.         (void) fprintf(stderr, "Library %s empty\n", fullpath? fullpath: str);
  207.         exit(104);
  208.     }
  209.     if  (fullpath != NULL)
  210.         free(fullpath);
  211.     currlib.lf_offset = sizeof(magic) + sizeof(arhdr);
  212.     currlib.lf_next = currlib.lf_offset + arhdr.ar_size + 1;
  213.     currlib.lf_next &= ~1;
  214.     currlib.lf_fd = fd;
  215.     (void) strncpy(currlib.lf_name, arhdr.ar_name, sizeof(currlib.lf_name));
  216.     return    &currlib;
  217. }
  218.  
  219. /*
  220.  *    Process library files.
  221.  */
  222.  
  223. #define    MINTEXT    6
  224.  
  225. void    lscan(nfiles, fnames)
  226. int    nfiles;
  227. char    **fnames;
  228. {
  229.     ef_fids    libfile;
  230.     register  ef_fid  ll = &libfile;
  231.     register  struct  libit     *clf;
  232.     extern    symbol    dolsymb();
  233.     int    firstfile;
  234.     
  235.     for  (;  nfiles > 0;  fnames++, nfiles--)  {
  236.         clf = getfnam(*fnames);
  237.         cfile = *fnames;
  238.         firstfile = 1;
  239.         do  {
  240.             bfopen(tfnam, ll);
  241.  
  242.             /*
  243.              *    If file is garbled, silently forget it and go
  244.              *    on to the next one.
  245.              */
  246.  
  247.             if  (!rtext(clf->lf_fd, clf->lf_offset, ll))
  248.                 goto  closeit;
  249.                 
  250.             if  (ll->ef_tsize < MINTEXT)
  251.                 goto  closeit;
  252.                 
  253.             if  (!rdata(clf->lf_fd, clf->lf_offset, ll))
  254.                 goto  closeit;
  255.                 
  256.             if  (rrell1(clf->lf_fd, clf->lf_offset, ll) < 0)
  257.                 goto  closeit;
  258.                 
  259.             /*
  260.              *    If first file in library, find it from
  261.              *    beginning of main file.
  262.              */
  263.             
  264.             if  (firstfile)  {
  265.                 if  ((trelpos = findstart(&mainfile, ll)) < 0)
  266.                     goto  closeit;
  267.                 firstfile = 0;
  268.             }
  269.             else   if  (!matchup(&mainfile, ll, trelpos))
  270.                     goto  closeit;
  271.             
  272.             /*
  273.              *    Found a match.
  274.              */
  275.             
  276.             if  (!rsymb(clf->lf_fd, clf->lf_offset, dolsymb, ll))  {
  277.                 (void) fprintf(stderr, "Corrupt file %s\n",
  278.                             *fnames);
  279.                 exit(150);
  280.             }
  281.             
  282.             donedrel = 0;
  283.             donebrel = 0;
  284.             rrell2(clf->lf_fd, clf->lf_offset, ll);
  285.             if  (verbose)  {
  286.                 (void) fprintf(stderr, "Found: ");
  287.                 if  (clf->lf_name[0])
  288.                     (void) fprintf(stderr, "%.14s in ",
  289.                             clf->lf_name);
  290.                 (void) fprintf(stderr, "%s\n", *fnames);
  291.             }
  292.             if  (libfile.ef_stvec != NULL)  {
  293.                 free(libfile.ef_stvec);
  294.                 libfile.ef_stvec = NULL;
  295.                 libfile.ef_stcnt = 0;
  296.             }
  297.             dreltab.c_int = 0;
  298.                 
  299.             /*
  300.              *    Start looking next time round
  301.              *    where last one left off.
  302.              */
  303.             
  304.             markmatch(&mainfile, ll, trelpos);
  305.             trelpos += libfile.ef_tsize;
  306. closeit:
  307.             bfclose(ll);
  308.         }  while  (nextmemb(clf) >= 0);
  309.     }
  310. }
  311.