xref: /csrg-svn/contrib/bib/src/locate.c (revision 15889)
112913Sgarrison #ifndef lint
2*15889Srrh static char sccsid[] = "@(#)locate.c	2.3	01/24/84";
313111Srrh #endif not lint
415062Sgarrison #
512913Sgarrison 
612913Sgarrison # include   "stdio.h"
712913Sgarrison # include   "streams.h"
812913Sgarrison # include   "ctype.h"
912913Sgarrison # define    maxrefs      200
1012913Sgarrison 
1112913Sgarrison struct reftype{
1215062Sgarrison     char reffile[maxstr];
1312913Sgarrison     long int start, length;
1412913Sgarrison     };
1512913Sgarrison 
1612913Sgarrison char *malloc();
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.
2412913Sgarrison     Pointer returned comes from malloc.  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 */
28*15889Srrh int fflag;	/* set if want the reference string to have the file name*/
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");
7012913Sgarrison             if (index==NULL)
7112913Sgarrison             {   fprintf(stderr, "locate: cannot open %s\n", oldname);
7212913Sgarrison 		strcpy(oldname, "");
7312913Sgarrison                 return(NULL);
7412913Sgarrison             }
7512913Sgarrison             else
7612913Sgarrison             {   fseek(index,0L,2);     /*  seeks last newline      */
7712913Sgarrison                 i_size= ftell(index);
7812913Sgarrison             }
7912913Sgarrison 
8012913Sgarrison         }
8112913Sgarrison 
8212913Sgarrison     /*  load references to first key  */
8312913Sgarrison         keys= stripkeys(keys,key, max_klen, common);
8412913Sgarrison 	if (*key==NULL)
8512913Sgarrison 	{ fprintf(stderr,"locate: no keys for citation\n");
8612913Sgarrison 	  allrefs = malloc(1);
8712913Sgarrison 	  if (allrefs==NULL)
8812913Sgarrison 	  {  fprintf(stderr,
8912913Sgarrison 	       "locate: insufficient space for references\n");
9012913Sgarrison 	     exit(1);
9112913Sgarrison 	  }
9212913Sgarrison 	  *allrefs= NULL;
9312913Sgarrison 	  return(allrefs);
9412913Sgarrison 	}
9512913Sgarrison         len= strlen(key);
9612913Sgarrison         strcat(key," ");
9712913Sgarrison         alpha_seek(index, key, i_size, 0);
9812913Sgarrison         key[len]= NULL;                     /*  strip blank off */
9912913Sgarrison 
10012913Sgarrison         refcnt= 0;
10112913Sgarrison         fscanf(index,"%s ", str);
10212913Sgarrison         if (strcmp(str,key) == 0)
10312913Sgarrison         {   str[0]= NULL;
10412913Sgarrison             while (refcnt < maxrefs && fetchref(index, str, &ref) )
10512913Sgarrison             {   refs[refcnt]= ref;
10612913Sgarrison                 refcnt++;
10712913Sgarrison             }
10812913Sgarrison         }
10912913Sgarrison 
11012913Sgarrison         if (refcnt==maxrefs)
11112913Sgarrison             fprintf(stderr,
11212913Sgarrison 		"locate: first key (%s) matched too many refs\n", key);
11312913Sgarrison 
11412913Sgarrison     /*  intersect the reference sets for remaining keys with first set */
11512913Sgarrison         while (*keys!=NULL)
11612913Sgarrison         {   keys= stripkeys(keys, key, max_klen, common);
11712913Sgarrison             if (*key==NULL) continue;
11812913Sgarrison 
11912913Sgarrison             len= strlen(key);
12012913Sgarrison             strcat(key," ");
12112913Sgarrison             alpha_seek(index, key, i_size, 0);
12212913Sgarrison             key[len]= NULL;
12312913Sgarrison 
12412913Sgarrison             fscanf(index,"%s ", str);
12512913Sgarrison             if (strcmp(str,key) != 0)  refcnt= 0;   /*  no matching refs */
12612913Sgarrison 
12712913Sgarrison             copied= 0; comp= 0; more= fetchref(index, str, &ref);
12812913Sgarrison             while (comp < refcnt && more)
12912913Sgarrison             {   /*  ans= ref-refs[comp]    */
13012913Sgarrison                     ans= strcmp(ref.reffile, refs[comp].reffile);
13112913Sgarrison                     if (ans==0)     ans= ref.start-refs[comp].start;
13212913Sgarrison                     if (ans==0)     ans= ref.length-refs[comp].length;
13312913Sgarrison                 if (ans<0)  more= fetchref(index, str, &ref);
13412913Sgarrison                 if (ans==0) { refs[copied]= refs[comp]; comp++; copied++;
13512913Sgarrison                               more= fetchref(index, str, &ref);}
13612913Sgarrison                 if (ans>0)  comp++;
13712913Sgarrison             }
13812913Sgarrison 
13912913Sgarrison             refcnt= copied;
14012913Sgarrison         }
14112913Sgarrison 
14215062Sgarrison     total= 0;
14315062Sgarrison     for (i=0; i<refcnt; i++)    total += refs[i].length+1;
144*15889Srrh     if (fflag){
145*15889Srrh 	total += strlen(refs[i].reffile) + 1;
146*15889Srrh     }
14715062Sgarrison 
14815062Sgarrison     allrefs= malloc(total+1);
14915062Sgarrison     if (allrefs==NULL)
15015062Sgarrison     {   fprintf(stderr, "locate: insufficient space for references\n");
15115062Sgarrison 	exit(1);
15215062Sgarrison     }
15315062Sgarrison 
15415062Sgarrison     /* copy refs into allrefs */
15515062Sgarrison         next= allrefs;
15612913Sgarrison         for (i=0; i<refcnt; i++)
15712913Sgarrison         {   /*  open text */
15812913Sgarrison                 if (strcmp(oldtext,refs[i].reffile) != 0)
15912913Sgarrison                 {   strcpy(oldtext,refs[i].reffile);
16012913Sgarrison 		    if (oldtext[0]=='/')
16112913Sgarrison 		    {   /* absolute path */
16212913Sgarrison 			strcpy(str,oldtext);
16312913Sgarrison 		    } else
16412913Sgarrison 		    {   /* relative name */
16512913Sgarrison 			strncpy(str, oldname, pathlen);  str[pathlen]= NULL;
16612913Sgarrison 			strcat(str, oldtext);
16712913Sgarrison 		    }
16812913Sgarrison                     if (text) fclose(text);
16912913Sgarrison                     text= fopen(str, "r");
17012913Sgarrison                     if (text==NULL)
17112913Sgarrison                     {   fprintf(stderr, "locate: cannot open %s\n", str);
17212913Sgarrison 			strcpy(oldtext, "");
17312913Sgarrison                         return(NULL);
17412913Sgarrison                     }
17512913Sgarrison                 }
17612913Sgarrison             fseek(text, refs[i].start, 0);
177*15889Srrh 	    if (fflag){
178*15889Srrh 		strcat(next, refs[i].reffile);
179*15889Srrh 		next += strlen(next);
180*15889Srrh 		*next++ = '\n';
181*15889Srrh 		*next = 0;
182*15889Srrh 	    }
18312913Sgarrison             for (j=0; j<refs[i].length; j++)    *next++ = getc(text);
18412913Sgarrison             *next++ = '\n';
18512913Sgarrison         }
18612913Sgarrison         *next = NULL;
18712913Sgarrison     return(allrefs);
18812913Sgarrison }
18912913Sgarrison 
19012913Sgarrison 
19112913Sgarrison 
19212913Sgarrison /*  stripkeys(line,key,max_klen, common):
19312913Sgarrison         assigns to key the first key in line
19412913Sgarrison         and returns a pointer to the position following the key
19512913Sgarrison */
19612913Sgarrison char *stripkeys(line,key,max_klen,common)
19712913Sgarrison char *line, *key;
19812913Sgarrison int  max_klen;
19912913Sgarrison char *common;
20012913Sgarrison {   char *p;
20112913Sgarrison 
20212913Sgarrison     do
20312913Sgarrison     {   while (isspace(*line))   line++;
20412913Sgarrison 
20512913Sgarrison         p= key;
20612913Sgarrison         while (*line!=NULL && !isspace(*line))
20712913Sgarrison         {   *p++ = *line++;
20812913Sgarrison         }
20912913Sgarrison         *p= NULL;
21012913Sgarrison 
21112913Sgarrison         makekey(key, max_klen, common);
21212913Sgarrison     }   while (*key==NULL && *line!=NULL);
21312913Sgarrison     return(line);
21412913Sgarrison }
21512913Sgarrison 
21612913Sgarrison /*  read a reference pair from stream into *ref.  if file not given,
21712913Sgarrison     use oldfile. return 1 if pair found, 0 ow.
21812913Sgarrison */
21912913Sgarrison int fetchref(stream, oldfile, ref)
22012913Sgarrison FILE *stream;
22112913Sgarrison char *oldfile;
22212913Sgarrison struct reftype *ref;
22312913Sgarrison {   char cntl;
22412913Sgarrison 
22512913Sgarrison     fscanf(stream, "%c", &cntl);
22612913Sgarrison     if (cntl=='\n') {return (0);}
22712913Sgarrison     if (cntl==':')  fscanf(stream, "%s", oldfile);
22812913Sgarrison     strcpy(ref->reffile, oldfile);
22915062Sgarrison     fscanf(stream, "%D/%D", &ref->start, &ref->length);
23012913Sgarrison     return(1);
23112913Sgarrison }
232