home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Vectronix 2
/
VECTRONIX2.iso
/
FILES_01
/
LATTIC_3.LZH
/
EXAMPLES
/
GSTLIB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-02
|
30KB
|
1,242 lines
/* lc -w -v -csfm -Lav -O -M gstlib.c */
/* librarian for GST .bin files (c) k.b.v. controls 02 jun 1989
* read existing archive into memory, and build list of modules
* process arguments, and modify the archive list
* output a ranlib consisting of comment items
* output the modules on the list to tmp file. if ok unlink old and rename
* we should be able to sort archive list into single pass order as default.
* if we use a|b modifiers, the sorting is not done.
* we will do everything in memory, requiring approx 100k for typical archive.
*
* we must have a module name entry in the .bin file else we have problems
* Prospero libraries have wierd module name entries.
* if we convert to a more reasonable name in our MODULE structure
* then we can continue as per Unix.
* ie convert to "WIERD blah blah" to "wierd.bin"
* but "normal.ext" remains as "normal.ext"
*
*/
#include <stdio.h>
#include <osbind.h>
#ifdef LATTICE
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#define lmalloc(n) malloc(n)
#endif
/* #define DEBUG */
#define JAN011980 ((1 << 5) | 1)
#define UPDATE 1
#define LOAD 2
#ifdef DEBUG
#define D(x) x
#else
#define D(x)
#endif
/*
* Modes, a la GEM-DOS:
*/
#define S_IJRON 0x01 /* Read-only */
#define S_IJHID 0x02 /* Hidden from search */
#define S_IJSYS 0x04 /* System, hidden from search */
#define S_IJVOL 0x08 /* Volume label in first 11 bytes */
#define S_IJDIR 0x10 /* Directory */
#define S_IJWAC 0x20 /* Written to and closed */
typedef struct {
char d_glob[12]; /* GEMDOS wildcard string from Fsfirst */
char d_mask; /* Attribute mask from Fsfirst */
char d_dirent[4]; /* Offset into directory, MSB first */
char d_dirid[4]; /* Pointer to directory structure in GEM mem */
char d_fattr; /* File attributes */
long d_tandd; /* Time and date words */
long d_fsize; /* File size */
char d_fname[14]; /* File name */
} DMABUFFER;
typedef struct tm {
int tm_sec; /* Seconds (0-59) */
int tm_min; /* Minutes (0-59) */
int tm_hour; /* Hours (0-23); 0 = midnight */
int tm_mday; /* Day of month (1..28,29,30,31) */
int tm_mon; /* Month (0-11); 0 = January */
int tm_year; /* Year AD since 1900 */
int tm_wday; /* Day of week (0-6): 0 = Sunday */
int tm_yday; /* Day of year (0-365,366) */
int tm_isdst; /* Daylight savings time flag: */
/* Non-standard, they make negative==NA */
} tm_t;
typedef unsigned long tand_t; /* we use disk format for time */
#ifndef NARGS
tand_t tm_to_tand(tm_t *);
tm_t *tand_to_tm(tand_t);
void mytime(tand_t *);
char *myctime(tand_t *);
#else
tand_t tm_to_tand();
tm_t *tand_to_tm();
void mytime();
char *myctime();
#endif
typedef union any_ptr {
char *name;
struct mod_info *module;
struct cref_info *cref;
} PTR;
typedef struct list {
struct list *next;
PTR p;
} LIST;
typedef struct mod_info {
char *name;
tand_t date;
long size;
unsigned char *buf;
LIST *xdef;
LIST *xref;
} MODULE;
typedef struct cref_info {
char *name;
LIST *xdef;
LIST *xref;
} CREF;
#define MALLOC(x) (x *)malloc(sizeof(x))
#define AFTER 1
#define BEFORE 2
#define TRUE 1
#define VOIDP char * /* really want a void * */
LIST *libhead = NULL;
LIST *xrefhead = NULL;
LIST *beforemod = NULL;
LIST *ranlib = NULL;
char *aftmodname;
extern int errno;
int verbose, aftbef, sortflag, keepflag, quitflag;
#ifndef LATTICE
char *calloc(), *malloc(), *realloc(), *strrchr(), *strchr();
#endif
#define addlist(x, y) inslist(x, y, NULL)
#ifndef NARGS
void inslist(LIST **, VOIDP, LIST *); /* want to check for ptr argument */
void dellist(LIST **, LIST *);
void mkxrefs(LIST *, LIST **);
void prtxrefs(LIST *);
void prtlist(LIST *, char *);
int sortxrefs(LIST **, LIST *);
int weneed(LIST *, MODULE *);
int weload(LIST **, LIST **, MODULE *);
int mkcode(int, char *, char *, int);
void fatal(char *, char *);
void faterr(char *, char *);
MODULE *gstread(unsigned char *, unsigned char *);
MODULE *mkranlib(LIST *, char *);
tand_t rdranlib(MODULE *, char *);
LIST *msearch(LIST *, char *);
LIST *nsearch(LIST *, char *);
CREF *addxsym(LIST **, char *);
char *newstring(char *, int);
char *cleannm(char *);
char *strlower(char *);
char *unwierd(char *, int);
#else
void fatal();
void faterr();
void inslist();
void dellist();
void mkxrefs();
void prtxrefs();
void prtlist();
int sortxrefs();
int weneed();
int weload();
int mkcode();
MODULE *gstread();
MODULE *mkranlib();
tand_t rdranlib();
LIST *msearch();
LIST *nsearch();
CREF *addxsym();
char *newstring();
char *strlower();
char *cleannm();
char *unwierd();
#endif
void usage()
{
fprintf(stderr,
"Librarian for GST .bin object files (c) kbv controls 1989\n");
fprintf(stderr,
"Usage: gstlib {dlmrtux}[vsk][a|b obmod] library [files..]\n");
fprintf(stderr, "\toptions\td delete modules\n");
fprintf(stderr, "\t\tm move modules\n");
fprintf(stderr, "\t\tr replace modules\n");
fprintf(stderr, "\t\tu update modules\n");
fprintf(stderr, "\t\tl load modules\n");
fprintf(stderr, "\t\tt table [modules..]\n");
fprintf(stderr, "\t\tx extract [modules..]\n");
fprintf(stderr, "\t\modifiers\tv verbose\n");
fprintf(stderr, "\t\t\ta|b obmod with m|r replace after|before obmod\n");
fprintf(stderr, "\t\t\ts sort library for single pass\n");
fprintf(stderr, "\t\t\tk keep module datestamp when extracting\n");
fprintf(stderr, "\tall modified libraries will have a ranlib\n");
exit(1);
}
int main(argc, argv)
int argc;
char *argv[];
{
char **myargv;
char inpbuf[160], *p, *q, *r;
int myargc = 0;
int i, j;
FILE *fp;
myargv = NULL;
for (i = 1; i < argc; i++) {
strlower(argv[i]);
if (argv[i][0] == '@') {
if ((myargv = (char **)calloc(sizeof(char *), 200)) == NULL)
fatal("exparg", "duff calloc");
break;
}
}
if (myargv) {
for (i = 0; i < argc; i++) {
if (argv[i][0] == '@') {
if ((fp = fopen(argv[i] + 1, "r")) == NULL)
fatal("exparg", argv[i]);
while (fgets(inpbuf, 160, fp) != NULL) {
p = inpbuf;
while (*p) {
while (*p == ' ' || *p == '\t' || *p == '\n') p++;
if (*p == '\0' || *p == '#') break;
if (*p == '\\' && *(p+1) == '\n') break;
q = p;
for (j = 0; *p && *p != ' ' && *p != '\t' && *p != '\n'; j++,p++) ;
if (j) {
if ((r = malloc(j+1)) == NULL)
fatal("exparg", "duff malloc");
strncpy(r, q, j);
r[j] = '\0';
myargv[myargc++] = r;
}
}
}
fclose(fp);
}
else myargv[myargc++] = argv[i];
if (myargc > 199) fatal("exparg", "too many args");
}
myargv[myargc] = NULL;
return (mymain(myargc, myargv));
}
return (mymain(argc, argv));
}
int mymain(argc, argv)
int argc;
char **argv;
{
char *libname, *cmd, *p;
int ret = 2;
int fd, keepran, exist = 1;
setbuf(stdout, NULL);
if (argc < 3)
usage();
p = cmd = *++argv;
switch (*cmd) {
case 'r':
case 'u': exist = 0;
case 'd':
case 'm':
case 'l': keepran = 0; break;
case 't':
case 'x': keepran = 1; break;
default:
fatal("Usage",
"gstlib {dmrutx}[vsk][a|b modname] archive files..");
break;
}
while (*++p) {
switch (*p) {
case 'a': aftbef |= AFTER; break;
case 'b': aftbef |= BEFORE; break;
case 'v': verbose++; break;
case 's': sortflag = TRUE; break;
case 'k': keepflag = TRUE; break;
case 'q': quitflag = TRUE; break;
default: usage(); break;
}
}
if (aftbef) aftmodname = *++argv;
libname = *++argv;
if ((fd = open(libname, O_RAW)) > 0) close(fd);
else {
if (exist) fatal(libname, "library does not exist");
else if (verbose)
fprintf(stderr, "creating new library %s\n", libname);
}
if (fd > 0) readlib(&libhead, libname, keepran);
if (aftbef) {
if (*cmd != 'r' || *cmd != 'm' || *cmd != 'u')
fatal("a or b modifiers only with r or m option", cmd);
if ((beforemod = msearch(libhead, aftmodname)) == NULL)
fatal(aftmodname, "not in library");
if (aftbef & AFTER) {
beforemod = beforemod->next;
}
}
else beforemod = NULL;
switch (*cmd) {
case 'd': ret = delete(libname, ++argv); break;
case 'l': ret = replace(libname, ++argv, LOAD); break;
case 'm': ret = move(libname, ++argv); break;
case 'r': ret = replace(libname, ++argv, 0); break;
case 't': ret = table(libname, ++argv); break;
case 'u': ret = replace(libname, ++argv, UPDATE); break;
case 'x': ret = extract(libname, ++argv); break;
}
myexit(ret);
}
myexit(ret)
int ret;
{
if (ferror(stdout)) {
fprintf(stderr, "stream error on <stdout>\n");
ret |= 1;
}
if (quitflag) {
fprintf(stderr, "press return to continue\n");
getchar();
}
exit(ret);
}
/* print the table.
* if (verbose == 0) just the modnames
* if (verbose > 0) we do size and datestamp
* if (verbose > 1) we do xdefs (and xrefs)
* if (verbose > 3) we do a cross-reference of symbols too.
*/
int table(libname, namelist)
char *libname, **namelist;
{
register LIST *l;
register MODULE *m;
LIST *xlisthead = NULL;
LIST *tablehead = NULL;
register char *name;
int all = 1;
name = NULL;
if (*namelist) all = 0;
while (all || (name = *namelist++)) {
for (l = libhead; l != NULL; l = l->next) {
m = l->p.module;
if ((name != NULL) && (strcmp(name, m->name) != 0))
continue;
addlist(&tablehead, (VOIDP)m);
if (verbose) {
printf("%-16.16s size:%5ld date:%s",
m->name, m->size, myctime(&m->date));
}
else printf("%s\n", m->name);
if (verbose > 1)
prtlist(m->xdef, " xdef:");
if (verbose > 2)
prtlist(m->xref, " xref:");
if (all = 0) break;
}
all = 0;
}
if (verbose > 3) {
mkxrefs(tablehead, &xlisthead);
prtxrefs(xlisthead);
}
return 0;
}
/* replace the modules found in the file, (it may have multiple mods)
* if update mode is set, we only replace out of date modules
*/
replace(libname, namelist, mode)
char *libname, **namelist;
int mode;
{
char *name;
register LIST *l, *xl;
LIST *onemod, *resolved = NULL, *unres = NULL;
register MODULE *m;
tand_t old, new;
int count = 0, ret = 0;
if (mode & LOAD)
for (l = libhead; l; l = l->next)
if (weload(&resolved, &unres, l->p.module)) ret |= 1;
while (name = *namelist++) {
onemod = NULL;
readlib(&onemod, name, 0);
for (l = onemod; l; l = l->next) {
m = l->p.module;
new = m->date;
new = (new >> 16) | (new << 16);
if (mode & LOAD) {
if (weneed(unres, m) == 0) continue;
if (weload(&resolved, &unres, m)) ret |= 1;
}
if (xl = msearch(libhead, m->name)) {
old = xl->p.module->date;
old = (old >> 16) | (old << 16);
if (!(mode & UPDATE) || old < new) {
xl->p.module = l->p.module;
if (verbose)
printf("r %s\n", m->name);
count++;
}
}
else {
inslist(&libhead, (VOIDP)l->p.module, beforemod);
if (verbose) printf("a %s\n", m->name);
count++;
}
}
}
if (verbose > 1 && (mode & LOAD))
prtlist(unres, "unresolved:");
if (ret) return ret;
if ((mode & UPDATE) && (count == 0)) return 0;
return (copyback(libhead, libname));
}
move(libname, namelist)
char *libname, **namelist;
{
char *name;
LIST *l;
MODULE *m;
while (name = *namelist++) {
if ((l = msearch(libhead, name)) == NULL) {
printf("move: %s is not in library", name);
}
else {
m = l->p.module;
dellist(&libhead, l);
inslist(&libhead, (VOIDP)m, beforemod);
if (verbose) printf("m %s\n", m->name);
}
}
return (copyback(libhead, libname));
}
delete(libname, namelist)
char *libname, **namelist;
{
char *name;
LIST *l;
int ret = 0;
if (*namelist == NULL) return -1;
while (name = *namelist++) {
if (l = msearch(libhead, name)) {
dellist(&libhead, l);
if (verbose) printf("d %s\n", name);
}
else {
printf("delete: %s not in archive\n", name);
ret |= 1;
}
}
if (ret) return(ret);
return (copyback(libhead, libname));
}
extract(libname, namelist)
char *libname, **namelist;
{
char *name;
char tmpname[80];
LIST *l, *xl, onemod;
MODULE *m;
int dummy = 0;
int ret = 0;
if (*namelist == NULL) xl = libhead;
else xl = NULL;
for (;;) {
if (xl == NULL) name = *namelist++;
else {
m = xl->p.module;
xl = xl->next;
name = m->name;
}
if (name == NULL) break;
if (l = msearch(libhead, name)) {
m = l->p.module;
strcpy(tmpname, m->name);
if (*tmpname == '\0')
sprintf(tmpname, "dummy%03d.bin", ++dummy);
if (verbose) printf("x %s\n", tmpname);
onemod.p.module = l->p.module;
onemod.next = NULL;
writemod(&onemod, tmpname, keepflag);
}
else {
printf("extract: %s not in %s\n", name, libname);
ret |= 1;
}
}
return ret;
}
/* read a file into memory, and append details to listp
* if a single module with no ranlib we use the file datestamp else jan 1 1970
* if the first module is "ranlib" then we re-adjust date fields from there
* and eliminate "ranlib" from our enquiries.
*/
int readlib(listp, name, keepran)
LIST **listp;
char *name;
int keepran;
{
DMABUFFER filestat;
long count;
int chunk;
tand_t t;
unsigned char *mp, *p, *endp;
MODULE *m, *ranmod = NULL;
LIST *l;
int fd;
if (mystat(name, &filestat) < 0) faterr("cannot mystat", name);
if ((mp = lmalloc(filestat.d_fsize)) == NULL)
fatal("readlib", "lmalloc");
if ((fd = open(name, O_RAW)) < 0) faterr("cant open", name);
for (p = mp, count = filestat.d_fsize; count > 0L; p += chunk) {
chunk = (count > 4096L) ? 4096 : count;
if (read(fd, p, chunk) != chunk) faterr("read error", name);
count -= chunk;
}
close(fd);
for (count = 0L, p = mp, endp = mp + filestat.d_fsize; p < endp; ) {
if ((m = gstread(p, endp)) == NULL) fatal("duff module", name);
m->date = JAN011980;
addlist(listp, (VOIDP)m);
count += m->size;
p += m->size;
}
if (l = msearch(*listp, "ranlib.bin")) {
ranmod = l->p.module;
if (l != *listp) fatal("ranlib.bin", "is not at beginning");
if (keepran == 0) dellist(listp, l);
for (l = *listp; l; l = l->next) {
m = l->p.module;
t = rdranlib(ranmod, m->name);
m->date = t;
D(printf("module:%s %s", m->name, myctime(&m->date));)
}
}
else if ((l = *listp) && (l->next == NULL))
l->p.module->date = filestat.d_tandd;
return 0;
}
/* given a memory address, we read the memory to analyse the module.
* if ok, we return the details in a freshly malloced MODULE structure
* else we return NULL
*/
MODULE *gstread(mp, endp)
unsigned char *mp;
register unsigned char *endp;
{
register unsigned char *p;
register MODULE *m;
register int len, byte;
register short section;
char *newname;
if ((m = MALLOC(MODULE)) == NULL) fatal("gstread", "malloc");
m->name = "";
m->buf = mp;
m->size = m->date = 0L;
m->xdef = m->xref = NULL;
p = mp;
if (*p != 0xfb || *(p+1) != 0x01) return NULL;
p += 2;
len = *p++;
newname = unwierd(p, len);
m->name = newstring(newname, strlen(newname));
p += len;
while (p < endp) {
if (*p++ != 0xfb) continue;
switch (byte = *p++) {
case 0xfb: break;
case 0x01: m->size = (long)(p - mp -2); return m;
case 0x02: len = *p++; p += len; break;
case 0x03: p += 4; break;
case 0x04: p += 2; break;
case 0x05: p += 4; break;
case 0x06: /* XDEF */
len = *p++;
addlist(&m->xdef, (VOIDP)newstring(p, len));
p += len;
p += 4; /* .kbv was missing */
section = (*p << 8) + *(p+1);
p += 2;
break;
case 0x07:
p += 5;
while (*p++ != 0xfb) p += 2;
break;
case 0x10: /* XREF */
section = (*p << 8) + *(p+1);
p += 2;
len = *p++;
if (section >= 0) addlist(&m->xref, (VOIDP)newstring(p, len));
p += len;
break;
case 0x12:
p += 2;
break;
case 0x13: m->size = (long)(p - mp); return m;
default:
printf("escape 0xfb%02x in %s\n", byte, m->name);
fatal("gstread", "unknown object type");
break;
}
}
fatal("gstread", "unexpected EOF");
}
/* insert an item before list entry and update head if empty
* if posn is NULL, then we are adding to the end of list
* if posn is not in the list, we've had it
*/
void inslist(head, str, posn)
LIST **head;
VOIDP str;
register LIST *posn;
{
register LIST *l, *new;
if ((new = MALLOC(LIST)) == NULL) fatal("inslist", "malloc");
new->next = posn;
new->p.name = str;
for (l = *head; l; l = l->next) {
if (l->next == posn) {
l->next = new;
return;
}
}
*head = new;
return;
}
/* delete entry from list
*/
void dellist(head, lentry)
LIST **head;
LIST *lentry;
{
register LIST *l;
if (lentry == *head) *head = lentry->next;
else {
for (l = *head; l->next; l = l->next) {
if (l->next == lentry) {
l->next = lentry->next;
break;
}
}
}
free(lentry);
}
int weneed(reflist, newmod)
register LIST *reflist;
register MODULE *newmod;
{
register LIST *l;
if (reflist == NULL) return 0;
for (l = newmod->xdef; l; l = l->next)
if (nsearch(reflist, l->p.name)) return 1;
return 0;
}
/* merge the new module's symbols into our lists
* if multiple xdefs then shout
*/
int weload(pdeflist, preflist, newmod)
MODULE *newmod;
LIST **pdeflist, **preflist;
{
register LIST *l, *xl;
register char *name;
int ret = 0;
for (l = newmod->xdef; l; l = l->next) {
name = l->p.name;
if (xl = nsearch(*preflist, name))
dellist(preflist, xl);
if (nsearch(*pdeflist, name)) {
ret |= 1;
printf("%s is multiply defined in %s\n",
name, newmod->name);
}
else addlist(pdeflist, name);
}
for (l = newmod->xref; l; l = l->next) {
name = l->p.name;
if (nsearch(*pdeflist, name)) continue;
if (nsearch(*preflist, name) == NULL)
addlist(preflist, name);
}
return ret;
}
/* build an xref list from the module list
*/
void mkxrefs(list, xlist)
LIST *list;
LIST **xlist;
{
LIST *modlist;
register LIST *l;
register MODULE *m;
register CREF *xr;
char *symbol, *modname;
for (modlist = list; modlist; modlist = modlist->next) {
m = modlist->p.module;
modname = m->name;
for (l = m->xdef; l; l = l->next) {
symbol = l->p.name;
xr = addxsym(xlist, symbol);
addlist(&xr->xdef, (VOIDP)modname);
}
for (l = m->xref; l; l = l->next) {
symbol = l->p.name;
xr = addxsym(xlist, symbol);
addlist(&xr->xref, (VOIDP)modname);
}
}
}
/* display the xref list
*/
void prtxrefs(xlist)
LIST *xlist;
{
register LIST *l, *xl;
register CREF *xr;
for (l = xlist; l; l = l->next) {
xr = l->p.cref;
printf("symbol:%s", xr->name);
if (xl = xr->xdef) {
printf("\txdef:");
for ( ; xl; xl = xl->next) printf(" %s", xl->p.name);
}
printf("\n");
prtlist(xr->xref, " xref:");
}
}
void prtlist(list, title)
register LIST *list;
char *title;
{
register LIST *l;
char buf[256];
l = list;
while (l) {
strcpy(buf, title);
for (; l; l = l->next) {
strcat(buf, " ");
strcat(buf, l->p.name);
if (strlen(buf) > 60) break;
}
printf("%s\n", buf);
}
}
/* we go thru the whole list of xdef'd symbols.
* if it is possible to find any module that contains xref to symbol
* we move the xdef MODULE info in the main list to after the xref MODULE
* we give up if we make moves but list in unchanged.
* we give up if we have 50 attempts to sort list.
*/
int sortxrefs(list, xlist)
LIST **list;
LIST *xlist;
{
register LIST *l, *xl;
LIST *xrefl, *refpsn, *defpsn, *copyhead;
MODULE *m;
register CREF *xr;
register int exchanges, changed, attempts;
char *modname;
copyhead = NULL;
for (l = *list; l; l = l->next)
addlist(©head, (VOIDP)l);
for (attempts = 0; attempts < 50; attempts++) {
exchanges = 0;
for (l = *list, xl = copyhead; l; l = l->next, xl = xl->next)
xl->p.module = l->p.module;
for (l = xlist; l; l = l->next) {
xr = l->p.cref;
for (xl = xr->xdef; xl; xl = xl->next) {
defpsn = msearch(*list, xl->p.name);
modname = xl->p.name;
for (xrefl = xr->xref; xrefl; xrefl = xrefl->next) {
if (refpsn = msearch(defpsn, xrefl->p.name)) {
D(printf("moving %s after %s\n", modname, xrefl->p.name);)
m = defpsn->p.module;
dellist(list, defpsn);
inslist(list, (VOIDP)m, refpsn->next);
defpsn = refpsn->next;
exchanges++;
}
}
}
}
if (verbose > 3)
printf("attempt :%d moves done :%d\n", attempts, exchanges);
if (exchanges == 0) return 0;
for (l = *list, xl = copyhead, changed = 0; l; l = l->next, xl = xl->next) {
if (xl->p.module != l->p.module) {
changed = 1;
break;
}
}
if (changed == 0) return 1;
}
return 1;
}
tand_t rdranlib(ranmod, name)
MODULE *ranmod;
char *name;
{
register MODULE *m;
register unsigned char *p;
tm_t t;
int byte, len;
char buf[128];
sprintf(buf,"module:%-16.16s", name);
m = ranmod;
p = m->buf;
if (*p != 0xfb || *(p+1) != 0x01) return JAN011980;
p += 2;
len = *p++;
if (strncmp(p, "ranlib.bin", len)) return JAN011980;
p += len;
for (;;) {
if (*p++ != 0xfb) return 0L;
switch (byte = *p++) {
case 0x01: return JAN011980;
case 0x02:
len = *p++;
if (strncmp(p, buf, strlen(buf)) == 0) {
strncpy(buf, p, len);
p = buf + 32;
t.tm_mon = atoi(p) - 1; p += 3;
t.tm_mday = atoi(p); p += 3;
t.tm_year = atoi(p) - 1900; p += 5;
t.tm_hour = atoi(p); p += 3;
t.tm_min = atoi(p); p += 3;
t.tm_sec = atoi(p);
return (tm_to_tand(&t));
}
p += len;
break;
case 0x13: return JAN011980;
default:
fatal("rdranlib", "unknown object type");
break;
}
}
}
MODULE *mkranlib(list, name)
LIST *list;
char *name;
{
register LIST *xl;
register unsigned char *p;
register MODULE *m;
register int pass;
MODULE *ranmod;
LIST *l, onemod;
tm_t *tp;
char buf[1000], *mp = NULL;
if ((ranmod = m = MALLOC(MODULE)) == NULL) fatal("mkranlib", "MALLOC");
m->name = name;
m->size = 0L;
m->buf = NULL;
mytime(&m->date);
m->xref = m->xdef = NULL;
onemod.p.module = m;
onemod.next = list;
for (pass = 0; pass < 2; pass++) {
p = mp;
sprintf(buf, "%s", name);
D(printf("mkranlib: %s\n", buf);)
p += mkcode(0x01, p, buf, pass);
for (l = &onemod; l; l = l->next) {
m = l->p.module;
tp = tand_to_tm(m->date);
sprintf(buf,
"module:%-16.16s %8ld %02d %02d %04d %02d %02d %02d ",
m->name, m->size,
tp->tm_mon+1,
tp->tm_mday,
tp->tm_year+1900,
tp->tm_hour,
tp->tm_min,
tp->tm_sec);
D(printf("%s\n", buf);)
p += mkcode(0x02, p, buf, pass);
if (xl = m->xdef) {
more:
strcpy(buf, "xdef:");
for (; xl; xl = xl->next) {
strcat(buf, " ");
strcat(buf, xl->p.name);
if (strlen(buf) > 60) break;
}
D(printf("%s\n", buf);)
p += mkcode(0x02, p, buf, pass);
if (xl) goto more;
}
}
p += mkcode(0x13, p, NULL, pass);
m = ranmod;
m->size = (long)(p - mp);
if (pass == 0)
if ((p = mp = m->buf = malloc((unsigned)m->size)) == NULL)
fatal("mkranlib", "malloc");
}
D(printf("ranlib size: %ld\n", m->size);)
return m;
}
int mkcode(code, mp, buf, doflag)
register char *mp, *buf;
register int code, doflag;
{
register char *p;
register int len;
p = mp;
if (doflag) {
*p++ = 0xfb;
*p++ = code;
}
else p += 2;
if (buf != NULL) {
len = strlen(buf);
if (doflag) {
*p++ = len;
strncpy(p, buf, len);
}
else p++;
p += len;
}
return (p - mp);
}
/* lookup a module name in LIST of modules
*/
LIST *msearch(list, name)
LIST *list;
char *name;
{
register LIST *l;
register MODULE *m;
for (l = list; l ; l = l->next) {
m = l->p.module;
if (m && (strcmp(m->name, name) == 0)) return l;
}
return NULL;
}
/* lookup a name in LIST of names
*/
LIST *nsearch(list, name)
LIST *list;
register char *name;
{
register LIST *l;
for (l = list; l ; l = l->next) {
if ((strcmp(l->p.name, name) == 0)) return l;
}
return NULL;
}
/* insert symbol into sorted list of xref symbols
* create a new node if reqd. return ptr to CREF
*/
CREF *addxsym(xlist, name)
LIST **xlist;
char *name;
{
register LIST *l;
register CREF *xr;
register int cmp;
for (l = *xlist; l ; l = l->next) {
xr = l->p.cref;
cmp = strcmp(name, xr->name);
if (cmp == 0) return xr;
if (cmp < 0) break;
}
if ((xr = MALLOC(CREF)) == NULL)
fatal("addxsym", "MALLOC");
xr->name = name;
xr->xref = xr->xdef = NULL;
inslist(xlist, (VOIDP)xr, l);
return xr;
}
/* copy archive back to tmp file inserting "ranlib" module
*/
int copyback(liblist, libname)
LIST *liblist;
char *libname;
{
int ret = 0;
LIST *xlist, *list;
char tempname[200], *p;
strcpy(tempname, libname);
if (p = strrchr(tempname, '\\')) p++;
else p = tempname;
strcpy(p, "libname.tmp");
list = liblist;
xlist = NULL;
if (sortflag) {
mkxrefs(list, &xlist);
if (ret = sortxrefs(&list, xlist))
fprintf(stderr, "unable to sort library %s\n", libname);
}
if (msearch(list, "ranlib.bin") == NULL)
inslist(&list, (VOIDP)mkranlib(list, "ranlib.bin"), list);
ret |= writemod(list, tempname, 0);
if (ret == 0) {
unlink(libname);
if (rename(tempname, libname) != 0) faterr("rename", libname);
}
return ret;
}
/* write a list of modules to name
*/
int writemod(list, name, touch)
LIST *list;
char *name;
int touch;
{
register LIST *l;
register MODULE *m;
register int fd, chunk, ret;
register long count;
register unsigned char *p;
if ((fd = creat(name, O_RAW)) < 0) faterr("cant creat", name);
for (l = list; l != NULL; l = l->next) {
m = l->p.module;
for (count = m->size, p = m->buf; count > 0L; ) {
chunk = (count > 4096L) ? 4096 : count;
if (write(fd, p, chunk) != chunk)
faterr("write error", name);
count -= chunk;
p += chunk;
}
}
ret = close(fd);
if (touch) keepdate(name, m->date);
return ret;
}
char *newstring(mp, len)
register char *mp;
int len;
{
register char *dst, *str;
if ((str = dst = malloc(len + 1)) == NULL) fatal("newstring", "malloc");
while (len--) *dst++ = *mp++;
*dst = '\0';
D(printf("%s\n", str);)
return str;
}
/* make a normal lowercase filename
* with a .bin extension if none already
*/
char *unwierd(name, len)
char *name;
int len;
{
register char *p, *dst;
static char wierdbuf[200];
for (p = name, dst = wierdbuf, *dst = '\0'; len > 0; len--, p++) {
if (*p == ' ') break;
*dst++ = (*p >= 'A' && *p <= 'Z') ? *p + ('a' - 'A') : *p;
}
*dst++ = '\0';
*dst++ = '\0';
if (strchr(wierdbuf+1, '.') == NULL) strcat(wierdbuf, ".bin");
return wierdbuf;
}
char *strlower(s)
char *s;
{
register char *p;
for (p = s; *p; p++)
*p = (*p >= 'A' && *p <= 'Z') ? *p + ('a' - 'A') : *p;
return s;
}
char *cleannm(name)
char *name;
{
register char *p;
if (p = strrchr(name, '\\')) return p+1;
if (p = strrchr(name, ':')) return p+1;
return name;
}
void faterr(s, t)
char *s, *t;
{
fprintf(stderr, "gstlib: Fatal error: %s %s\n", s, t);
perror("Tos error");
myexit(1);
}
void fatal(s, t)
char *s, *t;
{
fprintf(stderr, "gstlib: Fatal error: %s %s\n", s, t);
myexit(1);
}
#ifndef LATTICE
rename(old, new)
char *new, *old;
{
int ret;
ret = Frename(0, old, new);
if (ret < 0) errno = -ret;
return ret;
}
#endif
keepdate(name, date)
char *name;
tand_t date;
{
int fd;
if ((fd = Fopen(name, 0)) > 0) {
Fdatime(&date, fd, 1);
Fclose(fd);
}
else {
errno = -fd;
perror(name);
}
return fd;
}
int mystat(fullname, statptr)
char *fullname;
DMABUFFER *statptr;
{
DMABUFFER *saved;
char *name;
int ret = 0;
name = cleannm(fullname);
saved = (DMABUFFER *)Fgetdta();
Fsetdta(statptr);
ret = Fsfirst(fullname, 0);
if (ret < 0) {
errno = -ret;
ret = -1;
}
/* else if (strcmp(name, statptr->d_fname) != 0) ret = -1; */
Fsetdta(saved);
return ret;
}
tm_t *tand_to_tm(tandd)
register tand_t tandd;
{
static tm_t tm;
static int monbeg[2][12] = {
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 306, 335 }
};
register unsigned time;
register unsigned date;
int leap;
time = tandd >> 16;
date = tandd & 0xffffL;
tm.tm_sec = (time & 0x1f)<< 1; /* Seconds (0-59) */
tm.tm_min = (time >> 5) & 0x3f; /* Minutes (0-59) */
tm.tm_hour = (time >> 11) & 0x1f; /* Hours (0-23); 0 = midnight */
tm.tm_mday = ((date) & 0x1f); /* Day of month (1..28,29,30,31) */
tm.tm_mon = ((date >> 5) & 0x0f) - 1; /* Month (0-11); 0 = January */
tm.tm_year = ((date >> 9) & 0x3f)+80; /* Year AD since 1900 */
leap = ((tm.tm_year %4) == 0);
tm.tm_yday = monbeg[leap][tm.tm_mon] + tm.tm_mday - 1;
tm.tm_wday = (3 + tm.tm_year + (tm.tm_year << 2) + tm.tm_yday) % 7;
return &tm;
}
tand_t tm_to_tand(tp)
register tm_t *tp;
{
register tand_t tandd = 0L;
tandd <<= 5; tandd |= (tp->tm_hour);
tandd <<= 6; tandd |= (tp->tm_min);
tandd <<= 5; tandd |= (tp->tm_sec >> 1);
tandd <<= 7; tandd |= (tp->tm_year - 80);
tandd <<= 4; tandd |= (tp->tm_mon + 1);
tandd <<= 5; tandd |= (tp->tm_mday);
return tandd;
}
void mytime(tandp)
tand_t *tandp;
{
*tandp = Tgettime();
*tandp = (*tandp << 16) | (Tgetdate() & 0xffffL);
}
char *myctime(tandp)
tand_t *tandp;
{
static char ctimbuf[30];
static char *monnm[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static char *daynm[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
tm_t *tp;
tp = tand_to_tm(*tandp);
sprintf(ctimbuf, "%s %s %2d %02d:%02d:%02d %04d GMT\n",
daynm[tp->tm_wday], monnm[tp->tm_mon], tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec, tp->tm_year+1900);
return ctimbuf;
}