xref: /csrg-svn/contrib/bib/src/locate.c (revision 13245)
1 #ifndef lint
2 static char sccsid[] = "@(#)locate.c	2.1	06/22/83";
3 #endif not lint
4 
5 # include   "stdio.h"
6 # include   "streams.h"
7 # include   "ctype.h"
8 # define    maxrefs      200
9 
10 struct reftype{
11     char reffile[64];		/* rrh: still may be too short */
12     long int start, length;
13     };
14 
15 char *malloc();
16 char *rindex();
17 char *stripkeys();
18 int   fetchref();
19 int fileflag;
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 malloc.  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 char *locate(keys,name,max_klen,common)
29 char *keys, *name, *common;
30 int  max_klen;          /* max key length */
31 {   static  char oldname[maxstr] = "";  /* oldname is name of stream index */
32     static  FILE *index = NULL;
33     static  long int i_size;            /* size of index                   */
34     static  char oldtext[maxstr];       /* oldtext is the path to stream   */
35     static  char workbuf[10240];	/* work buffer */
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 = malloc(1);
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     /* copy refs into the work buffer */
143         next= workbuf;
144         for (i=0; i<refcnt; i++)
145         {   /*  open text */
146                 if (strcmp(oldtext,refs[i].reffile) != 0)
147                 {   strcpy(oldtext,refs[i].reffile);
148 		    if (oldtext[0]=='/')
149 		    {   /* absolute path */
150 			strcpy(str,oldtext);
151 		    } else
152 		    {   /* relative name */
153 			strncpy(str, oldname, pathlen);  str[pathlen]= NULL;
154 			strcat(str, oldtext);
155 		    }
156                     if (text) fclose(text);
157                     text= fopen(str, "r");
158                     if (text==NULL)
159                     {   fprintf(stderr, "locate: cannot open %s\n", str);
160 			strcpy(oldtext, "");
161                         return(NULL);
162                     }
163                 }
164             fseek(text, refs[i].start, 0);
165 	    {
166 		register char *from;
167 		if (fileflag){
168 			from = oldtext;
169 			while(*next++ = *from++) /*VOID*/ ;
170 			next[-1] = '\n';
171 		}
172 	    }
173             for (j=0; j<refs[i].length; j++)    *next++ = getc(text);
174             *next++ = '\n';
175         }
176         *next = NULL;
177     allrefs = malloc(strlen(workbuf) + 1);
178     if (allrefs == NULL) {
179 	fprintf(stderr, "No space left for allrefs\n");
180 	exit(1);
181     }
182     strcpy(allrefs, workbuf);
183     return(allrefs);
184 }
185 
186 
187 
188 /*  stripkeys(line,key,max_klen, common):
189         assigns to key the first key in line
190         and returns a pointer to the position following the key
191 */
192 char *stripkeys(line,key,max_klen,common)
193 char *line, *key;
194 int  max_klen;
195 char *common;
196 {   char *p;
197 
198     do
199     {   while (isspace(*line))   line++;
200 
201         p= key;
202         while (*line!=NULL && !isspace(*line))
203         {   *p++ = *line++;
204         }
205         *p= NULL;
206 
207         makekey(key, max_klen, common);
208     }   while (*key==NULL && *line!=NULL);
209     return(line);
210 }
211 
212 /*  read a reference pair from stream into *ref.  if file not given,
213     use oldfile. return 1 if pair found, 0 ow.
214 */
215 int fetchref(stream, oldfile, ref)
216 FILE *stream;
217 char *oldfile;
218 struct reftype *ref;
219 {   char cntl;
220 
221     fscanf(stream, "%c", &cntl);
222     if (cntl=='\n') {return (0);}
223     if (cntl==':')  fscanf(stream, "%s", oldfile);
224     strcpy(ref->reffile, oldfile);
225     fscanf(stream, "%ld/%ld", &ref->start, &ref->length);
226     return(1);
227 }
228