1*12913Sgarrison # 2*12913Sgarrison #ifndef lint 3*12913Sgarrison static char sccsid[] = "@(#)locate.c 1.1 06/06/83"; 4*12913Sgarrison #endif lint 5*12913Sgarrison 6*12913Sgarrison # include "stdio.h" 7*12913Sgarrison # include "streams.h" 8*12913Sgarrison # include "ctype.h" 9*12913Sgarrison # define maxrefs 200 10*12913Sgarrison 11*12913Sgarrison struct reftype{ 12*12913Sgarrison char reffile[64]; /* rrh: still may be too short */ 13*12913Sgarrison long int start, length; 14*12913Sgarrison }; 15*12913Sgarrison 16*12913Sgarrison char *malloc(); 17*12913Sgarrison char *rindex(); 18*12913Sgarrison char *stripkeys(); 19*12913Sgarrison int fetchref(); 20*12913Sgarrison int fileflag; 21*12913Sgarrison 22*12913Sgarrison /* locate(keys, name, max_klen, common): 23*12913Sgarrison Returns a string containing all references pointed to by name 24*12913Sgarrison that contain all keys in keys. Common is name of common word file. 25*12913Sgarrison Pointer returned comes from malloc. Use free to return storage. 26*12913Sgarrison NB A zero length string returned if nothing is found. 27*12913Sgarrison A NULL pointer indicates an error accessing the file "name". 28*12913Sgarrison */ 29*12913Sgarrison char *locate(keys,name,max_klen,common) 30*12913Sgarrison char *keys, *name, *common; 31*12913Sgarrison int max_klen; /* max key length */ 32*12913Sgarrison { static char oldname[maxstr] = ""; /* oldname is name of stream index */ 33*12913Sgarrison static FILE *index = NULL; 34*12913Sgarrison static long int i_size; /* size of index */ 35*12913Sgarrison static char oldtext[maxstr]; /* oldtext is the path to stream */ 36*12913Sgarrison static char workbuf[10240]; /* work buffer */ 37*12913Sgarrison static FILE *text = NULL; /* text. if it is a relative */ 38*12913Sgarrison static int pathlen; /* path, it is relative to index */ 39*12913Sgarrison /* directory. */ 40*12913Sgarrison /* oldname[0..pathlen-1] is index */ 41*12913Sgarrison /* directory */ 42*12913Sgarrison int len; 43*12913Sgarrison char key[maxstr]; /* refs[i] is a line of index for */ 44*12913Sgarrison struct reftype refs[maxrefs]; /* all keys up to key */ 45*12913Sgarrison 46*12913Sgarrison int refcnt, copied, comp; /* refcnt = # of refs */ 47*12913Sgarrison /* copied = # of refs copied */ 48*12913Sgarrison /* comp = # of refs compared */ 49*12913Sgarrison struct reftype ref; 50*12913Sgarrison char str[maxstr]; 51*12913Sgarrison int more; 52*12913Sgarrison 53*12913Sgarrison long int ans; 54*12913Sgarrison int i,j; 55*12913Sgarrison unsigned total; 56*12913Sgarrison char *allrefs, *next; /* all refs (separated by null line)*/ 57*12913Sgarrison char *p; 58*12913Sgarrison 59*12913Sgarrison /* open index */ 60*12913Sgarrison if (strcmp(oldname,name)!=0) 61*12913Sgarrison { if (index) fclose(index); 62*12913Sgarrison if (text) fclose(text); 63*12913Sgarrison strcpy(oldname,name); 64*12913Sgarrison strcpy(oldtext,""); 65*12913Sgarrison /* determine pathlen */ 66*12913Sgarrison p= rindex(oldname, '/'); 67*12913Sgarrison if (p!=NULL) pathlen= p-oldname+1; 68*12913Sgarrison else pathlen= 0; 69*12913Sgarrison 70*12913Sgarrison index= fopen(oldname,"r"); 71*12913Sgarrison if (index==NULL) 72*12913Sgarrison { fprintf(stderr, "locate: cannot open %s\n", oldname); 73*12913Sgarrison strcpy(oldname, ""); 74*12913Sgarrison return(NULL); 75*12913Sgarrison } 76*12913Sgarrison else 77*12913Sgarrison { fseek(index,0L,2); /* seeks last newline */ 78*12913Sgarrison i_size= ftell(index); 79*12913Sgarrison } 80*12913Sgarrison 81*12913Sgarrison } 82*12913Sgarrison 83*12913Sgarrison /* load references to first key */ 84*12913Sgarrison keys= stripkeys(keys,key, max_klen, common); 85*12913Sgarrison if (*key==NULL) 86*12913Sgarrison { fprintf(stderr,"locate: no keys for citation\n"); 87*12913Sgarrison allrefs = malloc(1); 88*12913Sgarrison if (allrefs==NULL) 89*12913Sgarrison { fprintf(stderr, 90*12913Sgarrison "locate: insufficient space for references\n"); 91*12913Sgarrison exit(1); 92*12913Sgarrison } 93*12913Sgarrison *allrefs= NULL; 94*12913Sgarrison return(allrefs); 95*12913Sgarrison } 96*12913Sgarrison len= strlen(key); 97*12913Sgarrison strcat(key," "); 98*12913Sgarrison alpha_seek(index, key, i_size, 0); 99*12913Sgarrison key[len]= NULL; /* strip blank off */ 100*12913Sgarrison 101*12913Sgarrison refcnt= 0; 102*12913Sgarrison fscanf(index,"%s ", str); 103*12913Sgarrison if (strcmp(str,key) == 0) 104*12913Sgarrison { str[0]= NULL; 105*12913Sgarrison while (refcnt < maxrefs && fetchref(index, str, &ref) ) 106*12913Sgarrison { refs[refcnt]= ref; 107*12913Sgarrison refcnt++; 108*12913Sgarrison } 109*12913Sgarrison } 110*12913Sgarrison 111*12913Sgarrison if (refcnt==maxrefs) 112*12913Sgarrison fprintf(stderr, 113*12913Sgarrison "locate: first key (%s) matched too many refs\n", key); 114*12913Sgarrison 115*12913Sgarrison /* intersect the reference sets for remaining keys with first set */ 116*12913Sgarrison while (*keys!=NULL) 117*12913Sgarrison { keys= stripkeys(keys, key, max_klen, common); 118*12913Sgarrison if (*key==NULL) continue; 119*12913Sgarrison 120*12913Sgarrison len= strlen(key); 121*12913Sgarrison strcat(key," "); 122*12913Sgarrison alpha_seek(index, key, i_size, 0); 123*12913Sgarrison key[len]= NULL; 124*12913Sgarrison 125*12913Sgarrison fscanf(index,"%s ", str); 126*12913Sgarrison if (strcmp(str,key) != 0) refcnt= 0; /* no matching refs */ 127*12913Sgarrison 128*12913Sgarrison copied= 0; comp= 0; more= fetchref(index, str, &ref); 129*12913Sgarrison while (comp < refcnt && more) 130*12913Sgarrison { /* ans= ref-refs[comp] */ 131*12913Sgarrison ans= strcmp(ref.reffile, refs[comp].reffile); 132*12913Sgarrison if (ans==0) ans= ref.start-refs[comp].start; 133*12913Sgarrison if (ans==0) ans= ref.length-refs[comp].length; 134*12913Sgarrison if (ans<0) more= fetchref(index, str, &ref); 135*12913Sgarrison if (ans==0) { refs[copied]= refs[comp]; comp++; copied++; 136*12913Sgarrison more= fetchref(index, str, &ref);} 137*12913Sgarrison if (ans>0) comp++; 138*12913Sgarrison } 139*12913Sgarrison 140*12913Sgarrison refcnt= copied; 141*12913Sgarrison } 142*12913Sgarrison 143*12913Sgarrison /* copy refs into the work buffer */ 144*12913Sgarrison next= workbuf; 145*12913Sgarrison for (i=0; i<refcnt; i++) 146*12913Sgarrison { /* open text */ 147*12913Sgarrison if (strcmp(oldtext,refs[i].reffile) != 0) 148*12913Sgarrison { strcpy(oldtext,refs[i].reffile); 149*12913Sgarrison if (oldtext[0]=='/') 150*12913Sgarrison { /* absolute path */ 151*12913Sgarrison strcpy(str,oldtext); 152*12913Sgarrison } else 153*12913Sgarrison { /* relative name */ 154*12913Sgarrison strncpy(str, oldname, pathlen); str[pathlen]= NULL; 155*12913Sgarrison strcat(str, oldtext); 156*12913Sgarrison } 157*12913Sgarrison if (text) fclose(text); 158*12913Sgarrison text= fopen(str, "r"); 159*12913Sgarrison if (text==NULL) 160*12913Sgarrison { fprintf(stderr, "locate: cannot open %s\n", str); 161*12913Sgarrison strcpy(oldtext, ""); 162*12913Sgarrison return(NULL); 163*12913Sgarrison } 164*12913Sgarrison } 165*12913Sgarrison fseek(text, refs[i].start, 0); 166*12913Sgarrison { 167*12913Sgarrison register char *from; 168*12913Sgarrison if (fileflag){ 169*12913Sgarrison from = oldtext; 170*12913Sgarrison while(*next++ = *from++) /*VOID*/ ; 171*12913Sgarrison next[-1] = '\n'; 172*12913Sgarrison } 173*12913Sgarrison } 174*12913Sgarrison for (j=0; j<refs[i].length; j++) *next++ = getc(text); 175*12913Sgarrison *next++ = '\n'; 176*12913Sgarrison } 177*12913Sgarrison *next = NULL; 178*12913Sgarrison allrefs = malloc(strlen(workbuf) + 1); 179*12913Sgarrison if (allrefs == NULL) { 180*12913Sgarrison fprintf(stderr, "No space left for allrefs\n"); 181*12913Sgarrison exit(1); 182*12913Sgarrison } 183*12913Sgarrison strcpy(allrefs, workbuf); 184*12913Sgarrison return(allrefs); 185*12913Sgarrison } 186*12913Sgarrison 187*12913Sgarrison 188*12913Sgarrison 189*12913Sgarrison /* stripkeys(line,key,max_klen, common): 190*12913Sgarrison assigns to key the first key in line 191*12913Sgarrison and returns a pointer to the position following the key 192*12913Sgarrison */ 193*12913Sgarrison char *stripkeys(line,key,max_klen,common) 194*12913Sgarrison char *line, *key; 195*12913Sgarrison int max_klen; 196*12913Sgarrison char *common; 197*12913Sgarrison { char *p; 198*12913Sgarrison 199*12913Sgarrison do 200*12913Sgarrison { while (isspace(*line)) line++; 201*12913Sgarrison 202*12913Sgarrison p= key; 203*12913Sgarrison while (*line!=NULL && !isspace(*line)) 204*12913Sgarrison { *p++ = *line++; 205*12913Sgarrison } 206*12913Sgarrison *p= NULL; 207*12913Sgarrison 208*12913Sgarrison makekey(key, max_klen, common); 209*12913Sgarrison } while (*key==NULL && *line!=NULL); 210*12913Sgarrison return(line); 211*12913Sgarrison } 212*12913Sgarrison 213*12913Sgarrison /* read a reference pair from stream into *ref. if file not given, 214*12913Sgarrison use oldfile. return 1 if pair found, 0 ow. 215*12913Sgarrison */ 216*12913Sgarrison int fetchref(stream, oldfile, ref) 217*12913Sgarrison FILE *stream; 218*12913Sgarrison char *oldfile; 219*12913Sgarrison struct reftype *ref; 220*12913Sgarrison { char cntl; 221*12913Sgarrison 222*12913Sgarrison fscanf(stream, "%c", &cntl); 223*12913Sgarrison if (cntl=='\n') {return (0);} 224*12913Sgarrison if (cntl==':') fscanf(stream, "%s", oldfile); 225*12913Sgarrison strcpy(ref->reffile, oldfile); 226*12913Sgarrison fscanf(stream, "%D/%D", &ref->start, &ref->length); 227*12913Sgarrison return(1); 228*12913Sgarrison } 229