home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / mbug / mbug103.arc / LIB.C < prev    next >
Text File  |  1979-12-31  |  14KB  |  533 lines

  1. /* 
  2. ** LIB.C -- Small-Mac Library Manager
  3. **
  4. **                  Copyright 1985 J. E. Hendrix
  5. **
  6. ** Usage: LIB -{DPTUX}[A] library [module...]
  7. **
  8. ** -D     delete named modules
  9. ** -P[A]  print named, or all (-PA), modules on stdout
  10. ** -T[A]  table of contents of named, or all (-TA), files on stdout
  11. ** -U     update (adding/replace) named modules
  12. **        (gets module names from stdin if not in command line)
  13. ** -X[A]  extract named, or all (-XA), modules
  14. **
  15. **        The A suffix obviates prompting stdin for module
  16. **        names when none are in the command line.  This is handy for
  17. **        eliminating operator intervention, especially in batch mode.
  18. **        Ordinarily, when no modules are given in the command line,
  19. **        LIB prompts the user (if stdin is not redirected) and
  20. **        accepts one module name at a time from stdin.  If none
  21. **        are given (CR response to first prompt) and the command
  22. **        switch is -P, -T, or -X then all members of the library are
  23. **        processed.
  24. **
  25. ** Drive Designators (e.g. B:):
  26. **     allowed with any library and module names
  27. **     new library and index go on same drive as old
  28. **     will default to the default drive
  29. **
  30. ** Filename Extensions:
  31. **     do NOT specify with library or module names
  32. **     standard extensions are:
  33. **
  34. **     .REL = relocatable object module
  35. **     .LIB = library of object modules
  36. **     .NDX = index to library
  37. **     .L$  = temporary new library
  38. **     .N$  = temporary new index
  39. **
  40. ** Enter control-S to pause and control-C to abort.
  41. */
  42. #include <stdio.h>
  43. #include "notice.h"
  44. #include "rel.h"
  45.  
  46. #define NOCCARGC        /* no argument count passing */
  47. #define NAMESIZE   15
  48. #define MAXMODS   200
  49. #define MODEXT  ".REL"
  50. #define LIBEXT  ".LIB"
  51. #define NDXEXT  ".NDX"
  52. #define L_EXT   ".L$"
  53. #define N_EXT   ".N$"
  54. #define HIGH      127        /* high-value byte */
  55.  
  56. char
  57.   cmd[5],            /* command switch */
  58.   oldlib[NAMESIZE],        /* old library name */
  59.   oldndx[NAMESIZE],        /* old index name */
  60.   newlib[NAMESIZE],        /* new library name (temporary) */
  61.   newndx[NAMESIZE],        /* new index name (temporary) */
  62.  *modname;            /* points to module name buffer */
  63.  
  64. int
  65.  *mptr,                /* module name pointers */
  66.  *mdone,            /* done with module? */
  67.   modules,            /* count of modules to process */
  68.   all,                /* process all members? */
  69.   inndx,            /* input index fd */
  70.   outndx,            /* output index fd */
  71.   oldblock,            /* block of next input member */
  72.   oldbyte,            /* byte in block of next input member */
  73.   newblock,            /* block of next output member */
  74.   newbyte;            /* byte in block of next output member */
  75.  
  76. int  item2, type2, field2, inrel2, inrem2, inch2;
  77. char sym2[NAMESIZE];
  78.  
  79. main(argc,argv) int argc, argv[]; {
  80.   fputs("Small-Mac Library Manager, ", stderr); fputs(VERSION, stderr);
  81.   fputs(CRIGHT1, stderr);
  82.   mptr  = calloc(MAXMODS, 2);    /* allocate zeroed memory */
  83.   mdone = calloc(MAXMODS, 2);
  84.   if(getarg(1, cmd, 5, argc, argv) == EOF) usage();
  85.   cmd[1] = toupper(cmd[1]);
  86.   cmd[2] = toupper(cmd[2]);
  87.   if(cmd[0] != '-' || (cmd[2] && cmd[2] != 'A') || strlen(cmd) > 3) usage();
  88.   if(getarg(2,  oldlib, NAMESIZE, argc, argv) == EOF) usage();
  89.   extend(oldlib, LIBEXT, LIBEXT);
  90.   newfn(oldndx, oldlib, NDXEXT);
  91.   newfn(newlib, oldlib, L_EXT);
  92.   newfn(newndx, oldlib, N_EXT);
  93.   getmods(argc, argv);        /* gather switches and module names */
  94.   switch(cmd[1]) {
  95.     case 'D': drop();    break;
  96.     case 'T': table();   break;
  97.     case 'U': update();  break;
  98.     case 'X': extract(); break;
  99.     case 'P': print();   break;
  100.      default: usage();
  101.     }
  102.   }
  103.  
  104. /*
  105. ** add module to library
  106. */
  107. addmod(name) char *name; {
  108.   char *cp, nam[NAMESIZE];
  109.   saverel();            /* save REL variables */
  110.   strcpy(nam, name); extend(nam, MODEXT, MODEXT);
  111.   inrel = open(nam, "r");
  112.   cpymod(NO);            /* do not already have header */
  113.   close(inrel);
  114.   restrel();            /* restore REL variables */
  115.   strcpy(nam, name);
  116.   if(nam[1] == ':') cp = nam + 2; else cp = nam;
  117.   cp[MAXSYM] = NULL;
  118.   }
  119.  
  120. /*
  121. ** close input library and index
  122. */
  123. closein(mod1, mod2) char *mod1, *mod2 ; {
  124.   close(inrel);
  125.   close(inndx);
  126.   }
  127.  
  128. /*
  129. ** close output library and index
  130. */
  131. closeup(mod1, mod2) char *mod1, *mod2 ; {
  132.   closein();
  133.   endrel();
  134.   close(outrel);
  135.   putndx(newblock, newbyte);            /* index EFILE */
  136.   putndx(EOF, EOF);                /* terminate new index */
  137.   close(outndx);
  138.   movfil(newlib, oldlib);            /* take original names */
  139.   movfil(newndx, oldndx);
  140.   }
  141.  
  142. /*
  143. ** compare module names ignoring drive designators
  144. */
  145. cmpmod(mod1, mod2) char *mod1, *mod2; {
  146.   char str1[NAMESIZE], str2[NAMESIZE];
  147.   if(mod1[1] == ':') mod1 += 2; strncpy(str1, mod1, MAXSYM);
  148.   if(mod2[1] == ':') mod2 += 2; strncpy(str2, mod2, MAXSYM);
  149.   return (strcmp(str1, str2));
  150.   }
  151.  
  152. /*
  153. ** copy one module from inrel to outrel
  154. */
  155. cpymod(hdr) int hdr; {
  156.   if(outndx) putndx(newblock, newbyte);    /* must not be extracting */
  157.   if(hdr && !putrel()) abort(7);    /* already have input header */
  158.   do {
  159.     poll(YES);
  160.     if(getrel() == ERR || !putrel()) abort (7);
  161.     } while(item != EPROG);
  162.   fflush(outrel);        /* must empty aux buf for ctell() */
  163.   newblock = ctell(outrel);    /* remember for next member */
  164.   newbyte = ctellc(outrel);
  165.   if(newbyte == 128) {++newblock; newbyte = 0;}
  166.   }
  167.  
  168. /*
  169. ** drop modules from library
  170. */
  171. drop() {
  172.   char mod[NAMESIZE];
  173.   if(modules == 0) error("- Delete by Name Only");
  174.   openup();
  175.   while(nxtmod(mod)) {
  176.     if(match(mod, NO)) {
  177.       puts2("Deleted ", mod);
  178.       continue;
  179.       }
  180.     cpymod(YES);
  181.     }
  182.   missing();
  183.   closeup();
  184.   }
  185.  
  186. /*
  187. ** terminate REL or LIB file
  188. */
  189. endrel() {
  190.   item = EFILE;
  191.   field = 0;
  192.   type = 0;
  193.   if(!putrel()) abort(7);
  194.   }
  195.  
  196. /*
  197. ** extract files from library
  198. */
  199. extract() {
  200.   char modnam[NAMESIZE];
  201.   openin();
  202.   while(nxtmod(modnam)) {
  203.     if(match(modnam, YES)) {
  204.       extend(modnam, MODEXT, MODEXT);
  205.       outrel = open(modnam, "w");
  206.       cpymod(YES);
  207.       endrel();
  208.       close(outrel);
  209.       puts2("Created ", modnam);
  210.       }
  211.     }
  212.   missing();
  213.   closein();
  214.   }
  215.  
  216. /*
  217. ** get module names
  218. */
  219. getmods(argc, argv) int argc, argv[]; {
  220.   char *cp, *mp, name[NAMESIZE], fn[NAMESIZE];
  221.   int err, eof, arg, i, j;
  222.   if(!(mp = modname = malloc(MAXMODS*10))) error("- Memory Overflow");
  223.   if((j = avail(NO)) >= 0 && j < 512) {
  224.     puts("- Limited Stack Space");
  225.     err = YES;
  226.     }
  227.   all = YES;            /* default to all modules */
  228.   if(argc > 3) arg = 3;        /* get module names from command line */
  229.   else {
  230.     arg = 0;            /* get module names from stdin */
  231.     if(cmd[2] && (cmd[1] == 'P' || cmd[1] == 'T' || cmd[1] == 'X')) {
  232.       modname[0] = HIGH;        /* high value */
  233.       modname[1] = NULL;
  234.       return;
  235.       }
  236.     }
  237.   err = eof = NO;
  238.   while(modules < MAXMODS-1) {
  239.     poll(YES);
  240.     if(arg) {
  241.       if(getarg(arg++, name, NAMESIZE, argc, argv)==EOF) {eof = YES; break;}
  242.       }
  243.     else {
  244.       if(!reqstr("Module Name: ", name, NAMESIZE)) {eof = YES; break;}
  245.       }
  246.     all = NO;                /* do selected modules only */
  247.     if(cp = strchr(name, '.')) {
  248.       fputs(name, stdout); puts2(" - Extension Forced to ", MODEXT);
  249.       *cp = NULL;
  250.       err = YES;
  251.       }
  252.     if(cp = strchr(name, ':')) {
  253.       if(cp == name+1) ++cp;        /* set up next check */
  254.       else {
  255.         puts2(name, " - Invalid Format - Ignored");
  256.         goto ignore;
  257.         }
  258.       }
  259.     else cp = name;            /* set up next check */
  260.     if(strlen(cp) > MAXSYM) {
  261.       strcpy(fn, cp);
  262.       fputs(fn, stdout);
  263.       fn[MAXSYM] = NULL;
  264.       puts2(" - Will be Truncated to ", fn);
  265.       err = YES;    /* assembler does actual truncation */
  266.       }
  267.     if(cmd[1] == 'U') {            /* REL file must exist */
  268.       strcpy(fn, name); extend(fn, MODEXT, MODEXT);
  269.       if(i = fopen(fn, "r")) fclose(i);
  270.       else {
  271.         puts2(name, " - Can't Find - Ignored");
  272.         goto ignore;
  273.         }
  274.       }
  275.     for(i = 0; i < modules; ++i) {    /* find place for module */
  276.       if(cmpmod(mptr[i], name) > 0) {    /* shift others up */
  277.         for(j = modules; j > i; --j) mptr[j] = mptr[j-1];
  278.         break;
  279.         }
  280.       if(cmpmod(name, mptr[i]) == 0) {    /* already loaded */
  281.         puts2(mp, " - Duplicate Name - Ignored");
  282.         goto ignore;
  283.         }
  284.       }
  285.     mptr[i] = mp;            /* load modname pointer */
  286.     strcpy(mp, name);            /* load modname buffer */
  287.     while(*mp++) ;            /* scoot to next address */
  288.     ++modules;                /* bump number of modules */
  289.     continue;
  290.  
  291.     ignore:
  292.     err = YES;
  293.     }
  294.   mptr[modules] = mp;            /* load terminal pointer */
  295.   *mp++ = HIGH;                /* high value */
  296.   *mp   = NULL;
  297.   if(!eof) error("- Too Many Modules Specified");
  298.   if(err) {
  299.     fputs("\nContinue? ", stderr);
  300.     fgets(name, NAMESIZE, stderr);
  301.     if(toupper(*name) != 'Y') exit(7);
  302.     }
  303.   }
  304.  
  305. /*
  306. ** read an entry from the old index
  307. */
  308. getndx() {
  309.   if(read(inndx, &oldblock, 2) != 2 ||    /* next block */
  310.      read(inndx, &oldbyte,  2) != 2)    /* next byte in block */
  311.     error("- Error Reading Index");
  312.   }
  313.  
  314. /*
  315. ** check if name matches module list
  316. */
  317. match(name, quit) char *name; int quit; {
  318.   int i, done;
  319.   char *mp;
  320.   if(all) return(YES);
  321.   done = YES;
  322.   for(i = 0; i < modules; ++i) {
  323.     if(cmpmod(mptr[i], name) == 0) {
  324.       mdone[i] = YES;
  325.       return(YES);
  326.       }
  327.     if(!mdone[i]) done = NO;
  328.     }
  329.   if(quit && done) exit(0);
  330.   return(NO);
  331.   }
  332.  
  333. /*
  334. ** print "not in library" messages
  335. */
  336. missing() {
  337.   int i;
  338.   for(i = 0; i < modules; ++i)
  339.     if(!mdone[i]) puts2(mptr[i], " Was Not in Library");
  340.   }
  341.  
  342. /*
  343. ** move file1 to file2
  344. */
  345. movfil(file1, file2) char *file1, *file2; {
  346.   unlink(file2);
  347.   if(file2[1] == ':') file2 += 2;
  348.   if(rename(file1, file2)) error("- Can't Rename Files");
  349.   }
  350.  
  351. /*
  352. ** create new filename from old filename and specified extension
  353. */
  354. newfn(dest, sour, ext) char *dest, *sour, *ext; {
  355.   while(*sour && *sour != '.') *dest++ = *sour++;
  356.   strcpy(dest, ext);
  357.   }
  358.  
  359. /*
  360. ** get next module name
  361. */
  362. nxtmod(name) char *name; {
  363.   seek();                /* go straight to next member */
  364.   if(getrel() == PNAME) {
  365.     strcpy(name, symbol);
  366.     return (YES);
  367.     }
  368.   if(item == EFILE) {
  369.     *name++ = HIGH;            /* high value */
  370.     *name   = NULL;
  371.     return (NO);
  372.     }
  373.   error("- Corrupt Library or Index");
  374.   }
  375.  
  376. /*
  377. ** open library and index for input
  378. */
  379. openin() {
  380.   while(!(inrel = fopen(oldlib, "r"))) {
  381.     puts("\nCreating New Library");
  382.     outrel = open(oldlib, "w");
  383.     item = EFILE;
  384.     putrel();
  385.     close(outrel);
  386.     outndx = open(oldndx, "w");
  387.     putndx(0, 0);
  388.     putndx(EOF, EOF); 
  389.     close(outndx);
  390.     }
  391.   inndx = open(oldndx, "r");
  392.   }
  393.  
  394. /*
  395. ** open libraries and indices for updating
  396. */
  397. openup() {
  398.   openin();
  399.   outrel = open(newlib, "w");
  400.   outndx = open(newndx, "w");
  401.   auxbuf(outrel, 4096);
  402.   }
  403.  
  404. /*
  405. ** print files from library
  406. */
  407. print() {
  408.   char modnam[NAMESIZE];
  409.   openin();
  410.   while(nxtmod(modnam)) {
  411.     if(match(modnam, YES)) {
  412.       while(YES) {
  413.         poll(YES);
  414.         if(item > ENAME) seerel();
  415.         getrel();
  416.         if(item == EPROG) break;
  417.         }
  418.       }
  419.     }
  420.   missing();
  421.   closein();
  422.   }
  423.  
  424. /*
  425. ** write an entry to the new index
  426. */
  427. putndx(block, byte) int block, byte; {
  428.   if(write(outndx, &block, 2) != 2 ||    /* next block to index */
  429.      write(outndx, &byte, 2) != 2)    /* next byte in block to index */
  430.     error("- Error Writing New Index");
  431.   }
  432.  
  433. /*
  434. ** restore REL variables
  435. */
  436. restrel() {
  437.   item    = item2;
  438.   type    = type2;
  439.   field   = field2;
  440.   strcpy(symbol, sym2);
  441.   inrel   = inrel2;
  442.   inchunk = inch2;
  443.   inrem   = inrem2;
  444.   }
  445.  
  446. /*
  447. ** save REL variables
  448. */
  449. saverel() {
  450.   item2  = item;
  451.   type2  = type;
  452.   field2 = field;
  453.   strcpy(sym2, symbol);
  454.   inrel2 = inrel;
  455.   inch2  = inchunk;
  456.   inrem2 = inrem;
  457.   inrem  = 0;        /* force getrel() to read a byte */
  458.   }
  459.  
  460. /*
  461. ** seek to next member in old library
  462. */
  463. extern int Uchrpos[];        /* lives in CSYSLIB */
  464. seek() {
  465.   getndx();
  466.   if(oldblock == EOF) error("- Premature End of Index");
  467.   if(cseek(inrel, oldblock, 0) == EOF)
  468.     error("- Corrupt Library or Index");
  469.   Uchrpos[inrel] = oldbyte;
  470.   inrem = 0;            /* force getrel() to read a byte */
  471.   }
  472.  
  473. /*
  474. ** print table of contents
  475. */
  476. table() {
  477.   char name[NAMESIZE]; int i, j;
  478.   openin();
  479.   puts("");
  480.   i = 0;
  481.   while(nxtmod(name)) {
  482.     poll(YES);
  483.     if(match(name, YES)) {
  484.       fputs(name, stdout);
  485.       j = 9 - strlen(name);
  486.       while(j--) putchar(' ');
  487.       if (!(++i % 8)) puts("");
  488.       }
  489.     }
  490.   puts("");
  491.   missing();
  492.   closein();
  493.   }
  494.  
  495. /*
  496. ** update (add and replace) modules in alphanumeric order
  497. */
  498. update() {
  499.   char mod[NAMESIZE]; int m;
  500.   openup();
  501.   m = 0;                /* first in module list */
  502.   nxtmod(mod);                /* first in old library */
  503.   while(YES) {
  504.     if(cmpmod(mptr[m], mod) > 0) {    /* module > member */
  505.       cpymod(YES);            /* copy rest of member */
  506.       nxtmod(mod);            /* next in old library */
  507.       continue;
  508.       }
  509.     if(cmpmod(mptr[m], mod) < 0) {    /* module < member */
  510.       addmod(mptr[m]);            /* add new module */
  511.       puts2("   Added ", mptr[m]);
  512.       ++m;                /* next in module list */
  513.       continue;
  514.       }
  515.     if(*mod != HIGH) {            /* equal and not at end */
  516.       addmod(mptr[m]);            /* add new module */
  517.       ++m;                /* next in module list */
  518.       puts2("Replaced ", mod);
  519.       nxtmod(mod);            /* next in old library */
  520.       continue;
  521.       }
  522.     break;
  523.     }
  524.   closeup();
  525.   }
  526.  
  527. /*
  528. ** abort with a usage message
  529. */
  530. usage() {
  531.   error("Usage: LIB -{DPTUX}[A] library [module...]");
  532.   }
  533.