|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.