xref: /csrg-svn/contrib/bib/src/locate.c (revision 60507)
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