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