/* ** LIB.C -- Small-Mac Library Manager ** ** Copyriht 1985 J. E. Hendrix ** ** Usage: LIB -{DPTUX}[A] library [module...] ** ** -D delete named modules ** -P[A] print named, or all (-PA), modules on stdout ** -T[A] tabe of contents of named, or aaa (-TA), files on stdout ** -U update (adding/replace) named modules ** (gets module names from stdin if not in command line) ** -X[A] extract named, or all (-XA), modules ** ** The A suffix obviates prompting stdin for module ** names when none are in the command line. This is handy for ** eliminating operator intervention, especially in batch mode. ** Ordinarily, when no modules are given in the command line, ** LIB prompts the user (if stdin is not redirected) and ** accepts one module name at a time from stdin. If none ** are given (CR response to first prompt) and the command ** switch is -P, -T, or -X then all members of the library are ** processed. ** ** Drive Designators (e.g. B:): ** allowed with any library and module names ** new library and index go on same drive as old ** will default to the default drive ** ** Filename Extensions: ** do NOT specify with library or module names ** standard extensions are: ** ** .REL = relocatable object module ** .LIB = library of object modules ** .NDX = index to library ** .L$ = temporary new library ** .N$ = temporary new index ** ** Enter control-S to pause and control-C to abort. */ #include #include "notice.h" #include "rel.h" #define NOCCARGC /* no argument count passing */ #define NAMESIZE 15 #define MAXMODS 200 #define MODEXT ".REL" #define LIBEXT ".LIB" #define NDXEXT ".NDX" #define L_EXT ".L$" #define N_EXT ".N$" #define HIGH 127 /* high-value byte */ char cmd[5], /* command switch */ oldlib[NAMESIZE], /* old library name */ oldndx[NAMESIZE], /* old name index */ newlib[NAMESIZE], /* new library name (temporary) */ newndx[NAMESIZE], /* new index name (temporary) */ *modname; /* points to module name buffer */ int *mptr, /* module name pointers */ *mdone, /* done with mdule? */ modules, /* count of modulesto process */ all, /* process all members? */ inndx, /* input index fd */ outndx, /* output index fd */ oldblock, /* block of next input member */ oldbyte, /* byte in block of next input member */ newblock, /* block of next output member */ newbyte; /* byte in block of next output member */ int item2, type2, field2, inrel2, inrem2, inch2; char sym2[NAMESIZE]; main(argc,argv) int argc, argv[]; { fputs("Small-Mac Library Manager, ", stderr); fputs(VERSION, stderr); fputs(CRIGHT1, stderr); mptr = calloc(MAXMODS, 2); /* allocate zeroed memory */ mdone = calloc(MAXMODS, 2); if(getarg(1, cmd, 5, argc, argv) == EOF) usage (); cmd[1] = toupper(cmd[1]); cmd[2] = toupper(cmd[2]); if(cmd[0] != '-' || (cmd[2] && cmd[2] != 'A') || strlen(cmd) > 3) usage(); if(getarg(2, oldlib, NAMESIZE, argc, argv) == EOF) usage(); extend(oldlib, LIBEXT, LIBEXT); newfn(oldndx, oldlib, NDXEXT); newfn(newlib, oldlib, L_EXT); newfn(newndx, oldlib, N_EXT); getmods(argc, argv); /* gather switches and module names */ switch(cmd[1]) { case 'D': drop(); break; case 'T': table(); break; case 'U': update(); break; case 'X': extract();break; case 'P': print(); break; default: usage(); } } /* ** add module to library */ addmod(name) char *name; { char *cp, nam[NAMESIZE]; saverel(); /* saveREL variables */ strcpy(nam, name); extend(nam, MODEXT, MODEXT); inrel = open(nam, "r"); cpymod(NO); /* do not already have header */ close(inrel); restrel(); /* restore REL variables */ strcpy(nam, name); if(nam[1] == ':') cp = nam + 2; else cp = nam; cp[MAXSYM] = NULL; } /* ** close input library and index */ closein(mod1, mod2) char *mod1, *mod2 ; { close(inrel); close(inndx); } /* ** close output library and index */ closeup(mod1, mod2) char *mod1, *mod2 ; { closein(); endrel(); close(outrel); putndx(newblock, newbyte); /* index EFILE */ putndx(EOF, EOF); /* terminate new index */ close(outndx); movfil(newlib, oldlib); /* take original names */ movfil(newndx, oldndx); } /* ** compare module names ignoring drive designators */ cmpmod(mod1, mod2) char *mod1, *mod2; { char str1[NAMESIZE], str2[NAMESIZE]; if(mod1[1] == ':') mod1 += 2; strncpy(str1, mod1, MAXSYM); if(mod2[1] == ':') mod2 += 2; strncpy(str2, mod2, MAXSYM); return (strcmp(str1, str2)); } /* ** copy one module from inrel to outrel */ cpymod(hdr) int hdr;{ if(outndx) putndx(newblock, newbyte); /* must not be extracting */ if(hdr && !putrel()) abort(7); /* already have input header */ do { poll(YES); if(getrel() == ERR || !putrel()) abort (7); } while(item != EPROG); fflush(outrel); /* must empty aux buffer for ctell() */ newblock = ctell(outrel); /* remember for next member */ newbyte = ctellc(outrel); if(newbyte == 128) {++newblock; newbyte = 0;} } /* ** drop modules from library */ drop() { char mod[NAMESIZE]; if(modules == 0) error("- Delete by Name Only"); openup(); while(nxtmod(mod)) { if(match(mod, NO)) { puts2("Deleted ", mod); continue; } cpymod(YES); } missing(); closeup(); } /* ** terminate REL or LIB file */ endrel() { item = EFILE; field = 0; type = 0; if(!putrel()) abort(7); } /* ** extract files from library */ extract() { char modnam[NAMESIZE]; openin(); while(nxtmod(modnam)) { if(match(modnam, YES)) { extend(modnam, MODEXT, MODEXT); outrel = open(modnam, "w"); cpymod(YES); endrel(); close(outrel); puts2("Created ", modnam); } } missing(); closein(); } /* ** get module names */ getmods(argc, argv) int argc, argv[]; { char *cp, *mp, name[NAMESIZE], fn[NAMESIZE]; int err, eof, arg, i, j; if(!(mp = modname = malloc(MAXMODS*10))) error("- Memory Overflow"); if((j = avail(NO)) >= 0 && j < 512) { puts("- Limited Stack Space"); err = YES; } all = YES; /* default to all modules */ if(argc > 3) arg = 3; /* get module names from command line */ else { arg = 0; /* get module names from stdin */ if(cmd[2] && (cmd[1] == 'P' || cmd[1] == 'T' || cmd[1] == 'X')) { modname[0] = HIGH; /* high value */ modname[1] = NULL; return; } } err = eof = NO; while(modules < MAXMODS-1) { poll(YES); if(arg) { if(getarg(arg++, name, NAMESIZE, argc, argv)==EOF) {eof = YES; break;} } else { if(!reqstr("Module Name: ", name, NAMESIZE)) {eof = YES; break;} } all = NO; if(cp = strchr(name, '.')) { fputs(name, stdout); puts2(" - Extension Forced to ", MODEXT); *cp = NULL; err = YES; } if(cp = strchr(name, ':')) { if(cp == name+1) ++cp; /* set up next check */ else { puts2(name, " - Invalid Format - Ignored"); goto ignore; } } else cp = name; /* set up next check */ if(strlen(cp) > MAXSYM) { strcpy(fn, cp); fputs(fn, stdout); fn[MAXSYM] = NULL; puts2(" - Will be Truncated to ", fn); err = YES; /* assembler does actual truncation */ } if(cmd[1] == 'U') { /* REL file must exist */ strcpy(fn, name); extend(fn, MODEXT, MODEXT); if(i = fopen(fn, "r")) fclose(i); else { puts2(name, " - Can't Find - Ignored"); goto ignore; } } for(i = 0; i < modules; ++i) { /* find place for module */ if(cmpmod(mptr[i], name) > 0) { /* shift others up */ for(j = modules; j > i; --j) mptr[j] = mptr[j-1]; break; } if(cmpmod(name, mptr[i]) == 0) { /* already loaded */ puts2(mp, " - Duplicate Name - Ignored"); goto ignore; } } mptr[i] = mp; /* load modname pointer */ strcpy(mp, name); /* load modname buffer */ while(*mp++); /* scoot to next address */ ++modules; /* bump number of modules */ continue; ignore: err = YES; } mptr[modules] = mp; /* load terminal pointer */ *mp++ = HIGH; /* high value */ *mp = NULL; if(!eof) error("- Too Many Modules Specified"); if(err) { fputs("\nContinue? ", stderr); fgets(name, NAMESIZE, stderr); if(toupper(*name) != 'Y') exit(7); } } /* ** read an entry from the old index */ getndx() { if(read(inndx, &oldblock, 2) != 2 || /* next block */ read(inndx, &oldbyte, 2) != 2) /* next byte in block */ error("- Error Reading Index"); } /* ** check if name matches module list */ match(name, quit) char *name; int quit; { int i, done; char *mp; if(all) return(YES); done = YES; for(i = 0; i < modules; ++i) { if(cmpmod(mptr[i], name) == 0) { mdone[i] = YES; return(YES); } if(!mdone[i]) done = NO; } if(quit && done) exit(0); return(NO); } /* ** print "not in library" messages */ missing() { int i; for(i = 0; i < modules; ++i) if(!mdone[i]) puts2(mptr[i], " Was Not in Library"); } /* ** move file1 to file2 */ movfil(file1, file2) char *file1, *file2; { unlink(file2); if(file2[1] == ':') file2 += 2; if(rename(file1, file2)) error("- Can't Rename Files"); } /* ** create new filename from old filename and specified extension */ newfn(dest, sour, ext) char *dest, *sour, *ext; { while(*sour && *sour != '.') *dest++ = *sour++; strcpy(dest, ext); } /* ** get next module name */ nxtmod(name) char *name; { seek(); /* go straight to next member */ if(getrel() == PNAME) { strcpy(name, symbol); return (YES); } if(item == EFILE) { *name++ = HIGH; /* high value */ *name = NULL; return (NO); } error("- Corrupt Library of Index"); } /* ** open library and index for input */ openin() { while(!(inrel = fopen(oldlib, "r"))) { puts("\nCreating New Library"); outrel = open(oldlib, "w"); item = EFILE; putrel(); close(outrel); outndx = open(oldndx, "w"); putndx(0, 0); putndx(EOF, EOF); close(outndx); } inndx = open(oldndx, "r"); } /* ** open Libraries and indices for updating */ openup() { openin(); outrel = open(newlib, "w"); outndx = open(newndx, "w"); auxbuf(outrel, 4096); } /* ** print files from library */ print() { char modnam[NAMESIZE]; openin(); while(nxtmod(modnam)) { if(match(modnam, YES)) { while(YES) { poll(YES); if(item > ENAME) seerel(); getrel(); if(item == EPROG) break; } } } missing(); closein(); } /* ** write an entry to the new index */ putndx(block, byte) int block, byte; { if(write(outndx, &block, 2) != 2 || /* next block to index */ write(outndx, &byte, 2) != 2) /* next byte in block to index */ error("- Error Writing New Index"); } /* ** restore REL variables */ restrel() { item = item2; type = type2; field = field2; strcpy(symbol, sym2); inrel = inrel2; inchunk = inch2; inrem = inrem2; } /* ** save REL variables */ saverel() { item2 = item; type2 = type; field2 = field; strcpy(sym2, symbol); inrel2 = inrel; inch2 = inchunk; inrem2 = inrem; inrem = 0; /* force getrel() to read a byte */ } /* ** seek to next member in old library */ extern int Uchrpos[]; /* lives in CSYSLIB */ seek() { getndx(); if(oldblock == EOF) error("- Premature End of Index"); if(cseek(inrel, oldblock, 0) == EOF) error("- Corrupt Library or Index"); Uchrpos[inrel] = oldbyte; inrem = 0; /* force getrel() to read a byte */ } /* ** print table of contents */ table() { char name[NAMESIZE]; int i, j; openin(); puts(""); i = 0; while(nxtmod(name)) { poll(YES); if(match(name, YES)) { fputs(name, stdout); j = 9 - strlen(name); while(j--) putchar(' '); if (!(++i % 8)) puts(""); } } puts(""); missing(); closein(); } /* ** update (add and replace) modules in alphanumeric order */ update() { char mod[NAMESIZE]; int m; openup(); m = 0; /* first in module list */ nxtmod(mod); /* first in old library */ while(YES) { if(cmpmod(mptr[m], mod) > 0) { /* module > member */ cpymod(YES); /* copy rest of member */ nxtmod(mod); /* next in old library */ continue; } if(cmpmod(mptr[m], mod) < 0) { /* module < member */ addmod(mptr[m]); /* add new module */ puts2(" Added ", mptr[m]); ++m; /* next in module list */ continue; } if(*mod != HIGH) { /* equal and not at end */ addmod(mptr[m]); /* add new module */ ++m; /* next in module list */ puts2("Replaced ", mod); nxtmod(mod); /* next in old library */ continue; } break; } closeup(); } /* ** abort with a usage message */ usage() { error("Usage: LIB -{DPTUX}[A] library [module...]"); }