xref: /csrg-svn/contrib/bib/src/locate.c (revision 23486)
112913Sgarrison #ifndef lint
2*23486Sgarrison static char sccsid[] = "@(#)locate.c	2.4	06/10/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 
16*23486Sgarrison 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.
24*23486Sgarrison     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");
86*23486Sgarrison 	  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;
14315062Sgarrison     for (i=0; i<refcnt; i++)    total += refs[i].length+1;
14415889Srrh     if (fflag){
14515889Srrh 	total += strlen(refs[i].reffile) + 1;
14615889Srrh     }
14715062Sgarrison 
148*23486Sgarrison     allrefs= (char *) calloc(total+1, sizeof (char));
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);
17715889Srrh 	    if (fflag){
17815889Srrh 		strcat(next, refs[i].reffile);
17915889Srrh 		next += strlen(next);
18015889Srrh 		*next++ = '\n';
18115889Srrh 		*next = 0;
18215889Srrh 	    }
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