# to unbundle, sh this file (in an empty directory) echo COPYRIGHT 1>&2 sed >COPYRIGHT <<'-------cut here----- COPYRIGHT' 's/^X//' X/* X * The author of this software is Eric Grosse . X * Copyright (c) 1996 by Bell Laboratories, Lucent Technologies. X * Permission to use, copy, modify, and distribute this software for any X * purpose without fee is hereby granted, provided that this entire notice X * is included in all copies of any software which is or includes a copy X * or modification of this software and in all copies of the supporting X * documentation for such software. X * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED X * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY X * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY X * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. X */ X -------cut here----- COPYRIGHT echo Depend 1>&2 sed >Depend <<'-------cut here----- Depend' 's/^X//' X#!/bin/sh Xcase $1 in X X X-c) # creates ".depend" file for local directory, of the form X # F file.c X # D entrypoint1 X # R external1 X # R external2 X > .depend X for FILE in *.[cefr];do X echo "F $FILE" X OBJ=`echo $FILE|sed 's/\..$/.o/'` X make $OBJ 1>&2 X nm $OBJ | # the following works for SGI IRIX 5.1.1 X sed -n 's/^[^|]*|[^|]*|[^|]*|// X /|ref=[0-9]* *|Text/d X s/^Proc *| *|Undefined|/R/p X s/^Proc *|end.*|Text *|/D/p' | X skip_posix | sort -u X rm $OBJ X sed -n 's/^#[ ]*include[ ]*"\(.*\)" *$/R \1/p' $FILE X echo "" X done >> .depend X ls *.h* 2>/dev/null | X while read FILE;do echo "F $FILE";echo "";done >> .depend X ;; X X-t) # prints filenames covering routines in $* for libraries in $LIBS X shift # get rid of -t X case $* in X all) # *** return all files *** X for i in $LIBS;do X sed -n 's;^F ;'$i'/;p' $i/.depend X done | tr '\012' ' ' X echo;; X *) # ***cat .depend files for all LIBS, then search *** X # subtlety: have to add dir to F, hence make D explicit first. X U= X for i in $*; do U="$U $i $i"_; done X (for i in $LIBS; do X (cd $i X if test -r .depend; then X sed 's;^F \(.*\);F '$i'/\1\ XD \1; X s;^R \([^/]*\)\.h$;R '$i'/\1.h;' .depend X else X ls | sed '/index/d X /readme/d X /disclaimer/d X /depend/d X s;^;F '$i'/;' X fi) X done) | getdepend $U | tr '\012' ' ' X echo;; X esac X ;; X X-d) echo 'digraph G {' X grep -v '^[DR].*\.h$' .depend | depend2dot | sort -u X echo '}';; X X*) echo $0 -c ... to build .depend file for local directory X echo 'LIBS={directories} $0 -t {symbols} ... for transitive closure' X echo $0 -d ... to create input for dot X exit 1 X ;; X Xesac Xexit 0 -------cut here----- Depend chmod +x Depend echo Makefile 1>&2 sed >Makefile <<'-------cut here----- Makefile' 's/^X//' Xgetdepend: getdepend.c Malloc.c hash.c X cc -s -o getdepend -O getdepend.c Malloc.c hash.c X Xclean: X rm -f *.o *.x retadd nreply core X -------cut here----- Makefile echo Malloc.c 1>&2 sed >Malloc.c <<'-------cut here----- Malloc.c' 's/^X//' X#include X#include X#include X#include X#include "depend.h" X Xint Error_rc = 1; /* rarely, caller of Error() may want to set this */ Xextern int errno; X Xint XError(char *fmt, ...) X{ X va_list ap; X va_start(ap,fmt); X if(vfprintf(stderr,fmt,ap)<0) X fprintf(stderr,""); X fputc('\n',stderr); X va_end(ap); X if(errno) perror("<"); /* may or may not be relevant */ X exit(Error_rc); X /* NOTREACHED */ X return(0); /* so caller can use crunch() || Error("bad"); */ X} X Xvoid * XMalloc(size_t n) X{ X void *p; X if(n==0) X n=1; X if (!(p = malloc((size_t)n))) X Error("unable to allocate %d bytes",n); X return p; X} X Xvoid * XRealloc(void *ReallocP, int ReallocN) X{ X if(ReallocN == 0) X ReallocN = 1; X if(!ReallocP) X ReallocP = Malloc(ReallocN); X else if(!(ReallocP = realloc(ReallocP, ReallocN))) X Error("unable to allocate %d bytes",ReallocN); X return(ReallocP); X} X Xchar* XStrdup(char* s) X{ X int l; X if (!s) X return 0; X l = strlen(s)+1; X return strcpy((char *)Malloc((size_t)l), s); X} X X/* returns pointer to start of null-terminated line, or NULL if EOF */ Xchar* XFgets(char* buf, int bufl, FILE* fp) X{ X char* s; X int l; X X s = fgets(buf, bufl, fp); X if (s==NULL) X return NULL; X if (ferror(fp)) X Error("read error"); X l = strlen(buf)-1; X if (buf[l] == '\n') X buf[l] = '\0'; X else if (l == bufl) X Error("line longer than %d characters", bufl); X return s; X} X -------cut here----- Malloc.c echo depend.h 1>&2 sed >depend.h <<'-------cut here----- depend.h' 's/^X//' Xstruct HashEntry {char* Key; int Code;}; Xtypedef struct HashEntry *HashTable; Xextern char* Fgets(char*,int,FILE*); Xextern void hashdel(HashTable*,int); Xextern int hashins(HashTable*,int,char*,int); Xextern int hashasu(char*,int); Xextern int hashpjw(char*,int); Xextern int hashsrch(HashTable*,char*); Xextern void* Malloc(size_t); Xextern void* Realloc(void*,int); Xextern char* Strdup(char*); -------cut here----- depend.h echo getdepend.c 1>&2 sed >getdepend.c <<'-------cut here----- getdepend.c' 's/^X//' X/* read .depend file, compute transitive closure for request */ X/* Eric Grosse 9 Dec 1993; cleaned for export 21 Mar 1994 */ X X/* This reads from stdin a .depend file and builds 1) an array of Xfiles, each with a list of symbols referenced, and 2) a hash table Xmapping defined symbols into files. Now, to compute the transitive Xclosure of a list of symbols given as arguments on the command line, Xkeep a stack of symbols yet to be resolved, a stack of files yet to be Xexpanded, and a list of files processed. */ X X#include X#include X#include "depend.h" X Xtypedef struct{ X char *name; X char **ref; /* array of symbols referenced by this file */ X int nref; X int done; /* has this already been added to hit? */ X} File; X Xtypedef struct{ X File *file; X int nfile; X HashTable Def; /* symbol -> index of file defining it */ X} Dependencies; X Xstatic void Xsave_refs(File *f, int nref, char **ref) X{ X f->ref = (char**)Malloc(nref*sizeof(*f->ref)); X memcpy(f->ref,ref,nref*sizeof(*f->ref)); X f->nref = nref; X} X Xvoid Xgetdepend(Dependencies *d) X{ X int i; /* HashTable index */ X int nf = 0; /* index of file being read */ X int maxf = 1000; /* guess at an upper bound for nf */ X int nref, maxref = 5000; /* guess at an upper bound for nref */ X int linelen; X char *name; X char line[1000]; /* surely 100 would be enough, but what the heck */ X char **ref = Malloc(maxref*sizeof(*ref)); X File *f = Malloc(maxf*sizeof(*f)); X HashTable D = 0; X X while(Fgets(line,sizeof(line),stdin)!=NULL){ X if(line[0]==0 || line[0]=='#') continue; X linelen = strlen(line); X if(line[linelen-1]=='\n') X line[--linelen] = '\0'; X name = Strdup(line+2); X switch(line[0]){ X case 'F': X if(nf>0) X save_refs(&f[nf],nref,ref); X nref = 0; X nf++; X if(nf>=maxf){ X maxf *= 2; X f=Realloc(f,maxf*sizeof(*f)); X } X f[nf].name = name; X f[nf].done = 0; X /* FALL THROUGH (file implicitly defines own name) */ X case 'D': i = hashsrch(&D,name); X if(i<0) hashins(&D,i,name,nf); X break; X case 'R': X nref++; X if(nref>=maxref){ X maxref *= 2; X ref=Realloc(ref,maxref*sizeof(*ref)); X } X ref[nref-1] = name; X break; X /* ignore other lines */ X } X } X if(nf>0 && nref>0) X save_refs(&f[nf],nref,ref); X free(ref); X d->file = f; X d->nfile = nf; X d->Def = D; X} X X X X Xtypedef struct{ X char **p; X int np, maxp; X} stack; X Xstatic void Xnew_stack(stack *s) X{ X s->maxp = 1000; X s->p = (char**)Malloc(s->maxp*sizeof(char*)); X s->np = 0; X} X Xstatic void Xpush(char *p, stack *s) X{ X if(s->np==s->maxp){ X s->maxp *= 2; X s->p = (char**)Realloc(s->p,s->maxp*sizeof(char*)); X } X s->p[s->np++] = p; X} X Xstatic char* Xpop(stack *s) X{ X if(s->np==0) return 0; X return(s->p[--s->np]); X} X X X Xstatic void Xresolve(Dependencies *d, stack *hit, stack *need) X{ X int i, k; X char *r; X File *f; X X while(r = pop(need)){ X i = hashsrch(&d->Def,r); X if(i>0){ X f = &d->file[d->Def[i].Code]; X if(!f->done){ X f->done = 1; X push(f->name,hit); X for(k = 0; knref; k++) X push(f->ref[k],need); X } X } /* else unsatisfied external */ X } X} X Xstatic int Xcmp(const void*a, const void*b) X{ X return(strcmp(*(char **)a,*(char **)b)); X} X Xvoid Xmain(int argc, char**argv) X{ X Dependencies D; X stack hit, need; X int i; X X new_stack(&hit); X new_stack(&need); X while(argc>1) X push(argv[--argc],&need); X getdepend(&D); X resolve(&D,&hit,&need); X /* hit isn't really a stack; now we prove it. */ X qsort(hit.p,hit.np,sizeof(char*),cmp); X for(i = 0; i&2 sed >hash.c <<'-------cut here----- hash.c' 's/^X//' X/* version with Brent reorganization. Eric Grosse */ X/* see Gonnet and Baeza-Yates, Handbook of Algorithms and Data Structures, 1991, p.63 */ X X/* XLet {\tt char* s} be a key, Xlet {\tt int c} be a value to be associated with {\tt s}, Xlet {\tt HashTable H=0} be a symbol table, Xand let {\tt int i=hashsrch(\&H,s)}. XIf {\tt i<0}, then {\tt s}$\not\in${\tt H}, and the pair $(s,c)$ Xmay be inserted by X{\tt hashins(\&H,i,Strdup(s),c)}. XOtherwise, {\tt s}$\in${\tt H} and Xthe associated value is {\tt H[i].Code}. XThe pair may be removed by {\tt hashdel(\&H,i)}. XUse {\tt free(H)} to release the space allocated for {\tt H} Xitself; this does not free the individual keys. XThe implementation uses open hashing, allocating a larger table Xand rehashing when too many collisions occur. X*/ X X#include X#include X#include "depend.h" X X#define LENGTH (H[0].Code) X#define DEAD ((char*)H) X/* H[0] just holds the length n. The hash table proper is H[1],...,H[n]. */ X Xint Xhashpjw(char* key, int n) X{ X unsigned int g, h = 0; X while((unsigned char)*key!=0){ X h = (h<<4)+(unsigned char)*key++; X if(g = h&15<<28){ X h = h^g>>28; X h = h^g; X } X } X return h%n; X} X Xint Xhashasu(char* key, int n) X{ X unsigned int h = 0; X while((unsigned char)*key!=0) X h = 65599*h+(unsigned char)*key++; X return h%n; X} X Xstatic int Xrehash(HashTable*Hp) X{ X int i, j; X char* key; X static int level; /* don't rehash in the middle of a rehash */ X int m; /* m and m-2 must both be prime! */ X HashTable N, H = *Hp; X int n; X X if(!H){ X n = 211; X *Hp = H = (struct HashEntry*)Malloc((n+1)*sizeof(*H)); X LENGTH = n; X for(j=1;j<=n;j++) X H[j].Key = 0; X level = 0; X return(1); X } X level++==0 || Error("rehash: recursive rehash"); /* maybe return(0)? */ X n = LENGTH; X if(n == 211) { m = 1019; X } else if(n == 1019) { m = 5099; X } else if(n == 5099) { m = 25033; X } else if(n == 25033) { m = 100153; X } else if(n == 100153) { m = 500809; X } else if(n == 500809) { m = 2503183; X } else { m = 5007181; Error("HashTable overflowed"); X } X N = (struct HashEntry*)Malloc((m+1)*sizeof(*N)); X N[0].Code = m; /* LENGTH */ X for(j=1;j<=m;j++) X N[j].Key = 0; X for(i = 1; i <= n; i += 1 ) { X if((key = H[i].Key)!=0 && key!=DEAD) { X j = hashsrch(&N, key); X j<0 || Error("%s already in N in rehash!?",key); X hashins(&N, j, key, H[i].Code); X } X } X free(H); X *Hp = N; X level -= 1; X return(1); X} X Xint Xhashsrch(HashTable*Hp, char* key) X{ X int i, inc, last, m; X char *HiKey; X HashTable H = *Hp; X X key || Error("hashsrch: null key"); X H || rehash(Hp); H = *Hp; X m = LENGTH; X i = hashpjw(key,m)+1; X HiKey = H[i].Key; X if(HiKey==0) X return(-i); X if(HiKey!=DEAD && HiKey[0]==key[0] && strcmp(HiKey+1,key+1)==0) X return(i); X inc = hashasu(key,m-2)+1; X last = (i-1+(m-1)*inc)%m+1; X while(1){ X i = (i-1+inc)%m+1; X if(i==last) return(-i); X HiKey = H[i].Key; X if(HiKey==0) return(-i); X if(HiKey==DEAD) continue; X if(HiKey[0]==key[0] && strcmp(HiKey+1,key+1)==0) return(i); X } X} X Xint Xhashins(HashTable*Hp, int j, char* key, int code) X{ X HashTable H = *Hp; X int init, inc, i, ii, jj, m = LENGTH; X char *HiKey; X X j<0 || Error("hashins: Insert should follow unsuccessful Search"); X /* search anyway, in case we can fill a DEAD slot */ X X init = hashpjw(key,m)+1; X HiKey = H[init].Key; X if( HiKey==0 || HiKey==DEAD){ X H[init].Key = key; X H[init].Code = code; X return(init); X } X X inc = hashasu(key,m-2)+1; /* n-2 so probe offset is not zero */ X for(i = 1; i=0; j--){ X jj = (init-1+inc*j)%m + 1; X ii = (jj-1+(hashasu(H[jj].Key,m-2)+1)*(i-j))%m+1; X if(H[ii].Key==0 || H[ii].Key==DEAD){ /* move record forward */ X H[ii].Key = H[jj].Key; H[ii].Code = H[jj].Code; X H[jj].Key = key; H[jj].Code = code; X goto finish; X } X } X } X finish: X /* if there were a lot of probes, rehash to speed future searches */ X if((j>=5||(i-j)>5)&&m<1020 || (j>9||(i-j)>9)&&m<2500000){ X rehash(Hp) || Error("hashsrch: new algorithm needed!"); H = *Hp; X jj = hashsrch(&H,key); X jj>0 || Error("hashins:can't"); X } X return(jj); X} X Xvoid Xhashdel(HashTable*Hp, int j) X{ X HashTable H = *Hp; X j>0 || Error("hashdel must follow successful Search"); X H[j].Key = DEAD; X} X X -------cut here----- hash.c echo skip_posix 1>&2 sed >skip_posix <<'-------cut here----- skip_posix' 's/^X//' Xsed '/^R _/d X/^R assert.h$/d X/^R ctype.h$/d X/^R fcntl.h$/d X/^R float.h$/d X/^R grp.h$/d X/^R limits.h$/d X/^R locale.h$/d X/^R math.h$/d X/^R pwd.h$/d X/^R setjmp.h$/d X/^R signal.h$/d X/^R stdarg.h$/d X/^R stddef.h$/d X/^R stdio.h$/d X/^R stdlib.h$/d X/^R string.h$/d X/^R sys\/times.h$/d X/^R sys\/types.h$/d X/^R sys\/utsname.h$/d X/^R sys\/wait.h$/d X/^R time.h$/d X/^R unistd.h$/d X/^R utime.h$/d X/^R abs$/d X/^R acos$/d X/^R alarm$/d X/^R asctime$/d X/^R asin$/d X/^R atan$/d X/^R atan2$/d X/^R atexit$/d X/^R atof$/d X/^R atoi$/d X/^R atol$/d X/^R bsearch$/d X/^R ceil$/d X/^R chdir$/d X/^R chmod$/d X/^R clearerr$/d X/^R clock$/d X/^R close$/d X/^R closedir$/d X/^R cos$/d X/^R cosh$/d X/^R ctermid$/d X/^R cuserid$/d X/^R difftime$/d X/^R dup$/d X/^R exit$/d X/^R exp$/d X/^R fabs$/d X/^R fclose$/d X/^R fdopen$/d X/^R feof$/d X/^R ferror$/d X/^R fflush$/d X/^R fgetc$/d X/^R fgets$/d X/^R fileno$/d X/^R floor$/d X/^R fmod$/d X/^R fopen$/d X/^R fprintf$/d X/^R fputc$/d X/^R fputs$/d X/^R fread$/d X/^R free$/d X/^R freopen$/d X/^R fscanf$/d X/^R fseek$/d X/^R fstat$/d X/^R ftell$/d X/^R fwrite$/d X/^R getc$/d X/^R getchar$/d X/^R getenv$/d X/^R getopt$/d X/^R getpid$/d X/^R gets$/d X/^R gmtime$/d X/^R isdigit$/d X/^R isspace$/d X/^R isupper$/d X/^R labs$/d X/^R localtime$/d X/^R log$/d X/^R log10$/d X/^R lseek$/d X/^R malloc$/d X/^R memcpy$/d X/^R memmove$/d X/^R memset$/d X/^R mkdir$/d X/^R mkfifo$/d X/^R mknod$/d X/^R mktime$/d X/^R modf$/d X/^R opendir$/d X/^R pause$/d X/^R pclose$/d X/^R perror$/d X/^R pipe$/d X/^R popen$/d X/^R pow$/d X/^R printf$/d X/^R putc$/d X/^R putchar$/d X/^R puts$/d X/^R qsort$/d X/^R read$/d X/^R readdir$/d X/^R realloc$/d X/^R remove$/d X/^R rename$/d X/^R rewind$/d X/^R rewinddir$/d X/^R scanf$/d X/^R seekdir$/d X/^R setbuf$/d X/^R setvbuf$/d X/^R sin$/d X/^R sinh$/d X/^R sleep$/d X/^R sprintf$/d X/^R sqrt$/d X/^R sscanf$/d X/^R strcat$/d X/^R strchr$/d X/^R strcmp$/d X/^R strcpy$/d X/^R strftime$/d X/^R strlen$/d X/^R strncmp$/d X/^R strrchr$/d X/^R strtod$/d X/^R system$/d X/^R tan$/d X/^R tanh$/d X/^R telldir$/d X/^R time$/d X/^R tmpfile$/d X/^R tmpnam$/d X/^R tolower$/d X/^R tzset$/d X/^R umask$/d X/^R ungetc$/d X/^R utime$/d X/^R vfprintf$/d X/^R vprintf$/d X/^R vsprintf$/d X/^R write$/d' -------cut here----- skip_posix chmod +x skip_posix .