home *** CD-ROM | disk | FTP | other *** search
/ Vectronix 2 / VECTRONIX2.iso / FILES_01 / LATTIC_3.LZH / EXAMPLES / GSTLIB.C < prev    next >
C/C++ Source or Header  |  1990-05-02  |  30KB  |  1,242 lines

  1. /* lc -w -v -csfm -Lav -O -M gstlib.c */
  2.  
  3. /* librarian for GST .bin files     (c) k.b.v. controls 02 jun 1989
  4.  * read existing archive into memory, and build list of modules
  5.  * process arguments, and modify the archive list
  6.  * output a ranlib consisting of comment items
  7.  * output the modules on the list to tmp file.  if ok unlink old and rename
  8.  * we should be able to sort archive list into single pass order as default.
  9.  * if we use a|b modifiers, the sorting is not done.
  10.  * we will do everything in memory,  requiring approx 100k for typical archive.
  11.  *
  12.  * we must have a module name entry in the .bin file else we have problems
  13.  * Prospero libraries have wierd module name entries.
  14.  * if we convert to a more reasonable name in our MODULE structure 
  15.  * then we can continue as per Unix.  
  16.  * ie convert to "WIERD blah blah" to "wierd.bin"
  17.  * but "normal.ext" remains as "normal.ext" 
  18.  *
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <osbind.h>
  23. #ifdef LATTICE
  24. #include <fcntl.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #define lmalloc(n) malloc(n)
  28. #endif
  29.  
  30. /* #define DEBUG */
  31. #define JAN011980    ((1 << 5) | 1)
  32. #define UPDATE  1
  33. #define LOAD    2
  34. #ifdef DEBUG
  35. #define D(x) x
  36. #else
  37. #define D(x)
  38. #endif
  39.  
  40. /*
  41.  * Modes, a la GEM-DOS:
  42.  */
  43. #define S_IJRON    0x01            /* Read-only */
  44. #define S_IJHID    0x02            /* Hidden from search */
  45. #define S_IJSYS    0x04            /* System, hidden from search */
  46. #define S_IJVOL    0x08            /* Volume label in first 11 bytes */
  47. #define S_IJDIR    0x10            /* Directory */
  48. #define S_IJWAC    0x20            /* Written to and closed */
  49.  
  50. typedef struct {
  51.     char    d_glob[12];    /* GEMDOS wildcard string from Fsfirst */
  52.     char    d_mask;        /* Attribute mask from Fsfirst */
  53.     char    d_dirent[4];    /* Offset into directory, MSB first */
  54.     char    d_dirid[4];    /* Pointer to directory structure in GEM mem */
  55.     char    d_fattr;    /* File attributes */
  56.     long    d_tandd;    /* Time and date words */
  57.     long    d_fsize;    /* File size */
  58.     char     d_fname[14];    /* File name */
  59. } DMABUFFER;
  60.  
  61. typedef struct    tm {
  62.     int    tm_sec;        /* Seconds (0-59) */
  63.     int    tm_min;        /* Minutes (0-59) */
  64.     int    tm_hour;    /* Hours (0-23); 0 = midnight */
  65.     int    tm_mday;    /* Day of month (1..28,29,30,31) */
  66.     int    tm_mon;        /* Month (0-11); 0 = January */
  67.     int    tm_year;    /* Year AD since 1900 */
  68.     int    tm_wday;    /* Day of week (0-6): 0 = Sunday */
  69.     int    tm_yday;    /* Day of year (0-365,366) */
  70.     int    tm_isdst;    /* Daylight savings time flag: */
  71.                 /* Non-standard, they make negative==NA */
  72. } tm_t;
  73.  
  74. typedef unsigned long tand_t;    /* we use disk format for time */
  75.  
  76. #ifndef NARGS
  77. tand_t tm_to_tand(tm_t *);
  78. tm_t *tand_to_tm(tand_t);
  79. void mytime(tand_t *);
  80. char *myctime(tand_t *);
  81. #else
  82. tand_t tm_to_tand();
  83. tm_t *tand_to_tm();
  84. void mytime();
  85. char *myctime();
  86. #endif
  87.  
  88. typedef union any_ptr {
  89.     char *name;
  90.     struct mod_info *module;
  91.     struct cref_info *cref;
  92. } PTR;
  93.  
  94. typedef struct list {
  95.     struct list *next;
  96.     PTR p;
  97. } LIST;
  98.  
  99. typedef struct mod_info {
  100.     char *name;
  101.     tand_t date;
  102.     long size;
  103.     unsigned char *buf;
  104.     LIST *xdef;
  105.     LIST *xref;
  106. } MODULE;
  107.  
  108. typedef struct cref_info {
  109.     char *name;
  110.     LIST *xdef;
  111.     LIST *xref;
  112. } CREF;
  113.  
  114. #define MALLOC(x)    (x *)malloc(sizeof(x))
  115. #define AFTER     1
  116. #define BEFORE    2
  117. #define TRUE    1
  118. #define VOIDP   char *        /* really want a void * */
  119. LIST *libhead = NULL;
  120. LIST *xrefhead = NULL;
  121. LIST *beforemod = NULL;
  122. LIST *ranlib = NULL;
  123. char *aftmodname;
  124.  
  125. extern int errno;
  126.  
  127. int verbose, aftbef, sortflag, keepflag, quitflag;
  128.  
  129. #ifndef LATTICE
  130. char *calloc(), *malloc(), *realloc(), *strrchr(), *strchr();
  131. #endif
  132.  
  133. #define addlist(x, y) inslist(x, y, NULL)
  134. #ifndef NARGS
  135. void inslist(LIST **, VOIDP, LIST *); /* want to check for ptr argument */
  136. void dellist(LIST **, LIST *);
  137. void mkxrefs(LIST *, LIST **);
  138. void prtxrefs(LIST *);
  139. void prtlist(LIST *, char *);
  140. int sortxrefs(LIST **, LIST *);
  141. int weneed(LIST *, MODULE *);
  142. int weload(LIST **, LIST **, MODULE *);
  143. int mkcode(int, char *, char *, int);
  144. void fatal(char *, char *);
  145. void faterr(char *, char *);
  146. MODULE *gstread(unsigned char *, unsigned char *);
  147. MODULE *mkranlib(LIST *, char *);
  148. tand_t rdranlib(MODULE *, char *);
  149. LIST *msearch(LIST *, char *);
  150. LIST *nsearch(LIST *, char *);
  151. CREF *addxsym(LIST **, char *);
  152. char *newstring(char *, int);
  153. char *cleannm(char *);
  154. char *strlower(char *);
  155. char *unwierd(char *, int);
  156. #else
  157. void fatal();
  158. void faterr();
  159. void inslist();
  160. void dellist();
  161. void mkxrefs();
  162. void prtxrefs();
  163. void prtlist();
  164. int sortxrefs();
  165. int weneed();
  166. int weload();
  167. int mkcode();
  168. MODULE *gstread();
  169. MODULE *mkranlib();
  170. tand_t rdranlib();
  171. LIST *msearch();
  172. LIST *nsearch();
  173. CREF *addxsym();
  174. char *newstring();
  175. char *strlower();
  176. char *cleannm();
  177. char *unwierd();
  178. #endif
  179.  
  180. void usage()
  181. {
  182.     fprintf(stderr, 
  183.         "Librarian for GST .bin object files (c) kbv controls 1989\n");
  184.     fprintf(stderr, 
  185.         "Usage: gstlib {dlmrtux}[vsk][a|b obmod] library [files..]\n");
  186.     fprintf(stderr, "\toptions\td delete modules\n");
  187.     fprintf(stderr, "\t\tm move modules\n");
  188.     fprintf(stderr, "\t\tr replace modules\n");
  189.     fprintf(stderr, "\t\tu update modules\n");
  190.     fprintf(stderr, "\t\tl load modules\n");
  191.     fprintf(stderr, "\t\tt table [modules..]\n");
  192.     fprintf(stderr, "\t\tx extract [modules..]\n");
  193.     fprintf(stderr, "\t\modifiers\tv verbose\n");
  194.     fprintf(stderr, "\t\t\ta|b obmod with m|r replace after|before obmod\n");
  195.     fprintf(stderr, "\t\t\ts sort library for single pass\n");
  196.     fprintf(stderr, "\t\t\tk keep module datestamp when extracting\n");
  197.     fprintf(stderr, "\tall modified libraries will have a ranlib\n");
  198.     exit(1);
  199. }
  200.  
  201. int main(argc, argv)
  202. int argc;
  203. char *argv[];
  204. {
  205.     char **myargv;
  206.     char inpbuf[160], *p, *q, *r;
  207.     int myargc = 0;
  208.     int i, j;
  209.     FILE *fp;
  210.     myargv = NULL;
  211.     for (i = 1; i < argc; i++) {
  212.         strlower(argv[i]);
  213.     if (argv[i][0] == '@') {
  214.         if ((myargv = (char **)calloc(sizeof(char *), 200)) == NULL)
  215.             fatal("exparg", "duff calloc");  
  216.         break;
  217.     }
  218.     }
  219.     if (myargv) {
  220.         for (i = 0; i < argc; i++) {
  221.         if (argv[i][0] == '@') {
  222.             if ((fp = fopen(argv[i] + 1, "r")) == NULL) 
  223.             fatal("exparg", argv[i]);
  224.          while (fgets(inpbuf, 160, fp) != NULL) {
  225.             p = inpbuf;
  226.             while (*p) {
  227.                 while (*p == ' ' || *p == '\t' || *p == '\n') p++;
  228.                 if (*p == '\0' || *p == '#') break;
  229.             if (*p == '\\' && *(p+1) == '\n') break;
  230.             q = p;
  231.             for (j = 0; *p && *p != ' ' && *p != '\t' && *p != '\n'; j++,p++) ;
  232.             if (j) {
  233.                 if ((r = malloc(j+1)) == NULL)
  234.                     fatal("exparg", "duff malloc");
  235.                 strncpy(r, q, j);
  236.                 r[j] = '\0';
  237.                 myargv[myargc++] = r;
  238.             }
  239.             }
  240.         }
  241.         fclose(fp);
  242.         }    
  243.         else myargv[myargc++] = argv[i];
  244.         if (myargc > 199) fatal("exparg", "too many args"); 
  245.     }
  246.         myargv[myargc] = NULL;
  247.     return (mymain(myargc, myargv));
  248.     }
  249.     return (mymain(argc, argv));
  250. }
  251.  
  252. int mymain(argc, argv)
  253. int argc;
  254. char **argv;
  255. {
  256.     char *libname, *cmd, *p;
  257.     int ret = 2;
  258.     int fd, keepran, exist = 1;
  259.     setbuf(stdout, NULL);
  260.  
  261.     if (argc < 3) 
  262.         usage();
  263.     p = cmd = *++argv;
  264.     switch (*cmd) {
  265.         case 'r':
  266.         case 'u': exist = 0;
  267.         case 'd':
  268.         case 'm':
  269.         case 'l': keepran = 0; break;
  270.         case 't':
  271.         case 'x': keepran = 1; break;
  272.         default:
  273.             fatal("Usage",
  274.              "gstlib {dmrutx}[vsk][a|b modname] archive files..");
  275.             break;
  276.     }
  277.     while (*++p) {
  278.         switch (*p) {
  279.         case 'a': aftbef |= AFTER; break;
  280.         case 'b': aftbef |= BEFORE; break;
  281.         case 'v': verbose++; break;
  282.         case 's': sortflag = TRUE; break;
  283.         case 'k': keepflag = TRUE; break;
  284.         case 'q': quitflag = TRUE; break;
  285.         default: usage(); break;
  286.         }
  287.     }
  288.     if (aftbef) aftmodname = *++argv;
  289.     libname = *++argv;
  290.     if ((fd = open(libname, O_RAW)) > 0) close(fd);
  291.     else {
  292.         if (exist) fatal(libname, "library does not exist");
  293.         else if (verbose) 
  294.             fprintf(stderr, "creating new library %s\n", libname);
  295.     }
  296.     if (fd > 0) readlib(&libhead, libname, keepran);
  297.     if (aftbef) {
  298.         if (*cmd != 'r' || *cmd != 'm' || *cmd != 'u') 
  299.             fatal("a or b modifiers only with r or m option", cmd);
  300.         if ((beforemod = msearch(libhead, aftmodname)) == NULL)
  301.             fatal(aftmodname, "not in library");
  302.         if (aftbef & AFTER) {
  303.             beforemod = beforemod->next;
  304.         }
  305.     }
  306.     else beforemod = NULL;
  307.     switch (*cmd) {
  308.         case 'd': ret = delete(libname, ++argv); break;
  309.         case 'l': ret = replace(libname, ++argv, LOAD); break;
  310.         case 'm': ret = move(libname, ++argv); break;
  311.         case 'r': ret = replace(libname, ++argv, 0); break;
  312.         case 't': ret = table(libname, ++argv); break;
  313.         case 'u': ret = replace(libname, ++argv, UPDATE); break;
  314.         case 'x': ret = extract(libname, ++argv); break;
  315.     }
  316.     myexit(ret);
  317. }
  318.  
  319. myexit(ret)
  320. int ret;
  321. {
  322.     if (ferror(stdout)) {
  323.         fprintf(stderr, "stream error on <stdout>\n");
  324.         ret |= 1;
  325.     }
  326.     if (quitflag) {
  327.         fprintf(stderr, "press return to continue\n");
  328.         getchar();
  329.     }
  330.     exit(ret);
  331. }
  332.  
  333. /* print the table.
  334.  * if (verbose == 0) just the modnames
  335.  * if (verbose >  0) we do size and datestamp
  336.  * if (verbose >  1) we do xdefs (and xrefs)
  337.  * if (verbose >  3) we do a cross-reference of symbols too.
  338.  */
  339. int table(libname, namelist)
  340. char *libname, **namelist;
  341. {
  342.     register LIST *l;
  343.     register MODULE *m;
  344.     LIST *xlisthead = NULL;
  345.     LIST *tablehead = NULL;
  346.     register char *name;
  347.     int all = 1;
  348.     name = NULL;
  349.     if (*namelist) all = 0;
  350.     while (all || (name = *namelist++)) {
  351.         for (l = libhead; l != NULL; l = l->next) {
  352.             m = l->p.module;
  353.             if ((name != NULL) && (strcmp(name, m->name) != 0)) 
  354.                 continue;
  355.             addlist(&tablehead, (VOIDP)m);
  356.             if (verbose) {
  357.                 printf("%-16.16s size:%5ld date:%s", 
  358.                     m->name, m->size, myctime(&m->date));
  359.             }
  360.             else printf("%s\n", m->name);
  361.             if (verbose > 1)
  362.                 prtlist(m->xdef, " xdef:");
  363.             if (verbose > 2)
  364.                 prtlist(m->xref, "  xref:");
  365.             if (all = 0) break;
  366.         }
  367.         all = 0;
  368.     } 
  369.     if (verbose > 3) {
  370.         mkxrefs(tablehead, &xlisthead);
  371.         prtxrefs(xlisthead);
  372.     }
  373.     return 0;
  374. }
  375.  
  376. /* replace the modules found in the file, (it may have multiple mods)
  377.  * if update mode is set, we only replace out of date modules
  378.  */
  379. replace(libname, namelist, mode)
  380. char *libname, **namelist;
  381. int mode;
  382. {
  383.     char *name; 
  384.     register LIST *l, *xl;
  385.     LIST *onemod, *resolved = NULL, *unres = NULL;
  386.     register MODULE *m;
  387.     tand_t old, new;
  388.     int count = 0, ret = 0;
  389.     if (mode & LOAD)
  390.         for (l = libhead; l; l = l->next) 
  391.             if (weload(&resolved, &unres, l->p.module)) ret |= 1;
  392.     while (name = *namelist++) {
  393.         onemod = NULL;
  394.         readlib(&onemod, name, 0);
  395.         for (l = onemod; l; l = l->next) {
  396.             m = l->p.module;
  397.             new = m->date;
  398.             new = (new >> 16) | (new << 16);
  399.             if (mode & LOAD) {
  400.                 if (weneed(unres, m) == 0) continue;
  401.                 if (weload(&resolved, &unres, m)) ret |= 1;
  402.             }
  403.             if (xl = msearch(libhead, m->name)) {
  404.                 old = xl->p.module->date;
  405.                 old = (old >> 16) | (old << 16);
  406.                 if (!(mode & UPDATE) || old < new) {
  407.                     xl->p.module = l->p.module;
  408.                     if (verbose) 
  409.                         printf("r %s\n", m->name);
  410.                     count++;
  411.                 }
  412.             }
  413.             else {
  414.                 inslist(&libhead, (VOIDP)l->p.module, beforemod);
  415.                 if (verbose) printf("a %s\n", m->name);
  416.                 count++;
  417.             }
  418.         }
  419.     }
  420.     if (verbose > 1 && (mode & LOAD))
  421.         prtlist(unres, "unresolved:");
  422.     if (ret) return ret;
  423.     if ((mode & UPDATE) && (count == 0)) return 0;
  424.     return (copyback(libhead, libname));
  425. }
  426.  
  427. move(libname, namelist)
  428. char *libname, **namelist;
  429. {
  430.     char *name; 
  431.     LIST *l;
  432.     MODULE *m;
  433.     while (name = *namelist++) {
  434.         if ((l = msearch(libhead, name)) == NULL) {
  435.             printf("move: %s is not in library", name);
  436.         }
  437.         else {
  438.             m = l->p.module;
  439.             dellist(&libhead, l);        
  440.             inslist(&libhead, (VOIDP)m, beforemod);
  441.             if (verbose) printf("m %s\n", m->name);
  442.         }
  443.     }
  444.     return (copyback(libhead, libname));
  445. }
  446.  
  447. delete(libname, namelist)
  448. char *libname, **namelist;
  449. {
  450.     char *name; 
  451.     LIST *l;
  452.     int ret = 0;
  453.     if (*namelist == NULL) return -1;
  454.     while (name = *namelist++) {
  455.         if (l = msearch(libhead, name)) {
  456.             dellist(&libhead, l);
  457.             if (verbose) printf("d %s\n", name);
  458.         }
  459.         else {
  460.             printf("delete: %s not in archive\n", name);
  461.             ret |= 1;
  462.         }
  463.     }
  464.     if (ret) return(ret);
  465.     return (copyback(libhead, libname));
  466. }
  467.  
  468. extract(libname, namelist)
  469. char *libname, **namelist;
  470. {
  471.     char *name; 
  472.     char tmpname[80];
  473.     LIST *l, *xl, onemod;
  474.     MODULE *m;
  475.     int dummy = 0;
  476.     int ret = 0;
  477.     if (*namelist == NULL) xl = libhead;
  478.     else xl = NULL;
  479.     for (;;) {
  480.         if (xl == NULL) name = *namelist++;
  481.         else {
  482.             m = xl->p.module;
  483.             xl = xl->next;
  484.             name = m->name;
  485.         }
  486.         if (name == NULL) break;
  487.         if (l = msearch(libhead, name)) {
  488.             m = l->p.module;
  489.             strcpy(tmpname, m->name);
  490.             if (*tmpname == '\0') 
  491.                 sprintf(tmpname, "dummy%03d.bin", ++dummy);
  492.             if (verbose) printf("x %s\n", tmpname);
  493.             onemod.p.module = l->p.module;
  494.             onemod.next = NULL;
  495.             writemod(&onemod, tmpname, keepflag);
  496.         }
  497.         else {
  498.             printf("extract: %s not in %s\n", name, libname);
  499.             ret |= 1;
  500.         }
  501.     }
  502.     return ret;
  503. }
  504.  
  505. /* read a file into memory, and append details to listp
  506.  * if a single module with no ranlib we use the file datestamp else jan 1 1970
  507.  * if the first module is "ranlib" then we re-adjust date fields from there
  508.  * and eliminate "ranlib" from our enquiries.
  509.  */
  510. int readlib(listp, name, keepran)
  511. LIST **listp;
  512. char *name;
  513. int keepran;
  514. {
  515.     DMABUFFER filestat;
  516.     long count;
  517.     int chunk;
  518.     tand_t t;
  519.     unsigned char *mp, *p, *endp;
  520.     MODULE *m, *ranmod = NULL;
  521.     LIST *l;
  522.     int fd;
  523.     if (mystat(name, &filestat) < 0) faterr("cannot mystat", name);
  524.     if ((mp = lmalloc(filestat.d_fsize)) == NULL)
  525.         fatal("readlib", "lmalloc");
  526.     if ((fd = open(name, O_RAW)) < 0) faterr("cant open", name);
  527.     for (p = mp, count = filestat.d_fsize; count > 0L; p += chunk) {
  528.         chunk = (count > 4096L) ? 4096 : count;
  529.         if (read(fd, p, chunk) != chunk) faterr("read error", name);
  530.         count -= chunk;
  531.     }
  532.     close(fd);
  533.     for (count = 0L, p = mp, endp = mp + filestat.d_fsize; p < endp; ) {
  534.         if ((m = gstread(p, endp)) == NULL) fatal("duff module", name);
  535.         m->date = JAN011980;
  536.         addlist(listp, (VOIDP)m);
  537.         count += m->size;
  538.         p += m->size;
  539.     }
  540.     if (l = msearch(*listp, "ranlib.bin")) {
  541.         ranmod = l->p.module;
  542.         if (l != *listp) fatal("ranlib.bin", "is not at beginning");
  543.         if (keepran == 0) dellist(listp, l);
  544.         for (l = *listp; l; l = l->next) {
  545.             m = l->p.module;
  546.             t = rdranlib(ranmod, m->name);
  547.             m->date = t;
  548.             D(printf("module:%s %s", m->name, myctime(&m->date));)
  549.         }
  550.     } 
  551.     else if ((l = *listp) && (l->next == NULL)) 
  552.         l->p.module->date = filestat.d_tandd;
  553.     return 0;
  554. }
  555.  
  556. /* given a memory address, we read the memory to analyse the module.
  557.  * if ok, we return the details in a freshly malloced MODULE structure
  558.  * else we return NULL
  559.  */
  560. MODULE *gstread(mp, endp)
  561. unsigned char *mp;
  562. register unsigned char *endp;
  563. {
  564.     register unsigned char *p;
  565.     register MODULE *m;
  566.     register int len, byte;
  567.     register short section;
  568.     char *newname;
  569.     if ((m = MALLOC(MODULE)) == NULL) fatal("gstread", "malloc");
  570.     m->name = "";
  571.     m->buf = mp;
  572.     m->size = m->date = 0L;
  573.     m->xdef = m->xref = NULL;
  574.     p = mp;
  575.     if (*p != 0xfb || *(p+1) != 0x01) return NULL;
  576.     p += 2;
  577.     len = *p++;
  578.     newname = unwierd(p, len);
  579.     m->name = newstring(newname, strlen(newname));
  580.     p += len;
  581.     while (p < endp) {
  582.         if (*p++ != 0xfb) continue;
  583.         switch (byte = *p++) {
  584.         case 0xfb: break;
  585.         case 0x01: m->size = (long)(p - mp -2); return m;
  586.         case 0x02: len = *p++; p += len; break;
  587.         case 0x03: p += 4; break;
  588.         case 0x04: p += 2; break;
  589.         case 0x05: p += 4; break;
  590.         case 0x06:                /* XDEF */ 
  591.             len = *p++;
  592.             addlist(&m->xdef, (VOIDP)newstring(p, len));
  593.             p += len;
  594.             p += 4;                /* .kbv was missing */
  595.             section = (*p << 8) + *(p+1);
  596.             p += 2;
  597.             break;
  598.         case 0x07: 
  599.             p += 5;
  600.             while (*p++ != 0xfb) p += 2;
  601.             break;
  602.         case 0x10:                /* XREF */
  603.             section = (*p << 8) + *(p+1);
  604.             p += 2;
  605.             len = *p++;
  606.             if (section >= 0) addlist(&m->xref, (VOIDP)newstring(p, len));
  607.             p += len;
  608.             break;
  609.         case 0x12:
  610.             p += 2;
  611.             break;
  612.         case 0x13: m->size = (long)(p - mp); return m;
  613.         default:
  614.             printf("escape 0xfb%02x in %s\n", byte, m->name);  
  615.             fatal("gstread", "unknown object type");
  616.             break;
  617.         }
  618.     }
  619.     fatal("gstread", "unexpected EOF");
  620. }
  621.  
  622. /* insert an item before list entry and update head if empty
  623.  * if posn is NULL, then we are adding to the end of list
  624.  * if posn is not in the list, we've had it
  625.  */
  626. void inslist(head, str, posn)
  627. LIST **head;
  628. VOIDP str;
  629. register LIST *posn;
  630. {
  631.     register LIST *l, *new;
  632.     if ((new = MALLOC(LIST)) == NULL) fatal("inslist", "malloc");
  633.     new->next = posn;
  634.     new->p.name = str;
  635.     for (l = *head; l; l = l->next) {
  636.         if (l->next == posn) {
  637.             l->next = new;
  638.             return;
  639.         }
  640.     }
  641.     *head = new;
  642.     return;
  643. }
  644.  
  645. /* delete entry from list
  646.  */
  647. void dellist(head, lentry)
  648. LIST **head;
  649. LIST *lentry;
  650. {
  651.     register LIST *l;
  652.     if (lentry == *head) *head = lentry->next; 
  653.     else {
  654.         for (l = *head; l->next; l = l->next) {
  655.             if (l->next == lentry) {
  656.                 l->next = lentry->next;
  657.                 break;
  658.             }
  659.         }
  660.     }
  661.     free(lentry);
  662. }
  663.  
  664. int weneed(reflist, newmod)
  665. register LIST *reflist;
  666. register MODULE *newmod;
  667. {
  668.     register LIST *l;
  669.     if (reflist == NULL) return 0;
  670.     for (l = newmod->xdef; l; l = l->next)
  671.         if (nsearch(reflist, l->p.name)) return 1;
  672.     return 0;
  673. }
  674.  
  675. /* merge the new module's symbols into our lists
  676.  * if multiple xdefs then shout
  677.  */
  678. int weload(pdeflist, preflist, newmod)
  679. MODULE *newmod;
  680. LIST **pdeflist, **preflist;
  681. {
  682.     register LIST *l, *xl;
  683.     register char *name;
  684.     int ret = 0;
  685.     for (l = newmod->xdef; l; l = l->next) {
  686.         name = l->p.name;
  687.         if (xl = nsearch(*preflist, name))
  688.             dellist(preflist, xl);
  689.         if (nsearch(*pdeflist, name)) {
  690.             ret |= 1;
  691.             printf("%s is multiply defined in %s\n", 
  692.                 name, newmod->name);
  693.         }
  694.         else addlist(pdeflist, name);
  695.     }
  696.     for (l = newmod->xref; l; l = l->next) {
  697.         name = l->p.name;
  698.         if (nsearch(*pdeflist, name)) continue;
  699.         if (nsearch(*preflist, name) == NULL)
  700.             addlist(preflist, name);
  701.     }
  702.     return ret;
  703. }
  704.  
  705. /* build an xref list from the module list
  706.  */
  707. void mkxrefs(list, xlist)
  708. LIST *list;
  709. LIST **xlist;
  710. {
  711.     LIST *modlist;
  712.     register LIST *l;
  713.     register MODULE *m;
  714.     register CREF *xr;
  715.     char *symbol, *modname;
  716.     
  717.     for (modlist = list; modlist; modlist = modlist->next) {
  718.         m = modlist->p.module;
  719.         modname = m->name;
  720.         for (l = m->xdef; l; l = l->next) {
  721.             symbol = l->p.name;
  722.             xr = addxsym(xlist, symbol);
  723.             addlist(&xr->xdef, (VOIDP)modname);
  724.         }
  725.         for (l = m->xref; l; l = l->next) {
  726.             symbol = l->p.name;
  727.             xr = addxsym(xlist, symbol);
  728.             addlist(&xr->xref, (VOIDP)modname);
  729.         }
  730.     }
  731. }
  732.  
  733. /* display the xref list
  734.  */
  735. void prtxrefs(xlist)
  736. LIST *xlist;
  737. {
  738.     register LIST *l, *xl;
  739.     register CREF *xr;
  740.     for (l = xlist; l; l = l->next) {
  741.         xr = l->p.cref;
  742.         printf("symbol:%s", xr->name);
  743.         if (xl = xr->xdef) {
  744.             printf("\txdef:");
  745.             for ( ; xl; xl = xl->next) printf(" %s", xl->p.name);
  746.         }
  747.         printf("\n");
  748.         prtlist(xr->xref, "  xref:");
  749.     }
  750. }
  751.  
  752. void prtlist(list, title)
  753. register LIST *list;
  754. char *title;
  755. {
  756.     register LIST *l;
  757.     char buf[256];
  758.     l = list;
  759.     while (l) {
  760.         strcpy(buf, title);
  761.         for (; l; l = l->next) {
  762.             strcat(buf, " ");
  763.             strcat(buf, l->p.name);
  764.             if (strlen(buf) > 60) break;
  765.         }
  766.         printf("%s\n", buf);
  767.     }
  768. }
  769.  
  770. /* we go thru the whole list of xdef'd symbols.
  771.  * if it is possible to find any module that contains xref to symbol
  772.  * we move the xdef MODULE info in the main list to after the xref MODULE
  773.  * we give up if we make moves but list in unchanged.
  774.  * we give up if we have 50 attempts to sort list.
  775.  */
  776. int sortxrefs(list, xlist)
  777. LIST **list;
  778. LIST *xlist;
  779. {
  780.     register LIST *l, *xl;
  781.     LIST *xrefl, *refpsn, *defpsn, *copyhead;
  782.     MODULE *m;
  783.     register CREF *xr;
  784.     register int exchanges, changed, attempts;
  785.     char *modname;
  786.     
  787.     copyhead = NULL;
  788.     for (l = *list; l; l = l->next) 
  789.         addlist(©head, (VOIDP)l);
  790.     for (attempts = 0; attempts < 50; attempts++) {
  791.         exchanges = 0;
  792.         for (l = *list, xl = copyhead; l; l = l->next, xl = xl->next)
  793.         xl->p.module = l->p.module;
  794.         for (l = xlist; l; l = l->next) {
  795.         xr = l->p.cref;
  796.         for (xl = xr->xdef; xl; xl = xl->next) {
  797.             defpsn = msearch(*list, xl->p.name);
  798.             modname = xl->p.name;
  799.             for (xrefl = xr->xref; xrefl; xrefl = xrefl->next) {
  800.                 if (refpsn = msearch(defpsn, xrefl->p.name)) {
  801.                     D(printf("moving %s after %s\n", modname, xrefl->p.name);)
  802.                     m = defpsn->p.module;
  803.                     dellist(list, defpsn);
  804.                     inslist(list, (VOIDP)m, refpsn->next); 
  805.                     defpsn = refpsn->next;
  806.                     exchanges++;
  807.                 }
  808.             }
  809.         }  
  810.         }
  811.         if (verbose > 3)
  812.             printf("attempt :%d moves done :%d\n", attempts, exchanges);
  813.         if (exchanges == 0) return 0;
  814.         for (l = *list, xl = copyhead, changed = 0; l; l = l->next, xl = xl->next) {
  815.         if (xl->p.module != l->p.module) {
  816.             changed = 1;
  817.             break;
  818.         }
  819.         }
  820.         if (changed == 0) return 1;
  821.     }
  822.     return 1;
  823. }
  824.  
  825. tand_t rdranlib(ranmod, name)
  826. MODULE *ranmod;
  827. char *name;
  828. {
  829.     register MODULE *m;
  830.     register unsigned char *p;
  831.     tm_t t;
  832.     int byte, len;
  833.     char buf[128];
  834.     sprintf(buf,"module:%-16.16s", name);
  835.     m = ranmod;
  836.     p = m->buf;
  837.     if (*p != 0xfb || *(p+1) != 0x01) return JAN011980;
  838.     p += 2;
  839.     len = *p++;
  840.     if (strncmp(p, "ranlib.bin", len)) return JAN011980;
  841.     p += len;
  842.     for (;;) {
  843.         if (*p++ != 0xfb) return 0L;
  844.         switch (byte = *p++) {
  845.         case 0x01: return JAN011980;
  846.         case 0x02: 
  847.             len = *p++; 
  848.             if (strncmp(p, buf, strlen(buf)) == 0) {
  849.                 strncpy(buf, p, len);
  850.                 p = buf + 32;
  851.                 t.tm_mon  = atoi(p) - 1;    p += 3;
  852.                 t.tm_mday = atoi(p);        p += 3;
  853.                 t.tm_year = atoi(p) - 1900; p += 5;
  854.                 t.tm_hour = atoi(p);        p += 3;
  855.                 t.tm_min  = atoi(p);        p += 3;
  856.                 t.tm_sec  = atoi(p); 
  857.                 return (tm_to_tand(&t));
  858.             }
  859.             p += len; 
  860.             break;
  861.         case 0x13: return JAN011980;
  862.         default:
  863.             fatal("rdranlib", "unknown object type");
  864.             break;
  865.         }
  866.     }
  867. }
  868.  
  869. MODULE *mkranlib(list, name)
  870. LIST *list;
  871. char *name;
  872. {
  873.     register LIST *xl;
  874.     register unsigned char *p;
  875.     register MODULE *m;
  876.     register int pass;
  877.     MODULE *ranmod;
  878.     LIST *l, onemod;
  879.     tm_t *tp;
  880.     char buf[1000], *mp = NULL;
  881.     if ((ranmod = m = MALLOC(MODULE)) == NULL) fatal("mkranlib", "MALLOC");
  882.     m->name = name;
  883.     m->size = 0L;
  884.     m->buf  = NULL;
  885.     mytime(&m->date);
  886.     m->xref = m->xdef = NULL;
  887.     onemod.p.module = m;
  888.     onemod.next = list;
  889.     for (pass = 0; pass < 2; pass++) {
  890.         p = mp;
  891.         sprintf(buf, "%s", name);
  892.         D(printf("mkranlib: %s\n", buf);)
  893.         p += mkcode(0x01, p, buf, pass);
  894.         for (l = &onemod; l; l = l->next) {
  895.             m = l->p.module;
  896.             tp = tand_to_tm(m->date);
  897.             sprintf(buf,
  898.               "module:%-16.16s %8ld %02d %02d %04d %02d %02d %02d ",
  899.                 m->name, m->size,
  900.                 tp->tm_mon+1,
  901.                 tp->tm_mday,
  902.                 tp->tm_year+1900,
  903.                 tp->tm_hour,
  904.                 tp->tm_min,
  905.                 tp->tm_sec);
  906.             D(printf("%s\n", buf);)
  907.             p += mkcode(0x02, p, buf, pass);
  908.             if (xl = m->xdef) {
  909. more:
  910.                 strcpy(buf, "xdef:");
  911.                 for (; xl; xl = xl->next) {
  912.                     strcat(buf, " ");
  913.                     strcat(buf, xl->p.name);
  914.                     if (strlen(buf) > 60) break;
  915.                 }
  916.                 D(printf("%s\n", buf);)
  917.                 p += mkcode(0x02, p, buf, pass);
  918.                 if (xl) goto more;
  919.             }
  920.         }
  921.         p += mkcode(0x13, p, NULL, pass);
  922.         m = ranmod;
  923.         m->size = (long)(p - mp);
  924.         if (pass == 0)
  925.             if ((p = mp = m->buf = malloc((unsigned)m->size)) == NULL) 
  926.                 fatal("mkranlib", "malloc");
  927.     }
  928.     D(printf("ranlib size: %ld\n", m->size);)
  929.     return m;
  930. }
  931.  
  932. int mkcode(code, mp, buf, doflag)
  933. register char *mp, *buf;
  934. register int code, doflag;
  935. {
  936.     register char *p;
  937.     register int len;
  938.     p = mp;
  939.     if (doflag) {
  940.         *p++ = 0xfb;
  941.         *p++ = code;
  942.     }
  943.     else p += 2;
  944.     if (buf != NULL) {
  945.         len = strlen(buf);
  946.         if (doflag) {
  947.             *p++ = len;
  948.             strncpy(p, buf, len);
  949.         }
  950.         else p++;
  951.         p += len;
  952.     }
  953.     return (p - mp);
  954. }
  955.  
  956. /* lookup a module name in LIST of modules
  957.  */
  958. LIST *msearch(list, name)
  959. LIST *list;
  960. char *name;
  961. {
  962.     register LIST *l;
  963.     register MODULE *m;
  964.     for (l = list; l ; l = l->next) {
  965.         m = l->p.module;
  966.         if (m && (strcmp(m->name, name) == 0)) return l;
  967.     }
  968.     return NULL;
  969. }
  970.  
  971. /* lookup a name in LIST of names
  972.  */
  973. LIST *nsearch(list, name)
  974. LIST *list;
  975. register char *name;
  976. {
  977.     register LIST *l;
  978.     for (l = list; l ; l = l->next) {
  979.         if ((strcmp(l->p.name, name) == 0)) return l;
  980.     }
  981.     return NULL;
  982. }
  983.  
  984. /* insert symbol into sorted list of xref symbols 
  985.  * create a new node if reqd. return ptr to CREF
  986.  */
  987. CREF *addxsym(xlist, name)
  988. LIST **xlist;
  989. char *name;
  990. {
  991.     register LIST *l;
  992.     register CREF *xr;
  993.     register int cmp;
  994.     for (l = *xlist; l ; l = l->next) {
  995.         xr = l->p.cref;
  996.         cmp = strcmp(name, xr->name);
  997.         if (cmp == 0) return xr;
  998.         if (cmp <  0) break;
  999.     }
  1000.     if ((xr = MALLOC(CREF)) == NULL)
  1001.         fatal("addxsym", "MALLOC");
  1002.     xr->name = name;
  1003.     xr->xref = xr->xdef = NULL;
  1004.     inslist(xlist, (VOIDP)xr, l);
  1005.     return xr;
  1006. }
  1007.  
  1008. /* copy archive back to tmp file inserting "ranlib" module
  1009.  */
  1010. int copyback(liblist, libname)
  1011. LIST *liblist;
  1012. char *libname;
  1013. {
  1014.     int ret = 0;
  1015.     LIST *xlist, *list;
  1016.     char tempname[200], *p;
  1017.     strcpy(tempname, libname);
  1018.     if (p = strrchr(tempname, '\\')) p++;
  1019.     else p = tempname;
  1020.     strcpy(p, "libname.tmp");
  1021.     list = liblist;
  1022.     xlist = NULL;
  1023.     if (sortflag) {
  1024.         mkxrefs(list, &xlist);
  1025.         if (ret = sortxrefs(&list, xlist))
  1026.             fprintf(stderr, "unable to sort library %s\n", libname);
  1027.     }
  1028.     if (msearch(list, "ranlib.bin") == NULL)
  1029.         inslist(&list, (VOIDP)mkranlib(list, "ranlib.bin"), list);
  1030.     ret |= writemod(list, tempname, 0);
  1031.     if (ret == 0) {
  1032.         unlink(libname);
  1033.         if (rename(tempname, libname) != 0) faterr("rename", libname);
  1034.      }
  1035.     return ret;
  1036. }
  1037.  
  1038. /* write a list of modules to name
  1039.  */
  1040. int writemod(list, name, touch)
  1041. LIST *list;
  1042. char *name;
  1043. int touch;
  1044. {
  1045.     register LIST *l;
  1046.     register MODULE *m;
  1047.     register int fd, chunk, ret;
  1048.     register long count;
  1049.     register unsigned char *p;
  1050.     
  1051.     if ((fd = creat(name, O_RAW)) < 0) faterr("cant creat", name);
  1052.     for (l = list; l != NULL; l = l->next) {
  1053.         m = l->p.module;
  1054.         for (count = m->size, p = m->buf; count > 0L; ) {
  1055.             chunk = (count > 4096L) ? 4096 : count;
  1056.             if (write(fd, p, chunk) != chunk) 
  1057.                 faterr("write error", name);
  1058.             count -= chunk;
  1059.             p += chunk;
  1060.         }
  1061.     }
  1062.     ret = close(fd);
  1063.     if (touch) keepdate(name, m->date);
  1064.     return ret;
  1065. }
  1066.         
  1067. char *newstring(mp, len)
  1068. register char *mp;
  1069. int len;
  1070. {
  1071.     register char *dst, *str;
  1072.     if ((str = dst = malloc(len + 1)) == NULL) fatal("newstring", "malloc");
  1073.     while (len--) *dst++ = *mp++;
  1074.     *dst = '\0';
  1075.     D(printf("%s\n", str);)
  1076.     return str;
  1077. }
  1078.      
  1079. /* make a normal lowercase filename 
  1080.  * with a .bin extension if none already
  1081.  */
  1082. char *unwierd(name, len)
  1083. char *name;
  1084. int len;
  1085. {
  1086.     register char *p, *dst;
  1087.     static char wierdbuf[200];
  1088.     for (p = name, dst = wierdbuf, *dst = '\0'; len > 0; len--, p++) {
  1089.         if (*p == ' ') break;
  1090.         *dst++ = (*p >= 'A' && *p <= 'Z') ? *p + ('a' - 'A') : *p;
  1091.     }
  1092.     *dst++ = '\0';
  1093.     *dst++ = '\0';
  1094.     if (strchr(wierdbuf+1, '.') == NULL) strcat(wierdbuf, ".bin");
  1095.     return wierdbuf;
  1096. }
  1097.     
  1098. char *strlower(s)
  1099. char *s;
  1100. {
  1101.     register char *p;
  1102.     for (p = s; *p; p++)
  1103.         *p = (*p >= 'A' && *p <= 'Z') ? *p + ('a' - 'A') : *p;
  1104.     return s;
  1105. }
  1106.     
  1107. char *cleannm(name)
  1108. char *name;
  1109. {
  1110.     register char *p;
  1111.     if (p = strrchr(name, '\\')) return p+1;
  1112.     if (p = strrchr(name, ':')) return p+1;
  1113.     return name;
  1114. }
  1115.  
  1116. void faterr(s, t)
  1117. char *s, *t;
  1118. {
  1119.     fprintf(stderr, "gstlib: Fatal error: %s %s\n", s, t);
  1120.     perror("Tos error");
  1121.     myexit(1);
  1122. }
  1123.  
  1124. void fatal(s, t)
  1125. char *s, *t;
  1126. {
  1127.     fprintf(stderr, "gstlib: Fatal error: %s %s\n", s, t);
  1128.     myexit(1);
  1129. }
  1130.  
  1131. #ifndef LATTICE
  1132. rename(old, new)
  1133. char *new, *old;
  1134. {
  1135.     int ret;
  1136.     ret = Frename(0, old, new);
  1137.     if (ret < 0) errno = -ret;
  1138.     return ret;
  1139. }
  1140. #endif
  1141.  
  1142. keepdate(name, date)
  1143. char *name;
  1144. tand_t date;
  1145. {
  1146.     int fd;
  1147.     if ((fd = Fopen(name, 0)) > 0) {
  1148.         Fdatime(&date, fd, 1);
  1149.         Fclose(fd);
  1150.     }
  1151.     else {
  1152.         errno = -fd;
  1153.         perror(name);
  1154.     }
  1155.     return fd;
  1156. }
  1157.  
  1158. int mystat(fullname, statptr) 
  1159. char *fullname;
  1160. DMABUFFER *statptr;
  1161. {
  1162.     DMABUFFER *saved;
  1163.     char *name;
  1164.     int ret = 0;
  1165.  
  1166.     name = cleannm(fullname);
  1167.     saved = (DMABUFFER *)Fgetdta();
  1168.     Fsetdta(statptr);
  1169.     ret = Fsfirst(fullname, 0);
  1170.     if (ret < 0) {
  1171.         errno = -ret;
  1172.         ret = -1;
  1173.     }
  1174. /*    else if (strcmp(name, statptr->d_fname) != 0) ret = -1; */
  1175.     Fsetdta(saved);
  1176.     return ret;
  1177. }
  1178.  
  1179. tm_t *tand_to_tm(tandd)
  1180. register tand_t tandd;
  1181. {
  1182.     static tm_t tm;
  1183.     static int monbeg[2][12] = { 
  1184.         { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
  1185.         { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 306, 335 }
  1186.     };
  1187.     register unsigned time;
  1188.     register unsigned date;
  1189.     int leap;
  1190.     time = tandd >> 16;
  1191.     date = tandd & 0xffffL;
  1192.     tm.tm_sec = (time & 0x1f)<< 1;        /* Seconds (0-59) */
  1193.     tm.tm_min = (time >> 5) & 0x3f;    /* Minutes (0-59) */
  1194.     tm.tm_hour = (time >> 11) & 0x1f;    /* Hours (0-23); 0 = midnight */
  1195.     tm.tm_mday = ((date) & 0x1f);    /* Day of month (1..28,29,30,31) */
  1196.     tm.tm_mon = ((date >> 5) & 0x0f) - 1;    /* Month (0-11); 0 = January */
  1197.     tm.tm_year = ((date >> 9) & 0x3f)+80;    /* Year AD since 1900 */
  1198.     leap = ((tm.tm_year %4) == 0);
  1199.     tm.tm_yday = monbeg[leap][tm.tm_mon] + tm.tm_mday - 1;
  1200.     tm.tm_wday = (3 + tm.tm_year + (tm.tm_year << 2) + tm.tm_yday) % 7;
  1201.     return &tm;
  1202. }
  1203.  
  1204. tand_t tm_to_tand(tp)
  1205. register tm_t *tp;
  1206. {
  1207.     register tand_t tandd = 0L;
  1208.     tandd <<= 5; tandd |= (tp->tm_hour);        
  1209.     tandd <<= 6; tandd |= (tp->tm_min);
  1210.     tandd <<= 5; tandd |= (tp->tm_sec >> 1);
  1211.     tandd <<= 7; tandd |= (tp->tm_year - 80);
  1212.     tandd <<= 4; tandd |= (tp->tm_mon + 1);
  1213.     tandd <<= 5; tandd |= (tp->tm_mday);
  1214.     return tandd;
  1215. }
  1216.  
  1217. void mytime(tandp)
  1218. tand_t *tandp;
  1219. {
  1220.     *tandp = Tgettime();
  1221.     *tandp = (*tandp << 16) | (Tgetdate() & 0xffffL);
  1222. }
  1223.  
  1224. char *myctime(tandp)
  1225. tand_t *tandp;
  1226. {
  1227.     static char ctimbuf[30];
  1228.     static char *monnm[] = {
  1229.         "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
  1230.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  1231.     };
  1232.     static char *daynm[] = {
  1233.         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  1234.     };
  1235.     tm_t *tp;
  1236.     tp = tand_to_tm(*tandp); 
  1237.     sprintf(ctimbuf, "%s %s %2d %02d:%02d:%02d %04d GMT\n",
  1238.         daynm[tp->tm_wday], monnm[tp->tm_mon], tp->tm_mday, 
  1239.         tp->tm_hour, tp->tm_min, tp->tm_sec, tp->tm_year+1900);
  1240.     return ctimbuf;
  1241. }
  1242.