112913Sgarrison #ifndef lint
2*60507Sbostic static char sccsid[] = "@(#)locate.c 2.7 05/27/93";
313111Srrh #endif not lint
415062Sgarrison #
512913Sgarrison
612913Sgarrison # include "stdio.h"
712913Sgarrison # include "streams.h"
812913Sgarrison # include "ctype.h"
930588Sgarrison # define maxrefs 1000
1012913Sgarrison
1112913Sgarrison struct reftype{
1215062Sgarrison char reffile[maxstr];
1312913Sgarrison long int start, length;
1412913Sgarrison };
1512913Sgarrison
1623486Sgarrison char *calloc();
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.
2423486Sgarrison Pointer returned comes from calloc. 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 */
2815889Srrh int fflag; /* set if want the reference string to have the file name*/
locate(keys,name,max_klen,common)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");
70*60507Sbostic if (index==NULL) {
71*60507Sbostic fprintf(stderr,"locate: cannot open %s\n", oldname);
72*60507Sbostic strcpy(oldname, "");
73*60507Sbostic return(NULL);
74*60507Sbostic }
75*60507Sbostic else {
76*60507Sbostic fseek(index,0L,2); /* seeks last newline */
77*60507Sbostic i_size= ftell(index);
78*60507Sbostic }
7912913Sgarrison
8012913Sgarrison }
8112913Sgarrison
8212913Sgarrison /* load references to first key */
8312913Sgarrison keys= stripkeys(keys,key, max_klen, common);
84*60507Sbostic if (*key==NULL) {
85*60507Sbostic fprintf(stderr,"locate: no keys for citation: %s\n", keys);
8623486Sgarrison allrefs = (char *) calloc(1, sizeof (char));
87*60507Sbostic if (allrefs==NULL) {
88*60507Sbostic fprintf(stderr,"locate: insufficient space for references\n");
89*60507Sbostic exit(1);
90*60507Sbostic }
9112913Sgarrison *allrefs= NULL;
9212913Sgarrison return(allrefs);
93*60507Sbostic }
9412913Sgarrison len= strlen(key);
9512913Sgarrison strcat(key," ");
9612913Sgarrison alpha_seek(index, key, i_size, 0);
9712913Sgarrison key[len]= NULL; /* strip blank off */
9812913Sgarrison
9912913Sgarrison refcnt= 0;
10012913Sgarrison fscanf(index,"%s ", str);
10112913Sgarrison if (strcmp(str,key) == 0)
10212913Sgarrison { str[0]= NULL;
10312913Sgarrison while (refcnt < maxrefs && fetchref(index, str, &ref) )
10412913Sgarrison { refs[refcnt]= ref;
10512913Sgarrison refcnt++;
10612913Sgarrison }
10712913Sgarrison }
10812913Sgarrison
10912913Sgarrison if (refcnt==maxrefs)
110*60507Sbostic fprintf(stderr,
111*60507Sbostic "locate: first key (%s) matched too many refs\n", key);
11212913Sgarrison
11312913Sgarrison /* intersect the reference sets for remaining keys with first set */
11412913Sgarrison while (*keys!=NULL)
11512913Sgarrison { keys= stripkeys(keys, key, max_klen, common);
11612913Sgarrison if (*key==NULL) continue;
11712913Sgarrison
11812913Sgarrison len= strlen(key);
11912913Sgarrison strcat(key," ");
12012913Sgarrison alpha_seek(index, key, i_size, 0);
12112913Sgarrison key[len]= NULL;
12212913Sgarrison
12312913Sgarrison fscanf(index,"%s ", str);
12412913Sgarrison if (strcmp(str,key) != 0) refcnt= 0; /* no matching refs */
12512913Sgarrison
12612913Sgarrison copied= 0; comp= 0; more= fetchref(index, str, &ref);
12712913Sgarrison while (comp < refcnt && more)
12812913Sgarrison { /* ans= ref-refs[comp] */
12912913Sgarrison ans= strcmp(ref.reffile, refs[comp].reffile);
13012913Sgarrison if (ans==0) ans= ref.start-refs[comp].start;
13112913Sgarrison if (ans==0) ans= ref.length-refs[comp].length;
13212913Sgarrison if (ans<0) more= fetchref(index, str, &ref);
13312913Sgarrison if (ans==0) { refs[copied]= refs[comp]; comp++; copied++;
13412913Sgarrison more= fetchref(index, str, &ref);}
13512913Sgarrison if (ans>0) comp++;
13612913Sgarrison }
13712913Sgarrison
13812913Sgarrison refcnt= copied;
13912913Sgarrison }
14012913Sgarrison
14115062Sgarrison total= 0;
14223493Sgarrison for (i=0; i<refcnt; i++) {
14323493Sgarrison total += refs[i].length+1;
14423493Sgarrison if (fflag){
14523493Sgarrison total += strlen(refs[i].reffile) + 1;
14623493Sgarrison }
14715889Srrh }
14815062Sgarrison
14923486Sgarrison allrefs= (char *) calloc(total+1, sizeof (char));
15015062Sgarrison if (allrefs==NULL)
151*60507Sbostic { fprintf(stderr,"locate: insufficient space for references\n");
15215062Sgarrison exit(1);
15315062Sgarrison }
15415062Sgarrison
15515062Sgarrison /* copy refs into allrefs */
15615062Sgarrison next= allrefs;
15712913Sgarrison for (i=0; i<refcnt; i++)
15812913Sgarrison { /* open text */
15912913Sgarrison if (strcmp(oldtext,refs[i].reffile) != 0)
16012913Sgarrison { strcpy(oldtext,refs[i].reffile);
16112913Sgarrison if (oldtext[0]=='/')
16212913Sgarrison { /* absolute path */
16312913Sgarrison strcpy(str,oldtext);
16412913Sgarrison } else
16512913Sgarrison { /* relative name */
16612913Sgarrison strncpy(str, oldname, pathlen); str[pathlen]= NULL;
16712913Sgarrison strcat(str, oldtext);
16812913Sgarrison }
16912913Sgarrison if (text) fclose(text);
17012913Sgarrison text= fopen(str, "r");
17112913Sgarrison if (text==NULL)
172*60507Sbostic { fprintf(stderr,"locate: cannot open %s\n", str);
17312913Sgarrison strcpy(oldtext, "");
17412913Sgarrison return(NULL);
17512913Sgarrison }
17612913Sgarrison }
17712913Sgarrison fseek(text, refs[i].start, 0);
17815889Srrh if (fflag){
17915889Srrh strcat(next, refs[i].reffile);
18015889Srrh next += strlen(next);
18115889Srrh *next++ = '\n';
18215889Srrh *next = 0;
18315889Srrh }
18412913Sgarrison for (j=0; j<refs[i].length; j++) *next++ = getc(text);
18512913Sgarrison *next++ = '\n';
18612913Sgarrison }
18712913Sgarrison *next = NULL;
18812913Sgarrison return(allrefs);
18912913Sgarrison }
19012913Sgarrison
19112913Sgarrison
19212913Sgarrison
19312913Sgarrison /* stripkeys(line,key,max_klen, common):
19412913Sgarrison assigns to key the first key in line
19512913Sgarrison and returns a pointer to the position following the key
19612913Sgarrison */
stripkeys(line,key,max_klen,common)19712913Sgarrison char *stripkeys(line,key,max_klen,common)
19812913Sgarrison char *line, *key;
19912913Sgarrison int max_klen;
20012913Sgarrison char *common;
20112913Sgarrison { char *p;
20212913Sgarrison
20312913Sgarrison do
20412913Sgarrison { while (isspace(*line)) line++;
20512913Sgarrison
20612913Sgarrison p= key;
20712913Sgarrison while (*line!=NULL && !isspace(*line))
20812913Sgarrison { *p++ = *line++;
20912913Sgarrison }
21012913Sgarrison *p= NULL;
21112913Sgarrison
21212913Sgarrison makekey(key, max_klen, common);
21312913Sgarrison } while (*key==NULL && *line!=NULL);
21412913Sgarrison return(line);
21512913Sgarrison }
21612913Sgarrison
21712913Sgarrison /* read a reference pair from stream into *ref. if file not given,
21812913Sgarrison use oldfile. return 1 if pair found, 0 ow.
21912913Sgarrison */
fetchref(stream,oldfile,ref)22012913Sgarrison int fetchref(stream, oldfile, ref)
22112913Sgarrison FILE *stream;
22212913Sgarrison char *oldfile;
22312913Sgarrison struct reftype *ref;
22412913Sgarrison { char cntl;
22512913Sgarrison
22612913Sgarrison fscanf(stream, "%c", &cntl);
22712913Sgarrison if (cntl=='\n') {return (0);}
22812913Sgarrison if (cntl==':') fscanf(stream, "%s", oldfile);
22912913Sgarrison strcpy(ref->reffile, oldfile);
23015062Sgarrison fscanf(stream, "%D/%D", &ref->start, &ref->length);
23112913Sgarrison return(1);
23212913Sgarrison }
233