112913Sgarrison #ifndef lint 2*15889Srrh static char sccsid[] = "@(#)locate.c 2.3 01/24/84"; 313111Srrh #endif not lint 415062Sgarrison # 512913Sgarrison 612913Sgarrison # include "stdio.h" 712913Sgarrison # include "streams.h" 812913Sgarrison # include "ctype.h" 912913Sgarrison # define maxrefs 200 1012913Sgarrison 1112913Sgarrison struct reftype{ 1215062Sgarrison char reffile[maxstr]; 1312913Sgarrison long int start, length; 1412913Sgarrison }; 1512913Sgarrison 1612913Sgarrison char *malloc(); 1712913Sgarrison char *rindex(); 1812913Sgarrison char *stripkeys(); 1912913Sgarrison int fetchref(); 2012913Sgarrison 2112913Sgarrison /* locate(keys, name, max_klen, common): 2212913Sgarrison Returns a string containing all references pointed to by name 2312913Sgarrison that contain all keys in keys. Common is name of common word file. 2412913Sgarrison Pointer returned comes from malloc. Use free to return storage. 2512913Sgarrison NB A zero length string returned if nothing is found. 2612913Sgarrison A NULL pointer indicates an error accessing the file "name". 2712913Sgarrison */ 28*15889Srrh int fflag; /* set if want the reference string to have the file name*/ 2912913Sgarrison char *locate(keys,name,max_klen,common) 3012913Sgarrison char *keys, *name, *common; 3112913Sgarrison int max_klen; /* max key length */ 3212913Sgarrison { static char oldname[maxstr] = ""; /* oldname is name of stream index */ 3312913Sgarrison static FILE *index = NULL; 3412913Sgarrison static long int i_size; /* size of index */ 3512913Sgarrison static char oldtext[maxstr]; /* oldtext is the path to stream */ 3612913Sgarrison static FILE *text = NULL; /* text. if it is a relative */ 3712913Sgarrison static int pathlen; /* path, it is relative to index */ 3812913Sgarrison /* directory. */ 3912913Sgarrison /* oldname[0..pathlen-1] is index */ 4012913Sgarrison /* directory */ 4112913Sgarrison int len; 4212913Sgarrison char key[maxstr]; /* refs[i] is a line of index for */ 4312913Sgarrison struct reftype refs[maxrefs]; /* all keys up to key */ 4412913Sgarrison 4512913Sgarrison int refcnt, copied, comp; /* refcnt = # of refs */ 4612913Sgarrison /* copied = # of refs copied */ 4712913Sgarrison /* comp = # of refs compared */ 4812913Sgarrison struct reftype ref; 4912913Sgarrison char str[maxstr]; 5012913Sgarrison int more; 5112913Sgarrison 5212913Sgarrison long int ans; 5312913Sgarrison int i,j; 5412913Sgarrison unsigned total; 5512913Sgarrison char *allrefs, *next; /* all refs (separated by null line)*/ 5612913Sgarrison char *p; 5712913Sgarrison 5812913Sgarrison /* open index */ 5912913Sgarrison if (strcmp(oldname,name)!=0) 6012913Sgarrison { if (index) fclose(index); 6112913Sgarrison if (text) fclose(text); 6212913Sgarrison strcpy(oldname,name); 6312913Sgarrison strcpy(oldtext,""); 6412913Sgarrison /* determine pathlen */ 6512913Sgarrison p= rindex(oldname, '/'); 6612913Sgarrison if (p!=NULL) pathlen= p-oldname+1; 6712913Sgarrison else pathlen= 0; 6812913Sgarrison 6912913Sgarrison index= fopen(oldname,"r"); 7012913Sgarrison if (index==NULL) 7112913Sgarrison { fprintf(stderr, "locate: cannot open %s\n", oldname); 7212913Sgarrison strcpy(oldname, ""); 7312913Sgarrison return(NULL); 7412913Sgarrison } 7512913Sgarrison else 7612913Sgarrison { fseek(index,0L,2); /* seeks last newline */ 7712913Sgarrison i_size= ftell(index); 7812913Sgarrison } 7912913Sgarrison 8012913Sgarrison } 8112913Sgarrison 8212913Sgarrison /* load references to first key */ 8312913Sgarrison keys= stripkeys(keys,key, max_klen, common); 8412913Sgarrison if (*key==NULL) 8512913Sgarrison { fprintf(stderr,"locate: no keys for citation\n"); 8612913Sgarrison allrefs = malloc(1); 8712913Sgarrison if (allrefs==NULL) 8812913Sgarrison { fprintf(stderr, 8912913Sgarrison "locate: insufficient space for references\n"); 9012913Sgarrison exit(1); 9112913Sgarrison } 9212913Sgarrison *allrefs= NULL; 9312913Sgarrison return(allrefs); 9412913Sgarrison } 9512913Sgarrison len= strlen(key); 9612913Sgarrison strcat(key," "); 9712913Sgarrison alpha_seek(index, key, i_size, 0); 9812913Sgarrison key[len]= NULL; /* strip blank off */ 9912913Sgarrison 10012913Sgarrison refcnt= 0; 10112913Sgarrison fscanf(index,"%s ", str); 10212913Sgarrison if (strcmp(str,key) == 0) 10312913Sgarrison { str[0]= NULL; 10412913Sgarrison while (refcnt < maxrefs && fetchref(index, str, &ref) ) 10512913Sgarrison { refs[refcnt]= ref; 10612913Sgarrison refcnt++; 10712913Sgarrison } 10812913Sgarrison } 10912913Sgarrison 11012913Sgarrison if (refcnt==maxrefs) 11112913Sgarrison fprintf(stderr, 11212913Sgarrison "locate: first key (%s) matched too many refs\n", key); 11312913Sgarrison 11412913Sgarrison /* intersect the reference sets for remaining keys with first set */ 11512913Sgarrison while (*keys!=NULL) 11612913Sgarrison { keys= stripkeys(keys, key, max_klen, common); 11712913Sgarrison if (*key==NULL) continue; 11812913Sgarrison 11912913Sgarrison len= strlen(key); 12012913Sgarrison strcat(key," "); 12112913Sgarrison alpha_seek(index, key, i_size, 0); 12212913Sgarrison key[len]= NULL; 12312913Sgarrison 12412913Sgarrison fscanf(index,"%s ", str); 12512913Sgarrison if (strcmp(str,key) != 0) refcnt= 0; /* no matching refs */ 12612913Sgarrison 12712913Sgarrison copied= 0; comp= 0; more= fetchref(index, str, &ref); 12812913Sgarrison while (comp < refcnt && more) 12912913Sgarrison { /* ans= ref-refs[comp] */ 13012913Sgarrison ans= strcmp(ref.reffile, refs[comp].reffile); 13112913Sgarrison if (ans==0) ans= ref.start-refs[comp].start; 13212913Sgarrison if (ans==0) ans= ref.length-refs[comp].length; 13312913Sgarrison if (ans<0) more= fetchref(index, str, &ref); 13412913Sgarrison if (ans==0) { refs[copied]= refs[comp]; comp++; copied++; 13512913Sgarrison more= fetchref(index, str, &ref);} 13612913Sgarrison if (ans>0) comp++; 13712913Sgarrison } 13812913Sgarrison 13912913Sgarrison refcnt= copied; 14012913Sgarrison } 14112913Sgarrison 14215062Sgarrison total= 0; 14315062Sgarrison for (i=0; i<refcnt; i++) total += refs[i].length+1; 144*15889Srrh if (fflag){ 145*15889Srrh total += strlen(refs[i].reffile) + 1; 146*15889Srrh } 14715062Sgarrison 14815062Sgarrison allrefs= malloc(total+1); 14915062Sgarrison if (allrefs==NULL) 15015062Sgarrison { fprintf(stderr, "locate: insufficient space for references\n"); 15115062Sgarrison exit(1); 15215062Sgarrison } 15315062Sgarrison 15415062Sgarrison /* copy refs into allrefs */ 15515062Sgarrison next= allrefs; 15612913Sgarrison for (i=0; i<refcnt; i++) 15712913Sgarrison { /* open text */ 15812913Sgarrison if (strcmp(oldtext,refs[i].reffile) != 0) 15912913Sgarrison { strcpy(oldtext,refs[i].reffile); 16012913Sgarrison if (oldtext[0]=='/') 16112913Sgarrison { /* absolute path */ 16212913Sgarrison strcpy(str,oldtext); 16312913Sgarrison } else 16412913Sgarrison { /* relative name */ 16512913Sgarrison strncpy(str, oldname, pathlen); str[pathlen]= NULL; 16612913Sgarrison strcat(str, oldtext); 16712913Sgarrison } 16812913Sgarrison if (text) fclose(text); 16912913Sgarrison text= fopen(str, "r"); 17012913Sgarrison if (text==NULL) 17112913Sgarrison { fprintf(stderr, "locate: cannot open %s\n", str); 17212913Sgarrison strcpy(oldtext, ""); 17312913Sgarrison return(NULL); 17412913Sgarrison } 17512913Sgarrison } 17612913Sgarrison fseek(text, refs[i].start, 0); 177*15889Srrh if (fflag){ 178*15889Srrh strcat(next, refs[i].reffile); 179*15889Srrh next += strlen(next); 180*15889Srrh *next++ = '\n'; 181*15889Srrh *next = 0; 182*15889Srrh } 18312913Sgarrison for (j=0; j<refs[i].length; j++) *next++ = getc(text); 18412913Sgarrison *next++ = '\n'; 18512913Sgarrison } 18612913Sgarrison *next = NULL; 18712913Sgarrison return(allrefs); 18812913Sgarrison } 18912913Sgarrison 19012913Sgarrison 19112913Sgarrison 19212913Sgarrison /* stripkeys(line,key,max_klen, common): 19312913Sgarrison assigns to key the first key in line 19412913Sgarrison and returns a pointer to the position following the key 19512913Sgarrison */ 19612913Sgarrison char *stripkeys(line,key,max_klen,common) 19712913Sgarrison char *line, *key; 19812913Sgarrison int max_klen; 19912913Sgarrison char *common; 20012913Sgarrison { char *p; 20112913Sgarrison 20212913Sgarrison do 20312913Sgarrison { while (isspace(*line)) line++; 20412913Sgarrison 20512913Sgarrison p= key; 20612913Sgarrison while (*line!=NULL && !isspace(*line)) 20712913Sgarrison { *p++ = *line++; 20812913Sgarrison } 20912913Sgarrison *p= NULL; 21012913Sgarrison 21112913Sgarrison makekey(key, max_klen, common); 21212913Sgarrison } while (*key==NULL && *line!=NULL); 21312913Sgarrison return(line); 21412913Sgarrison } 21512913Sgarrison 21612913Sgarrison /* read a reference pair from stream into *ref. if file not given, 21712913Sgarrison use oldfile. return 1 if pair found, 0 ow. 21812913Sgarrison */ 21912913Sgarrison int fetchref(stream, oldfile, ref) 22012913Sgarrison FILE *stream; 22112913Sgarrison char *oldfile; 22212913Sgarrison struct reftype *ref; 22312913Sgarrison { char cntl; 22412913Sgarrison 22512913Sgarrison fscanf(stream, "%c", &cntl); 22612913Sgarrison if (cntl=='\n') {return (0);} 22712913Sgarrison if (cntl==':') fscanf(stream, "%s", oldfile); 22812913Sgarrison strcpy(ref->reffile, oldfile); 22915062Sgarrison fscanf(stream, "%D/%D", &ref->start, &ref->length); 23012913Sgarrison return(1); 23112913Sgarrison } 232