|
|
1.1 root 1: #include <stdio.h>
2: #include <ctype.h>
3: #include <sys/types.h>
4: #include <sys/stat.h>
5: #include "streams.h"
6: #include "bib.h"
7:
8: #define maxrefs 500
9: #define LONGSTR 1280
10:
11:
12: char *strncat(), *strncpy(), *strcat(), *strcpy(), *strrchr();
13:
14: #define ireturn(s,name) \
15: { \
16: fprintf(stderr,s,name); \
17: nodatabase = 1; \
18: return(NULL); \
19: }
20:
21: struct reftype{
22: char reffile[maxstr];
23: long int start, length;
24: };
25:
26: char *malloc();
27: char *stripkeys();
28: int fetchref();
29:
30: /* locate(keys, name):
31: Returns a string containing all references pointed to by name
32: that contain all keys in keys. Common is name of common word file.
33: Pointer returned comes from malloc. Use free to return storage.
34: NB A zero length string returned if nothing is found.
35: A NULL pointer indicates an error accessing the file "name".
36: */
37: char *locate(keys,name)
38: char *keys, *name;
39: {
40: static int max_klen = MAXKLEN; /* max key length */
41: static char *common = COMFILE; /* pointer to common file */
42: static char comstr[maxstr]; /* holds name of common file */
43:
44: static char oldname[maxstr] = ""; /* oldname is name of stream index */
45: static FILE *index = NULL;
46: static long int i_size; /* size of index */
47: static char oldtext[maxstr]; /* oldtext is the path to stream */
48: static FILE *text = NULL; /* text. if it is a relative */
49: FILE *head;
50:
51: static int pathlen; /* path, it is relative to index */
52: int len;
53: char key[maxstr]; /* refs[i] is a line of index for */
54: char line[maxstr];
55: struct reftype refs[maxrefs]; /* all keys up to key */
56:
57: int refcnt, copied, comp; /* refcnt = # of refs */
58: struct reftype ref;
59: char str[LONGSTR];
60: char istr[LONGSTR];
61: char tstr[maxstr], *tp;
62: int more;
63: int outofdate;
64:
65: long int ans;
66: int i,j;
67: unsigned total;
68: char *allrefs, *next; /* all refs (separated by null line)*/
69: char *p;
70:
71: static int nodatabase = 0; /* cannot open or invert INDEX */
72:
73: struct stat ibuf, tbuf; /* for comparing mtimes of index and text */
74: /* open index */
75: if(strcmp(oldname,name)!=0) {
76: nodatabase = 0;
77: if (index) fclose(index);
78: if (text) fclose(text);
79: strcpy(oldname,name);
80: strcpy(oldtext,"");
81: /* determine pathlen */
82: p= strrchr(oldname, '/');
83: if (p!=NULL) pathlen= p-oldname+1;
84: else pathlen= 0;
85:
86: *istr = NULL;
87: if(stat(oldname,&ibuf) == -1) { /* create index */
88: strncpy(istr,oldname,strlen(oldname)-2);
89: /* assume that bib database is named istr */
90: if(makeindex(istr,istr,max_klen,common))
91: ireturn("locate: cannot invert %s\n",istr);
92: }
93: else { /* see if index is up to date */
94: *str = NULL;
95: strcpy(str,oldname);
96: str[strlen(oldname)-1] = NULL;
97: strcat(str,"h");
98: if((head = fopen(str,"r")) == NULL)
99: ireturn("locate: cannot open %s\n",str);
100: if(fscanf(head,"%s %d\n",comstr,&max_klen) != 2) {
101: ireturn("locate: %s is in the wrong format; rerun pinvert\n",str);
102: }
103: else {
104: common = comstr;
105: }
106: *str = NULL;
107: outofdate = 0;
108: while(fgets(line,maxstr,head)) {
109: line[strlen(line)-1] = NULL;
110: if(*line != '/') {
111: strncat(str, oldname, pathlen);
112: }
113: strcat(str,line);
114: strcat(str," ");
115: if(!outofdate) {
116: if(*line != '/') {
117: *tstr = NULL;
118: strncat(tstr, oldname, pathlen);
119: strcat(tstr,line);
120: tp = tstr;
121: }
122: else tp = line;
123: if(stat(tp,&tbuf) == -1)
124: ireturn("locate: cannot stat %s\n",tp);
125: if(tbuf.st_mtime > ibuf.st_mtime)
126: outofdate++;
127: }
128: }
129: fclose(head);
130: if(outofdate) {
131: if(*istr == NULL)
132: strncpy(istr,oldname,strlen(oldname)-2);
133: if(makeindex(str,istr,max_klen,common))
134: ireturn("locate: cannot invert %s\n",str);
135: }
136: }
137: if ((index= fopen(oldname,"r"))==NULL)
138: ireturn("locate: cannot open %s\n", oldname);
139: fseek(index,0L,2); /* seeks last newline */
140: i_size= ftell(index);
141: }
142: else if/* database known to be unaccessible */
143: (nodatabase) return(NULL);
144:
145: /* load references to first key */
146: keys= stripkeys(keys,key, max_klen, common);
147: if (*key==NULL) {
148: allrefs = malloc(1);
149: if (allrefs==NULL) {
150: fprintf(stderr,
151: "locate: insufficient space for references\n");
152: exit(1);
153: }
154: *allrefs= NULL;
155: return(allrefs);
156: }
157: len= strlen(key);
158: strcat(key," ");
159: alpha_seek(index, key, i_size, 0);
160: key[len]= NULL; /* strip blank off */
161:
162: refcnt= 0;
163: fscanf(index,"%s ", str);
164: if (strcmp(str,key) == 0) {
165: str[0]= NULL;
166: while (refcnt < maxrefs && fetchref(index, str, &ref) ) {
167: refs[refcnt]= ref;
168: refcnt++;
169: }
170: }
171:
172: if (refcnt==maxrefs)
173: fprintf(stderr,
174: "locate: first key (%s) matched too many refs\n", key);
175:
176: /* intersect the reference sets for remaining keys with first set */
177: while (*keys!=NULL) {
178: keys= stripkeys(keys, key, max_klen, common);
179: if (*key==NULL) continue;
180:
181: len= strlen(key);
182: strcat(key," ");
183: alpha_seek(index, key, i_size, 0);
184: key[len]= NULL;
185:
186: fscanf(index,"%s ", str);
187: if (strcmp(str,key) != 0) refcnt= 0; /* no matching refs */
188:
189: copied= 0;
190: comp= 0;
191: more= fetchref(index, str, &ref);
192: while (comp < refcnt && more) { /* ans= ref-refs[comp] */
193: ans= strcmp(ref.reffile, refs[comp].reffile);
194: if (ans==0) ans= ref.start-refs[comp].start;
195: if (ans==0) ans= ref.length-refs[comp].length;
196: if (ans<0) more= fetchref(index, str, &ref);
197: if (ans==0) {
198: refs[copied]= refs[comp];
199: comp++;
200: copied++;
201: more= fetchref(index, str, &ref);
202: }
203: if (ans>0) comp++;
204: }
205:
206: refcnt= copied;
207: }
208:
209: total= 0;
210: for (i=0; i<refcnt; i++) total += refs[i].length+1;
211:
212: allrefs= malloc(total+1);
213: if (allrefs==NULL) {
214: fprintf(stderr, "locate: insufficient space for references\n");
215: exit(1);
216: }
217:
218: /* copy refs into allrefs */
219: next= allrefs;
220: for (i=0; i<refcnt; i++) { /* open text */
221: if (strcmp(oldtext,refs[i].reffile) != 0) {
222: strcpy(oldtext,refs[i].reffile);
223: if (oldtext[0]=='/') { /* absolute path */
224: strcpy(str,oldtext);
225: } else { /* relative name */
226: strncpy(str, oldname, pathlen);
227: str[pathlen]= NULL;
228: strcat(str, oldtext);
229: }
230: if (text) fclose(text);
231: text= fopen(str, "r");
232: if (text==NULL) {
233: fprintf(stderr, "locate: cannot open %s\n", str);
234: strcpy(oldtext, "");
235: return(NULL);
236: }
237: }
238: fseek(text, refs[i].start, 0);
239: for (j=0; j<refs[i].length; j++) *next++ = getc(text);
240: *next++ = '\n';
241: }
242: *next = NULL;
243: return(allrefs);
244: }
245:
246:
247:
248: /* stripkeys(line,key,max_klen, common):
249: assigns to key the first key in line
250: and returns a pointer to the position following the key
251: */
252: char *stripkeys(line,key,max_klen,common)
253: char *line, *key;
254: int max_klen;
255: char *common;
256: {
257: char *p;
258:
259: do {
260: while (*line && !isalnum(*line)) line++;
261:
262: p= key;
263: while (isalnum(*line))
264: *p++ = *line++;
265: *p= NULL;
266: if(*key == NULL)
267: break;
268: makekey(key, max_klen, common);
269: } while (*key == NULL);
270: return(line);
271: }
272:
273: /* read a reference pair from stream into *ref. if file not given,
274: use oldfile. return 1 if pair found, 0 ow.
275: */
276: int fetchref(stream, oldfile, ref)
277: FILE *stream;
278: char *oldfile;
279: struct reftype *ref;
280: {
281: char cntl;
282:
283: fscanf(stream, "%c", &cntl);
284: if (cntl=='\n') {
285: return (0);
286: }
287: if (cntl==':') fscanf(stream, "%s", oldfile);
288: strcpy(ref->reffile, oldfile);
289: fscanf(stream, "%ld/%ld", &ref->start, &ref->length);
290: return(1);
291: }
292:
293:
294:
295: char pinvert[] = "pinvert -l%d -c%s -p%s %s";
296:
297: makeindex(names,index,k,com)
298: char *names,*com,*index;
299: int k;
300: {
301: char pcmd[LONGSTR];
302:
303: sprintf(pcmd,pinvert,k,com,index,names);
304: return(system(pcmd));
305: }
306:
307:
308:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.