# A good place to put all this is /netlib/admin. # to unbundle, sh this file (in an empty directory) mkdir bin/lo.src echo bin/lo.src/README 1>&2 sed >bin/lo.src/README <<'//GO.SYSIN DD bin/lo.src/README' 's/^-//' -datard() is machine-dependent; the one in datard.c works under -several versions of UNIX(R). datard.c.msdos is a version that -works on MSDOS(TM) machines. - -reffetch.a is assembly code understood by DeSmet's ASM88 under -MSDOS; refstore.c is a corresponding C version. The former stems -from a time when DeSmet's small-memory-model C compiler was the -only MSDOS C compiler available to me. - -With the I/O library I have been using under MSDOS, the -raw_fio() calls turn off conversions of \r\n to/from \n . //GO.SYSIN DD bin/lo.src/README echo bin/lo.src/cmpout.c 1>&2 sed >bin/lo.src/cmpout.c <<'//GO.SYSIN DD bin/lo.src/cmpout.c' 's/^-//' -#include -#include "ts.h" - -extern int fullg; - -struct ref1 { - struct ref *next; - char *name; - short rseq; - }; - -struct cheader { - char magic_char; - unsigned short namect; - }; - -cmpout(o0, obj0print) -struct obj1 *o0; -int obj0print; -{ - struct group *g = 0; - struct obj1 *o; - struct ref *r; - struct refc rc; - extern struct ref *undefrefs; - extern unsigned nrefc; - unsigned i, nrefs; - short j; - struct cheader ch; - extern struct obj *obj0; - struct obj1 *obj00; - -#ifdef MSDOS - raw_fio(stdout,1); -#endif - obj00 = obj0print ? 0 : (struct obj1 *) obj0; - ch.magic_char = 0xcd; - for (j = nrefs = 0, o = o0; o; o = o->next) { - if (o == obj00) continue; - for (r = ((struct obj1 *) o)->nextref; r; r = r->next) { - ((struct ref1 *) r)->rseq = - (struct obj *)o != obj0 && r->robj == obj0 ? -1 : j++; - nrefs++; - } - } - for (r = undefrefs; r; r = r->next) { - ((struct ref1 *) r)->rseq = j++; - nrefs++; - } - ch.namect = nrefs; - fwrite((char *)&ch, sizeof(struct cheader), 1, stdout); - for (o = o0; o; o = o->next) { - if (o == obj00) continue; - for (r = ((struct obj1 *) o)->nextref; r; r = r->next) { - fputs(r->name,stdout); - putchar(0); - } - } - for (r = undefrefs; r; r = r->next) { - fputs(r->name,stdout); - putchar(0); - } - for (o = o0; o; o = o->next) { - if (o == obj00) continue; - if (g != o->ogroup) { - g = o->ogroup; - printf("*%s", g->name); - putchar(0); - } - if ((r = ((struct obj1 *) o)->nextref) && r->name == o->name) { - putchar('='); - putchar(0); - do putsu(((struct ref1 *) r)->rseq); - while(r = r->next); - } - else { - fputs(o->name,stdout); - putchar(0); - for (r = ((struct obj1 *) o)->nextref; r; r = r->next) - putsu(((struct ref1 *) r)->rseq); - } - putsu(-1); - for (i = o->iptr; i; i = rc.rcnext) { - reffetch(i, &rc); - j = ((struct ref1 *) rc.rcref)->rseq; - if (j != -1) putsu(j); - if (rc.rcnext >= nrefc) rc.rcnext -= nrefc; - } - putsu(-1); - } - } - -putsu(su) -short su; -{ - if (fwrite((char *)&su, sizeof(short), 1, stdout) != 1) - scream("Write failed!\n",""); - } - -cmpread(infile,inname) -FILE *infile; -char *inname; -{ - struct cheader ch; - char *malloc(), name[NBUFLEN], *ne = name + NBUFLEN, *s; - struct ref *lookup(), *r, **ri; - short i; - int c; - -#ifdef MSDOS - raw_fio(infile,1); -#endif - if (fread((char *)&ch, sizeof(struct cheader), 1, infile) != 1 || - !ch.namect) return; - ri = (struct ref **) malloc(ch.namect*sizeof(struct ref *)); - if (!ri) scream("Not enough memory to read %s\n", inname); - for (i = 0; i < ch.namect; i++) { - for (s = name; *s++ = c = getc(infile); ) { - if (c == EOF) goto early_eof; - if (s >= ne) - scream("Oversized refname in %s\n", inname); - } - ri[i] = lookup(name,1); - } - for(;;){ - for (s = name; *s = c = getc(infile); s++) { - if (c == EOF) { - if (s == name) { free((char *)ri); return; } - goto early_eof; - } - if (s >= ne) - scream("Oversized name in %s\n", inname); - } - if (name[0] == '*') { - if (fullg) newgroup(name+1); - else newobj(name+1,1); - continue; - } - if (name[0] == '=') { - if (fread((char *)&i, sizeof(short), 1, infile) != 1) - goto early_eof; - r = ri[i]; - rdefobjref(r, r->name, 0); - } - else if (fullg) newobj(name, 0); - for(;;){ - if (fread((char *)&i, sizeof(short), 1, infile) != 1) - goto early_eof; - if (i == -1) break; - if ((unsigned short) i >= ch.namect) goto toobig; - r = ri[i]; - defrefr(r, r->name); - } - for(;;){ - if (fread((char *)&i, sizeof(short), 1, infile) != 1) { -early_eof: - scream("early end of file on %s\n", inname); - } - if (i == -1) break; - if ((unsigned short) i >= ch.namect) { -toobig: - scream("oversize ref index in %s\n", inname); - } - newrefr(ri[i]); - } - } - } //GO.SYSIN DD bin/lo.src/cmpout.c echo bin/lo.src/datard.c 1>&2 sed >bin/lo.src/datard.c <<'//GO.SYSIN DD bin/lo.src/datard.c' 's/^-//' -#include -#include "ts.h" - -#ifdef LibRead -#include -#include -#include -#include - -#ifdef mc68k -#define SystemV -#endif - -#ifdef SystemV -#ifdef mc68k -#define lbr(x) (x) -#else -long -lbr(N) -long N; -{ - long L; - register char *n = (char *)&N; - register char *s = (char *)&L; - s[3] = *n; - s[2] = n[1]; - s[1] = n[2]; - *s = n[3]; - return L; - } -#endif - -struct ar1_hdr { - char ar_magic[SARMAG]; - char ar_name[16]; - long ar_date, ar_syms }; - -struct arf1_hdr { - char ar_name[16]; - long arf_date, arf_uid, arf_gid, arf_mode, ar_size; - }; - -#define ar_hdr arf1_hdr -#define arf_hdr arf1_hdr -#define N_BADMAG(x) (x.f_magic != MC68KWRMAGIC &&\ - x.f_magic != MC68KROMAGIC && x.f_magic != MC68KPGMAGIC) -#define N_SYMOFF(x) (x.f_symptr) -#define exec filehdr -#endif - -struct ar_hdr archdr; - -union { - char mag_armag[SARMAG]; - struct exec mag_exp; - } mag_un; - -off_t off; -off_t strsiz; - -int archive; -#endif - -char *malloc(), *realloc(), *strp, *xargv; - -extern int fullg; - -void -datard(s,infile) -char *s; -FILE *infile; -{ - int c; - -#ifdef LibRead - c = fread((char *)&mag_un, sizeof(mag_un), 1, infile); - if (c == 1) { - xargv = s; - off = SARMAG; - fseek(infile, 0L, 0); - if (!strncmp(mag_un.mag_armag, ARMAG, SARMAG)) { - if (fullg) newgroup(s); - else newobj(s,0); - libread(infile,1); - } - else if (!N_BADMAG(mag_un.mag_exp)) { - if (fullg) { newgroup(""); newobj(s,0); } - else newobj("",1); - libread(infile,0); - } - else { fseek(infile, 0L, 0); goto chread; } - } - else -chread: -#endif - { - c = getc(infile); - fseek(infile, 0L, 0); - if (c == 0xcd) cmpread(infile,s); - else if (c < 0x7f) genrl_in(infile); - else scream("Bad file %s\n", s); - } - } - -#ifdef LibRead -libread(infile,lib) -FILE *infile; -int lib; -{ - register j; - off_t o; - register i, n; - struct nlist sym, *symp = 0; - struct stat stb; - -#ifdef SystemV - if (lib) { - struct ar1_hdr arh; - if (fseek(infile, 0L, 0) || - fread((char *)&arh, 1, sizeof(arh), infile) - != sizeof(arh)) return; - off = sizeof(arh) + - lbr(arh.ar_syms) * sizeof(struct ar_sym); - } -#endif - if (!lib || nextel(infile)) do { - archive = lib; - fread((char *)&mag_un.mag_exp, 1, sizeof(struct exec), infile); - if (N_BADMAG(mag_un.mag_exp)) - continue; - if (!lib) fstat(fileno(infile), &stb); - o = N_SYMOFF(mag_un.mag_exp) - sizeof (struct exec); - fseek(infile, o, 1); -#ifdef SystemV - n = mag_un.mag_exp.f_nsyms; -#else - n = mag_un.mag_exp.a_syms / sizeof(struct nlist); -#endif - if (n == 0) { - error(0, "no name list"); - continue; - } -#ifndef SystemV - if (N_STROFF(mag_un.mag_exp) + sizeof(off_t) > - (lib ? off : stb.st_size)) - error(1, "old format .o (no string table) or truncated file"); -#endif - i = 0; - if (strp) - free(strp), strp = 0; - while (--n >= 0) { - fread((char *)&sym, 1, sizeof(sym), infile); -#ifdef SystemV - if (sym.n_sclass != C_EXT) continue; -#else - if ((sym.n_type&N_EXT)==0) - continue; - if ((sym.n_type&N_STAB)) - continue; -#endif - if (symp==NULL) - symp = (struct nlist *) - malloc(sizeof(struct nlist)); - else - symp = (struct nlist *) - realloc((char *)symp, - (unsigned)(i+1)*sizeof(struct nlist)); - if (symp == NULL) - error(1, "out of memory"); - symp[i++] = sym; - } -#ifndef SystemV - if (lib && ftell(infile)+sizeof(off_t) >= off) { - error(0, "no string table (old format .o?)"); - continue; - } - if (fread((char *)&strsiz,sizeof(strsiz),1,infile) != 1) { - error(0, "no string table (old format .o?)"); - return; - } - strp = (char *)malloc((unsigned)strsiz); - if (strp == NULL) - error(1, "ran out of memory"); - if (fread(strp+sizeof(strsiz), (int)strsiz-sizeof(strsiz), - 1,infile) != 1) - error(1, "error reading string table"); - for (j = 0; j < i; j++) - if (symp[j].n_un.n_strx) - symp[j].n_un.n_name = - symp[j].n_un.n_strx + strp; - else - symp[j].n_un.n_name = ""; -#endif - if (lib) newobj(archdr.ar_name,0); - psyms(symp,i); - if (symp) - free((char *)symp), symp = 0; -#ifndef SystemV - if (strp) - free((char *)strp), strp = 0; -#endif - } while(lib && nextel(infile)); - } - -psyms(symp, nsyms) - register struct nlist *symp; - int nsyms; -{ - register int n, c; - - for (n=0; n&2 sed >bin/lo.src/lo.1 <<'//GO.SYSIN DD bin/lo.src/lo.1' 's/^-//' -.ds u \s-2UNIX\s+2 -.TH LO 88 \*(Cf \*(Ch -.SH NAME -lo \(em tell what routines from what libraries and in what order given routines need -.SH SYNOPSIS -.B lo -[\fIoption\fR]... [\fIfile\fR]... -.SH DESCRIPTION -.I Lo -(\fIL\fRoad-\fIO\fRrder) reads \fIfile\fRs describing subroutine libraries -and object files. These \fIfile\fRs may be a mixture of four kinds: -.sp .5 - \(bu object files (produced by a compiler); - \(bu subroutine libraries; - \(bu ASCII (human-readable) files describing libraries and object files; and - \(bu compressed versions of the input \fIfile\fRs from previous \fIlo\fR runs. -.PP -.I Lo -determines the kinds of such input files by looking at their initial byte(s). -.PP -Additionally, if an input \fIfile\fR has a name of the form @\fIflist\fR, -then \fIflist\fR is taken to be the name of a file containing a list of -files of the above kinds (or again of the form @\fIflist\fR). Under -\*u\(rg, such a name is equivalent to \f(CW`cat \fIflist\f(CW`\fR. This -feature is intended for the MS-DOS\(rg version of \fIlo\fR, in which -command argument lists can be at most 128 characters long. -.PP -ASCII files describing libraries and object files consist of a sequence -of words (strings of nonblank, printable characters), separated by -white space (blanks, tabs, newlines, etc.). Words of the form - \fIlibname\fR\(** specify the start of (object) library \fIlibname\fR; - \fIobjname\fR: specify the start of object file \fIobjname\fR; - \fIdefname\fR (not ending in \(**, :, =, or ?) specify that symbol -\fIdefname\fR is defined within the current object module; - \fIrefname\fR? specify that the current object module references (but -does not define) symbol \fIrefname\fR; - \fIobjdef\fR= specify the start of object file \fIobjdef\fR, which -defines symbol \fIobjdef\fR. This is equivalent to ``\fIobjdef\fR: -\fIobjdef\fR\|'' (except that \fIlo\fR stores the string ``\fIobjdef\fR\|'' -only once \(em this is relevant when handling large libraries on -a small machine). -.PP -Input object files go into the null library (named ``\(**''). -Output from \fIlo\fR includes information about all objects -needed by objects in the null library. -.PP -There is one special object file: the null object in the null library -(object : in library \(**). References to symbols defined in -this object are discarded immediately during input (and are -excluded from the output if they were defined -after they were referenced). -.PP -.I Lo -recognizes the following options (which may be elided, except that if ``n'' -appears in an option string, it must be at the end of that string). -If no printing options are given (none of \-d, \-l, \-o, \-r, \-s, \-u, \-v), -then \-ls0 is assumed. ``Printing'' is done on the standard output, -with error messages on the standard error file. -.TP -.B \-0 -(0 = zero) Omit printing information about the special null object. -.TP -.B \-c -Write compressed object and library information on the standard output, -which should be directed to a file. Only the \-0 and \-g options affect the -compressed output. -.TP -.B \-d -Print symbols defined. -.TP -.B \-e -``extract'' input in ASCII form. This is similar to \-c. It differs -from \-tlord in that input is sorted by library, rather than -topologically sorted. -.TP -.B \-g -group libraries into object files (to see the ordering requirements of -libraries): treat libraries as object files defining and referring to -all symbols defined or referred to by objects within the libraries -(and discard object names). -.TP -.B \-k -keep objects that define no symbols. -.TP -.B \-l -(l = lower case L) Print the names of object libraries. -.TP -.B \-m -Merge objects of the same name (and library). Ordinarily \fIlo\fR -ignores duplicate objects. -.TP -.BI "\-n " name -(or \-n\fIname\fR) Make \fIname\fR needed: have the output include -information about all objects directly or indirectly needed by \fIname\fR -(where \fIname\fR does not start with @). -.TP -.BI \-n @nfile -(or \-n@\fInfile\fR) Make all symbols in file \fInfile\fR needed. -.TP -.B \-o -Print the names of objects. -.TP -.B \-p -Inhibit the default printing of cycles on the standard error. For example, -if A calls B, B calls C, and C calls A, then by default you get a message -on the standard error telling about this cycle in the call graph. -.TP -.B \-r -Print symbols referenced but not defined in the objects included in -the output (on a per object basis). -.TP -.B \-s -Print library names that begin with ``#'', and print the names of objects -included within such libraries. When there are both source and object -libraries, this provides a way to have just object names -defined in the source libraries printed. -.TP -.B \-t -Totally order the input, and print information about all objects, -not just those needed (directly or indirectly) by objects in the null library. -.TP -.B \-u -Print the names of symbols that are never defined. -.TP -.B \-v -Verify that the input files and libraries are in an order -acceptable to a one-pass loader \(em print warnings (on the standard error) -about objects (other than the special null object) that refer to symbols -not yet defined. -.TP -.B \-w -Suppress the default warning messages about redefined symbols and repeated -objects. (Note that \fIlo\fR sees nothing wrong with different libraries -having objects with the same name \(em as long as these objects define different -symbols.) -.SH EXAMPLES -.ds p3 \s-2PORT 3\s+2 -.PP - Suppose \f(CWp3\fR is a file describing the \*(p3 source, and you want to -know which files from what parts of this source are needed to run \f(CWDN2F\fR. -.ti +1i -\f(CWlo -n DN2F p3\fR -.br -will tell you this. -.PP - Suppose you have compiled some modules and put them into one or more -libraries in the current directory, and you wish to make a summary file -that \fIlo\fR can use on later runs to tell you what additional \*(p3 -modules you need for some application. -.ti +1i -\f(CWlo -cw \(**.lib p3 >libinfo\fR -.br -will create summary file \fIlibinfo\fR. The \-w option eliminates -warning messages about symbols defined both in \(**.lib and in \f(CWp3\fR. -It is necessary to list your libraries first, so that the symbol -definitions in them are recorded. If you want to make sure none of -your libraries define the same symbol, issue the command -.ti +1i -\f(CWlo \(**.lib\fR -.PP - Suppose you have an application involving all the object files -(\f(CW\(**.obj\fR) in the current directory, -and you wonder which libraries are needed -and whether you must compile anything else. -.ti +1i -\f(CWlo *.obj libinfo\fR -.br -will tell you these things. If you want to know just about additional -source files needed, use the command -.ti +1i -\f(CWlo -s *.obj libinfo\fR -.br -If you want to know just whether you need some modules not in your -object libraries, use the command -.ti +1i -\f(CWlo -u *.obj libinfo\fR -.br -.PP - Some Fortran implementations, such as the one by Microsoft\(rg, define -a large number of symbols in their run-time libraries. -It is often convenient to discard these -symbols, especially if you want to use the \-u option (as above), -or if you are dealing with a large number of symbols. (The MS-DOS -version of \fIlo\fR will handle somewhere around 2100 symbols; it can -handle more if you discard the symbols in \f(CWFORTRAN.LIB\fR, as -follows.) The command -.ti +1i -\f(CWlo -td FORTRAN.LIB >flib\fR -.br -will create a list of the symbols defined in \f(CWFORTRAN.LIB\fR. If -\f(CWflib\fR is the first file that \fIlo\fR sees, it will include -all these symbols as symbols defined in the special null object -and will discard other occurrences of them. If, say, \f(CWp3\fR -does not already automatically discard these symbols for you, -you can make a version, say \f(CWp31\fR, that does via -.ti +1i -\f(CWlo -c flib p3 >p31\fR -.PP - Suppose you have a collection of objects, \f(CW\(**.obj\fR, -that you want put into a library in an order that allows a one-pass loader -to pick up all routines required from the library. You can have -an acceptable order put into file \f(CWzap\fR via -.ti +1i -\f(CWlo -to \(**.obj >zap\fR -.br -This has the same effect as the \*u command -.ti +1i -\f(CWlorder \(**.obj | tsort >zap\fR -.br -.PP - Suppose you want to know which subroutines are called by \f(CW\(**.obj\fR. -You can find out via -.ti +1i -\f(CWlo -or \(**.obj\fR -.br -Similarly you can find out which external symbols are defined in -\f(CWbletch.obj\fR via -.ti +1i -\f(CWlo -d bletch.obj\fR -Except for output formatting, the commands -.ti +1i -\f(CWlo -rod \(**.obj\fR -.br -and -.ti +1i -\f(CWlo -tlord \(**.lib\fR -.br -are thus similar to the \*u commands -.ti +1i -\f(CWnm -g \(**.obj -.br -and -.ti +1i -\f(CWnm -g \(**.lib -.br //GO.SYSIN DD bin/lo.src/lo.1 echo bin/lo.src/lo.c 1>&2 sed >bin/lo.src/lo.c <<'//GO.SYSIN DD bin/lo.src/lo.c' 's/^-//' -/* Load Order program. - * See "Using a Large Library on a Small Machine" by David M. Gay - * (to appear in a book of papers, published by SIAM, from the 1985 ARO - * Workshop on Microcomputers in Large-Scale Scientific Computation). - * - * This was written by David M. Gay. It is not copyrighted, and people - * may copy it at will. It's not guaranteed either! But bug reports to - * research!dmg are welcome. - */ - -#include "ts.h" -#include - -int cyclep = 1, fullg = 1, keepnodefs, verbose = 1, verify; -char *progname = 0; -static int merge = 0; - -usage(rc) -int rc; -{ - static char *opts[] = { - "-0 {omit information about null object}", - "-c {compress all input}", - "-d {output definitions}", - "-e {expand all input}", - "-g {group libraries into single objects}", - "-i {identify symbols with the objects containing them}", - "-k {keep objects with no definitions}", - "-l {output library names}", - "-m {merge objects of the same name}", - "-n OBJ {[or -nOBJ] make OBJ needed}", - "-n@OBJF {make symbols in file OBJF needed}", - "-o {output object names}", - "-p {suppress printing of cycles}", - "-r {output references}", - "-R {output references and objects containing them}", - "-s {output library names starting with # and names", - "\tof needed objects within them}", - "-t {totally order input and output all objects}", - "-u {output undefined objects}", - "-U {output undefined objects to stderr, set exit code}", - "-v {verify whether input is suitable for one-pass loader}", - "-w {suppress warnings of redefinitions}", - 0}; - char **o; - - fprintf(stderr, "Usage: %s [options] [file [file...]]\nOptions:\n", - progname); - for(o = opts; *o; o++) fprintf(stderr, "\t%s\n", *o); - exit(rc); - } - -main(argc,argv) -int argc; -char **argv; -{ - char c, *libfmt, *malloc(), *objfmt, *s; - struct obj *o, *o0, **og, **og1, *onext, *oprev, *ro, *ts1(), *ts0(); - struct obj1 *o1; - struct ref *r, *r1; - struct refc rc; - extern struct ref *undefrefs, *defedrefs; - extern unsigned ngroup, nrefc; - extern struct obj *obj0; - unsigned i, i0, i1; - int j; - struct group *g; - int all = 0, compress = 0, defprint = 0, extract = 0, identify = 0, - libprint = 0, needdata = 1, obj0print = 1, objprint = 0, - refprint = 0, sp, srcprint = 0, undefpr, undefprint = 0; - void datard(), undef(); - -#ifdef MSDOS - progname = "lo"; - argexpan(&argc, &argv); -#else - progname = argv[0]; - s = malloc(2*BUFSIZ); - if (!s) scream("initial malloc failure!",""); - setbuf(stdout, s); - setbuf(stderr, s+BUFSIZ); -#endif - Init(); -nextarg: - while(--argc) { - s = *++argv; - if (s[0] == '-') { - if (!s[1]) { indata(s,datard,1); needdata = 0; } - else while(c = *++s) { - switch(c) { - case '0': - obj0print = 0; break; - case 'c': - compress = 1; break; - case 'd': - defprint = 1; break; - case 'e': - all = extract = objprint = defprint = - refprint = libprint = 1; - break; - case 'g': - fullg = 0; - objprint = 1; - break; - case 'i': - identify = 1; - break; - case 'k': - keepnodefs = 1; break; - case 'l': - libprint = 1; break; - case 'm': - merge = 1; break; - case 'n': - all = 0; - if (*++s) indata(s,undef,0); - else if (--argc) indata(*++argv,undef,0); - else argc = 1; - goto nextarg; - case 'o': - objprint = 1; break; - case 'p': - cyclep = 0; break; - case 'r': - refprint = 1; break; - case 'R': - refprint = 2; break; - case 's': - srcprint = 1; break; - case 't': - all = 1; break; - case 'U': - undefprint |= 2; break; - case 'u': - undefprint |= 1; break; - case 'v': - verify = 1; break; - case 'w': - verbose = 0; break; - case '?': - usage(0); - default: - fprintf(stderr, "%s: unknown option `%c'\n", - progname, c); - usage(1); - } - } - } - else { indata(s,datard,1); needdata = 0; } - } - if (needdata) indata("-",datard,1); - - if (compress || extract) { - o0 = ts0(); - og = (struct obj **) malloc(ngroup*sizeof(struct obj *)); - if (og) { - for (i = 0; i < ngroup; i++) og[i] = 0; - for (o = o0; o; o = onext) { - onext = o->next; - og1 = og + o->ogroup->gseq; - o->next = *og1; - *og1 = o; - } - oprev = (struct obj *) &o0; - for (i = 0; i < ngroup; i++) { - if (o = og[i]) { - oprev->next = o; - do { oprev = o; o = o->next; } while (o); - } - } - free((char *)og); - } - } - else o0 = ts1(all); - if (identify) { - extern char *newstruct(); - extern struct ref *lookup(); - - for(o = o0; o; o = o->next) - o->seq = 0; - j = 1; - for(o = o0; o; o = o->next, j++) { - i0 = 0; - for(i = o->iptr; i; i = i1) { - reffetch(i, &rc); - i1 = rc.rcnext; - if (i1 >= nrefc) - i1 -= nrefc; - r = rc.rcref; - if (ro = r->robj) { - if (ro->seq == j) - continue; - ro->seq = j; - rc.rcref = lookup(ro->name,1); - if (!rc.rcref->robj) - rc.rcref->robj = ro; - } - rc.rcnext = i0; - i0 = i; - refstore(i, &rc); - } - o->iptr = i0; - } - r = defedrefs; - defedrefs = 0; - for(o = o0; o; o = o->next, r = r1) { - if (r) - r1 = r->next; - else { - r = (struct ref *) - newstruct(sizeof(struct ref)); - r1 = 0; - } - r->next = defedrefs; - defedrefs = r; - r->name = o->name; - r->robj = o; - } - } - for (o = o0; o; o = o->next) ((struct obj1 *)o)->nextref = 0; - for (r = defedrefs; r; r = r1) { - r1 = r->next; - if (o1 = (struct obj1 *) r->robj) { - r->next = o1->nextref; - o1->nextref = r; - } - } - if (!keepnodefs) for(oprev = (struct obj *) &o0; o = oprev->next;) { - if (((struct obj1 *)o)->nextref) oprev = o; - else oprev->next = o->next; - } - if (compress) { - cmpout((struct obj1 *)o0, obj0print); - return 0; - } - g = 0; - undefpr = undefprint; - if (!libprint && !objprint && !srcprint && !defprint && - !refprint && !verify) { - if (undefprint) undefpr = undefprint & 2; - else { - libprint = srcprint = 1; - obj0print = 0; - } - } - libfmt = objprint || defprint || refprint || srcprint ? "%s*\n" : "%s\n"; - objfmt = defprint || refprint ? "%s:\n" : "%s\n"; - sp = 0; - for (o = o0; o; o = o->next) { - if (o == obj0 && !(all && obj0print)) continue; - if ((libprint || srcprint) && g != o->ogroup) { - g = o->ogroup; - sp = srcprint && *g->name == '#'; - if (libprint || sp) printf(libfmt, g->name); - } - if (defprint) { - r = ((struct obj1 *)o)->nextref; - if (objprint || sp) { - if (r && r->name == o->name) { - printf("%s=\n", o->name); - r = r->next; - } - else printf(objfmt, o->name); - } - for (; r; r = r->next) puts(r->name); - } - else if (objprint || sp) printf(objfmt, o->name); - if (refprint) { - static char *reffmt[2] = { "%s?\n", "%s?\t%s\n" }; - s = reffmt[refprint-1]; - for (i = o->iptr; i; i = rc.rcnext) { - reffetch(i, &rc); - if (rc.rcref->robj != obj0) - if (ro = rc.rcref->robj) - printf(s, rc.rcref->name, - ro->name); - else if (!identify) - printf(reffmt[0], - rc.rcref->name); - if (rc.rcnext >= nrefc) rc.rcnext -= nrefc; - } - } - } - if (undefprint && undefrefs) { - for (o = o0; o; o = o->next) { - for (i = o->iptr; i; i = rc.rcnext) { - reffetch(i, &rc); - r = rc.rcref; - if (!r->robj) { - r->robj = (struct obj *) undefrefs; - if (undefpr & 1) puts("Undefined*"); - if (undefpr & 2) - fprintf(stderr, "undefined:\n"); - undefpr = 0; - if (undefprint & 1) puts(r->name); - if (undefprint & 2) - fprintf(stderr, "\t%s\n", r->name); - } - if (rc.rcnext >= nrefc) rc.rcnext -= nrefc; - } - } - if ((undefprint & 2) && !undefpr) exit(2); - } - return 0; - } - -indata(s,f,opn) -char *s; -void (*f)(); -int opn; -{ - char *s1 = s; - FILE *fopen(), *infile = 0; - char name[NBUFLEN]; - int c, opn1 = opn; - - if (s[0] == '@') { s1 = s + 1; opn1 = 1; } - if (opn1) { - if (strcmp(s1,"-")) { - infile = fopen(s1, "r"); - if (!infile) scream("cannot open %s\n", s1); - } - else { - infile = stdin; - if (s == s1) s = s1 = ""; - } - } - if (s == s1) (*f)(s,infile); - else { - do { - while((c = getc(infile)) <= ' ') if (c == EOF) goto eof; - s = name; - do *s++ = c; while((c = getc(infile)) > ' '); - *s = 0; - indata(name, f, opn); - } while (c != EOF); - } -eof: - if (infile) fclose(infile); - } - -genrl_in(infile) -FILE *infile; -{ - char name[100], *s; - int c; - - do { - - while((c = getc(infile)) <= ' ') if (c == EOF) return; - - s = name; - do *s++ = c; while((c = getc(infile)) > ' '); - *s = 0; - switch(*--s) { - - case '*': - *s = 0; - if (fullg) newgroup(name); - else newobj(name,1); - break; - - case '=': - *s = 0; - if (fullg) defobjref(name,merge); - else defref(name); - break; - - case ':': - *s = 0; - if (fullg) newobj(name,merge); - break; - - case '?': - *s = 0; - newref(name); - break; - - default: - defref(name); - } - } while (c != EOF); - } //GO.SYSIN DD bin/lo.src/lo.c echo bin/lo.src/makefile 1>&2 sed >bin/lo.src/makefile <<'//GO.SYSIN DD bin/lo.src/makefile' 's/^-//' -.SUFFIXES: .c .o -CFLAGS = -O -C = cc $(CFLAGS) -lo = lo.o subs.o refstore.o datard.o cmpout.o - -lo: $(lo) - $C -o lo $(lo) -subs.o: subs.c ts.h -refstore.o: refstore.c ts.h - -# To create a version that reads .o and .a files, -# uncomment the next two lines. -#datard.o: datard.c -# $C -c -DLibRead datard.c - -.c.o: - $C -c $*.c //GO.SYSIN DD bin/lo.src/makefile echo bin/lo.src/refstore.c 1>&2 sed >bin/lo.src/refstore.c <<'//GO.SYSIN DD bin/lo.src/refstore.c' 's/^-//' -/* On machines that address memory in segments, reffetch and refstore - * can be rewritten to save and store data in a different segment than - * the rest of the program uses. - */ - -#define XINC 8000 -#include "ts.h" - -static unsigned XMAX; -static struct refc *x; -char *malloc(), *realloc(); -static char toobig[] = "i too big in %s\n"; - -reffetch(i, rc) -unsigned i; -struct refc *rc; -{ - struct refc *xi; - - if (i >= XMAX) scream(toobig, "reffetch"); - xi = x + i; - rc->rcnext = xi->rcnext; - rc->rcref = xi->rcref; - } - -refstore(i, rc) -unsigned i; -struct refc *rc; -{ - struct refc *xi; - static char refst[] = "refstore"; - unsigned n; - - if (i >= XMAX) { - XMAX += XINC; - n = XMAX * sizeof(struct refc); - x = (struct refc *) (x ? realloc((char *)x, n) : malloc(n)); - if (!x) scream("not enough memory for %s!\n", refst); - } - if (i >= XMAX) scream(toobig, refst); - xi = x + i; - xi->rcnext = rc->rcnext; - xi->rcref = rc->rcref; - } //GO.SYSIN DD bin/lo.src/refstore.c echo bin/lo.src/subs.c 1>&2 sed >bin/lo.src/subs.c <<'//GO.SYSIN DD bin/lo.src/subs.c' 's/^-//' -#include -#include "ts.h" - -#ifdef MSDOS -#define HSIZE 307 -#define ALSIZE 2040 -#else -#define HSIZE 3203 -#define ALSIZE 20464 -#endif - -static struct obj **objhash, *cobj = 0, *lastobj; -static struct ref **refhash; -static struct group **grouphash, *group0; -struct ref *undefrefs = 0, *defedrefs = 0; -struct group *cgroup = 0; /* current group */ -struct obj *obj0 = 0; /* special null object */ - -unsigned lasthash = 0, ngroup = 0, nrefc = 0; -int nextseq; - -char *malloc(), *strcpy(); -extern char *progname; -extern int cyclep, verbose, verify; - -Init(){ - int i; - - objhash = (struct obj **) malloc(HSIZE*sizeof(struct obj *)); - refhash = (struct ref **) malloc(HSIZE*sizeof(struct ref *)); - grouphash = (struct group **) malloc(HSIZE*sizeof(struct group *)); - if (!objhash || !refhash || !grouphash) - scream("initial mallocs fail\n",""); - for (i = 0; i < HSIZE; i++) - { objhash[i] = 0; refhash[i] = 0; grouphash[i] = 0;} - cgroup = 0; - newgroup(""); - group0 = cgroup; - newobj("",1); - obj0 = cobj; - } - -unsigned -hash(s) -char *s; -{ - unsigned x = 0; - unsigned char c; - - while(c = (unsigned char)*s++) x = (x<<1) + c; - return x % HSIZE; - } - -char * -newstruct(n) -unsigned n; -{ - static char *next = 0, *last = 0; - char *s; - - if (next + n > last) { - next = malloc(ALSIZE); - if (!next) scream("malloc fails in newstruct\n",""); - last = next + ALSIZE; - } - s = next; - next += n; - return s; - } - -char * -newstring(s) -char *s; -{ - static char *next = 0, *last = 0; - char *s1; - unsigned n; - - n = (unsigned)strlen(s) + 1; - if (next + n > last) { - next = malloc(ALSIZE); - if (!next) scream("malloc fails in newstring\n",""); - last = next + ALSIZE; - } - s1 = next; - next += n; - strcpy(s1,s); - return s1; - } - -newgroup(s) -char *s; -{ - struct group *g, *gprev; - - cobj = 0; - gprev = (struct group *) &grouphash[hash(s)]; - g = gprev->next; - for(;; gprev = g, g = g->next) { - if (!g) { - g = (struct group *) - newstruct(sizeof(struct group)); - g->name = newstring(s); - g->next = 0; - g->gseq = ngroup++; - gprev->next = g; - break; - } - if (!strcmp(s,g->name)) break; - } - cgroup = g; - } - -struct ref * -lookup(s,add) -char *s; -int add; -{ - struct ref *h, *hprev; - - hprev = (struct ref *) &refhash[lasthash = hash(s)]; - h = hprev->next; - while(h) { - if (!strcmp(h->name,s)) return h; - hprev = h; - h = h->next; - } - if (add) { - h = (struct ref *) newstruct(sizeof(struct ref)); - hprev->next = h; - h->next = 0; - h->name = cobj && !strcmp(cobj->name,s) ? cobj->name : newstring(s); - h->robj = 0; - } - return h; - } - -newobj(s,dup) -char *s; -int dup; -{ - struct obj *h, *hnext = 0, *hprev, *o; - struct ref *r1; - - hprev = (struct obj *) &objhash[hash(s)]; - h = hprev->next; - while(h) { - if (!strcmp(h->name,s) && h->ogroup == cgroup) { - if (dup || h == obj0) { cobj = h; return; } - if (verbose) { - fprintf(stderr, "duplicate %s", s); - if (*cgroup->name) fprintf(stderr, " in %s", cgroup->name); - fprintf(stderr, " ignored\n"); - } - cobj = 0; - return; - } - hprev = h; - h = h->next; - } - cobj = o = (struct obj *) newstruct(sizeof(struct obj)); - hprev->next = o; - o->next = hnext; - r1 = lookup(s,0); - o->name = r1 ? r1->name : newstring(s); - o->ogroup = cgroup; - o->seq = o->iptr = o->jct = 0; - } - -defobjref(s,dup) -char *s; -int dup; -{ - rdefobjref(lookup(s,1), s, dup); - } - -rdefobjref(r,s,dup) -struct ref *r; -char *s; -int dup; -{ - struct obj *o; - - if (o = r->robj) { - newobj(s,dup); - if (!dup || o->ogroup != cgroup) dupmsg(0,r,s); - } - else { - r->robj = cobj = o = (struct obj *) newstruct(sizeof(struct obj)); - o->next = objhash[lasthash]; - objhash[lasthash] = o; - o->name = r->name; - o->ogroup = cgroup; - o->seq = o->iptr = o->jct = 0; - } - } - -dupmsg(oprt,r,s) -int oprt; -struct ref *r; -char *s; -{ - struct obj *o = r->robj; - char *in; - - if (verbose && o != obj0) { - fprintf(stderr, "def of %s", s); - if (oprt && strcmp(s,cobj->name)) { - fprintf(stderr, " in %s", cobj->name); - in = "of"; - } - else in = "in"; - if (*cgroup->name) fprintf(stderr, " %s lib %s", in, cgroup->name); - s = o->ogroup->name; - fprintf(stderr, *s ? "%s%s of lib %s\n" : "%s%s\n", - " ignored; first defined in ", o->name, s); - } - } - - -newref(s) -char *s; -{ newrefr(lookup(s,1)); } - -newrefr(r) -struct ref *r; -{ - struct refc rc; - struct obj *o1; - unsigned i; - - if (!cobj) return; - if (verify && r->robj && cobj != obj0) { - fprintf(stderr, "%s", cobj->name); - if (cgroup != group0) fprintf(stderr, " of %s", cgroup->name); - fprintf(stderr, " needs %s\n", r->name); - } - rc.rcnext = cobj->iptr; - rc.rcref = r; - o1 = rc.rcref->robj; - if (o1 != cobj && o1 != obj0) { - /* discard self references */ - /* and refs to null object */ - i = cobj->iptr = ++nrefc; - refstore(i, &rc); - } - } - -defref(s) -char *s; -{ defrefr(lookup(s,1), s); } - -defrefr(r,s) -struct ref *r; -char *s; -{ - if (!cobj) return; - if (r->robj) dupmsg(1,r,s); - else r->robj = cobj; - } - -struct obj * -ts0() -{ - int i; - struct obj *firstobj, *o, *onext; - struct ref *r, *rnext; - - /* chain objects together */ - - firstobj = 0; - for (i = 0; i < HSIZE; i++) { - for(o = objhash[i]; o; o = onext) { - onext = o->next; - o->next = firstobj; - firstobj = o; - } - } - - /* chain undefined refs together */ - - defedrefs = undefrefs = 0; - for (i = 0; i < HSIZE; i++) { - for (r = refhash[i]; r; r = rnext) { - rnext = r->next; - if (!r->robj) { r->next = undefrefs; undefrefs = r; } - else { r->next = defedrefs; defedrefs = r; } - } - refhash[i] = 0; - } - - free((char *) grouphash); - free((char *) refhash); - free((char *) objhash); - return firstobj; - } - -struct obj * -ts1(all) -{ - int i, i0, k; - unsigned j; - struct obj *firstobj, *o, *o1, *onext, *oprev, **ready, **rs; - struct refc rc; - - firstobj = ts0(); - - /* do depth-first search (to break cycles) */ - - nextseq = 1; - for (o = firstobj; o; o = o->next) - if (!o->seq && (all || o->ogroup == group0)) dfs(1,o); - - /* discard unreached objects */ - - if (!all) { - oprev = (struct obj *) &firstobj; - for (o = firstobj; o; o = o->next) - if (o->seq) { oprev->next = o; oprev = o; } - oprev->next = 0; - } - - /* set up for funny breadth-first search */ - - ready = (struct obj **) malloc(ngroup * sizeof(struct obj *)); - if (!ready) scream("malloc of ready list fails\n",""); - - obj0->jct = 0; /* force initial inclusion of obj0 */ - for (i = 0; i < ngroup; i++) ready[i] = 0; - for (o = firstobj; o; o = onext) { - onext = o->next; - if (!o->jct) { - rs = ready + o->ogroup->gseq; - o->next = *rs; - *rs = o; - } - } - firstobj = lastobj = 0; - i = i0 = 0; - for(;;) { - if (!(o = ready[i])) { - i = i0; - while(!(o = ready[i])) - if (++i >= ngroup) { - if (lastobj) lastobj->next = 0; - return firstobj; - } - i0 = i; - } - ready[i] = o->next; - if (!lastobj) firstobj = o; - else lastobj->next = o; - lastobj = o; - for (j = o->iptr; j; ) { - reffetch(j, &rc); - j = rc.rcnext; - if (j >= nrefc) { j -= nrefc; continue; } - o1 = rc.rcref->robj; - if (!o1) continue; - if (!--o1->jct) { - k = o1->ogroup->gseq; - o1->next = ready[k]; - ready[k] = o1; - if (i0 > k) i0 = k; - } - } - } - } - -dfs(level, o) -int level; -struct obj *o; -{ - struct refc rc; - struct obj *o1; - struct group *og; - int level0, s; - static int cycle = 0; - unsigned i, nextrc; - - o->seq = -level; - level0 = -(level + 1); - for (i = o->iptr; i; i = nextrc) { - reffetch(i, &rc); - nextrc = rc.rcnext; - o1 = rc.rcref->robj; - if (!o1 || o == o1 || o1 == obj0) continue; - s = o1->seq; - if (s >= 0) { - o1->jct++; - if (s > 0) continue; /* cross link */ - s = dfs(level+1, o1); - } - else { /* back link */ - if (cyclep && !cycle) { - fprintf(stderr, "%s: cycle...\n", progname); - cycle = 1; - } - rc.rcnext += nrefc; - refstore(i, &rc); - } - if (level0 < s) level0 = s; - } - o->seq = nextseq; - level = -level; - if (level <= level0 && cyclep) { - og = o->ogroup; - fprintf(stderr, og == group0 ? "%s\n" : "%s in %s\n", - o->name, og->name); - if (level == level0) { cycle = 0; putc('\n',stderr); } - else cycle = 1; - } - if (level > level0 || level == -1) { nextseq++; level0 = level; } - return level0; - } - -scream(s, s1) -char *s, *s1; -{ - fprintf(stderr, "%s: ", progname); - fprintf(stderr, s, s1); - exit(1); - } - -void -undef(s,infile) -char *s; -FILE *infile; -{ - newgroup(""); - newobj("", 1); - newref(s); - } //GO.SYSIN DD bin/lo.src/subs.c echo bin/lo.src/ts.h 1>&2 sed >bin/lo.src/ts.h <<'//GO.SYSIN DD bin/lo.src/ts.h' 's/^-//' -#ifndef TS_Include -#define TS_Include -#define NBUFLEN 132 - -struct obj { - struct obj *next; - char *name; - struct group *ogroup; - unsigned iptr, jct; - int seq; - }; - -struct obj1 { - struct obj1 *next; - char *name; - struct group *ogroup; - unsigned iptr; - struct ref *nextref; - }; - -struct ref { - struct ref *next; - char *name; - struct obj *robj; - }; - -struct refc { - unsigned rcnext; - struct ref *rcref; - }; - -struct group { - struct group *next; - char *name; - unsigned gseq; - }; -#endif //GO.SYSIN DD bin/lo.src/ts.h .