xref: /csrg-svn/contrib/bib/src/locate.c (revision 23493)
112913Sgarrison #ifndef lint
2*23493Sgarrison static char sccsid[] = "@(#)locate.c	2.5	06/11/85";
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 
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*/
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");
8623486Sgarrison 	  allrefs = (char *) calloc(1, sizeof (char));
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;
143*23493Sgarrison     for (i=0; i<refcnt; i++) {
144*23493Sgarrison         total += refs[i].length+1;
145*23493Sgarrison         if (fflag){
146*23493Sgarrison 	    total += strlen(refs[i].reffile) + 1;
147*23493Sgarrison         }
14815889Srrh     }
14915062Sgarrison 
15023486Sgarrison     allrefs= (char *) calloc(total+1, sizeof (char));
15115062Sgarrison     if (allrefs==NULL)
15215062Sgarrison     {   fprintf(stderr, "locate: insufficient space for references\n");
15315062Sgarrison 	exit(1);
15415062Sgarrison     }
15515062Sgarrison 
15615062Sgarrison     /* copy refs into allrefs */
15715062Sgarrison         next= allrefs;
15812913Sgarrison         for (i=0; i<refcnt; i++)
15912913Sgarrison         {   /*  open text */
16012913Sgarrison                 if (strcmp(oldtext,refs[i].reffile) != 0)
16112913Sgarrison                 {   strcpy(oldtext,refs[i].reffile);
16212913Sgarrison 		    if (oldtext[0]=='/')
16312913Sgarrison 		    {   /* absolute path */
16412913Sgarrison 			strcpy(str,oldtext);
16512913Sgarrison 		    } else
16612913Sgarrison 		    {   /* relative name */
16712913Sgarrison 			strncpy(str, oldname, pathlen);  str[pathlen]= NULL;
16812913Sgarrison 			strcat(str, oldtext);
16912913Sgarrison 		    }
17012913Sgarrison                     if (text) fclose(text);
17112913Sgarrison                     text= fopen(str, "r");
17212913Sgarrison                     if (text==NULL)
17312913Sgarrison                     {   fprintf(stderr, "locate: cannot open %s\n", str);
17412913Sgarrison 			strcpy(oldtext, "");
17512913Sgarrison                         return(NULL);
17612913Sgarrison                     }
17712913Sgarrison                 }
17812913Sgarrison             fseek(text, refs[i].start, 0);
17915889Srrh 	    if (fflag){
18015889Srrh 		strcat(next, refs[i].reffile);
18115889Srrh 		next += strlen(next);
18215889Srrh 		*next++ = '\n';
18315889Srrh 		*next = 0;
18415889Srrh 	    }
18512913Sgarrison             for (j=0; j<refs[i].length; j++)    *next++ = getc(text);
18612913Sgarrison             *next++ = '\n';
18712913Sgarrison         }
18812913Sgarrison         *next = NULL;
18912913Sgarrison     return(allrefs);
19012913Sgarrison }
19112913Sgarrison 
19212913Sgarrison 
19312913Sgarrison 
19412913Sgarrison /*  stripkeys(line,key,max_klen, common):
19512913Sgarrison         assigns to key the first key in line
19612913Sgarrison         and returns a pointer to the position following the key
19712913Sgarrison */
19812913Sgarrison char *stripkeys(line,key,max_klen,common)
19912913Sgarrison char *line, *key;
20012913Sgarrison int  max_klen;
20112913Sgarrison char *common;
20212913Sgarrison {   char *p;
20312913Sgarrison 
20412913Sgarrison     do
20512913Sgarrison     {   while (isspace(*line))   line++;
20612913Sgarrison 
20712913Sgarrison         p= key;
20812913Sgarrison         while (*line!=NULL && !isspace(*line))
20912913Sgarrison         {   *p++ = *line++;
21012913Sgarrison         }
21112913Sgarrison         *p= NULL;
21212913Sgarrison 
21312913Sgarrison         makekey(key, max_klen, common);
21412913Sgarrison     }   while (*key==NULL && *line!=NULL);
21512913Sgarrison     return(line);
21612913Sgarrison }
21712913Sgarrison 
21812913Sgarrison /*  read a reference pair from stream into *ref.  if file not given,
21912913Sgarrison     use oldfile. return 1 if pair found, 0 ow.
22012913Sgarrison */
22112913Sgarrison int fetchref(stream, oldfile, ref)
22212913Sgarrison FILE *stream;
22312913Sgarrison char *oldfile;
22412913Sgarrison struct reftype *ref;
22512913Sgarrison {   char cntl;
22612913Sgarrison 
22712913Sgarrison     fscanf(stream, "%c", &cntl);
22812913Sgarrison     if (cntl=='\n') {return (0);}
22912913Sgarrison     if (cntl==':')  fscanf(stream, "%s", oldfile);
23012913Sgarrison     strcpy(ref->reffile, oldfile);
23115062Sgarrison     fscanf(stream, "%D/%D", &ref->start, &ref->length);
23212913Sgarrison     return(1);
23312913Sgarrison }
234