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