xref: /csrg-svn/contrib/bib/src/locate.c (revision 15062)
112913Sgarrison #ifndef lint
2*15062Sgarrison static char sccsid[] = "@(#)locate.c	2.2	09/23/83";
313111Srrh #endif not lint
4*15062Sgarrison #
512913Sgarrison 
612913Sgarrison # include   "stdio.h"
712913Sgarrison # include   "streams.h"
812913Sgarrison # include   "ctype.h"
912913Sgarrison # define    maxrefs      200
1012913Sgarrison 
1112913Sgarrison struct reftype{
12*15062Sgarrison     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 */
2812913Sgarrison char *locate(keys,name,max_klen,common)
2912913Sgarrison char *keys, *name, *common;
3012913Sgarrison int  max_klen;          /* max key length */
3112913Sgarrison {   static  char oldname[maxstr] = "";  /* oldname is name of stream index */
3212913Sgarrison     static  FILE *index = NULL;
3312913Sgarrison     static  long int i_size;            /* size of index                   */
3412913Sgarrison     static  char oldtext[maxstr];       /* oldtext is the path to stream   */
3512913Sgarrison     static  FILE *text = NULL;		/*  text.  if it is a relative     */
3612913Sgarrison     static  int  pathlen;		/*  path, it is relative to index  */
3712913Sgarrison 					/*  directory.                     */
3812913Sgarrison 					/* oldname[0..pathlen-1] is index  */
3912913Sgarrison 					/*  directory                      */
4012913Sgarrison     int  len;
4112913Sgarrison     char key[maxstr];                   /* refs[i] is a line of index for  */
4212913Sgarrison     struct reftype  refs[maxrefs];      /* all keys up to key              */
4312913Sgarrison 
4412913Sgarrison     int  refcnt, copied, comp;          /* refcnt = # of refs               */
4512913Sgarrison                                         /* copied = # of refs copied        */
4612913Sgarrison                                         /* comp   = # of refs compared      */
4712913Sgarrison     struct reftype ref;
4812913Sgarrison     char   str[maxstr];
4912913Sgarrison     int    more;
5012913Sgarrison 
5112913Sgarrison     long int ans;
5212913Sgarrison     int i,j;
5312913Sgarrison     unsigned total;
5412913Sgarrison     char *allrefs, *next;               /* all refs (separated by null line)*/
5512913Sgarrison     char *p;
5612913Sgarrison 
5712913Sgarrison     /*  open index */
5812913Sgarrison         if  (strcmp(oldname,name)!=0)
5912913Sgarrison         {   if (index) fclose(index);
6012913Sgarrison             if (text) fclose(text);
6112913Sgarrison             strcpy(oldname,name);
6212913Sgarrison             strcpy(oldtext,"");
6312913Sgarrison             /*  determine pathlen   */
6412913Sgarrison                 p= rindex(oldname, '/');
6512913Sgarrison                 if      (p!=NULL)           pathlen= p-oldname+1;
6612913Sgarrison                 else                        pathlen= 0;
6712913Sgarrison 
6812913Sgarrison             index= fopen(oldname,"r");
6912913Sgarrison             if (index==NULL)
7012913Sgarrison             {   fprintf(stderr, "locate: cannot open %s\n", oldname);
7112913Sgarrison 		strcpy(oldname, "");
7212913Sgarrison                 return(NULL);
7312913Sgarrison             }
7412913Sgarrison             else
7512913Sgarrison             {   fseek(index,0L,2);     /*  seeks last newline      */
7612913Sgarrison                 i_size= ftell(index);
7712913Sgarrison             }
7812913Sgarrison 
7912913Sgarrison         }
8012913Sgarrison 
8112913Sgarrison     /*  load references to first key  */
8212913Sgarrison         keys= stripkeys(keys,key, max_klen, common);
8312913Sgarrison 	if (*key==NULL)
8412913Sgarrison 	{ fprintf(stderr,"locate: no keys for citation\n");
8512913Sgarrison 	  allrefs = malloc(1);
8612913Sgarrison 	  if (allrefs==NULL)
8712913Sgarrison 	  {  fprintf(stderr,
8812913Sgarrison 	       "locate: insufficient space for references\n");
8912913Sgarrison 	     exit(1);
9012913Sgarrison 	  }
9112913Sgarrison 	  *allrefs= NULL;
9212913Sgarrison 	  return(allrefs);
9312913Sgarrison 	}
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)
11012913Sgarrison             fprintf(stderr,
11112913Sgarrison 		"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 
141*15062Sgarrison     total= 0;
142*15062Sgarrison     for (i=0; i<refcnt; i++)    total += refs[i].length+1;
143*15062Sgarrison 
144*15062Sgarrison     allrefs= malloc(total+1);
145*15062Sgarrison     if (allrefs==NULL)
146*15062Sgarrison     {   fprintf(stderr, "locate: insufficient space for references\n");
147*15062Sgarrison 	exit(1);
148*15062Sgarrison     }
149*15062Sgarrison 
150*15062Sgarrison     /* copy refs into allrefs */
151*15062Sgarrison         next= allrefs;
15212913Sgarrison         for (i=0; i<refcnt; i++)
15312913Sgarrison         {   /*  open text */
15412913Sgarrison                 if (strcmp(oldtext,refs[i].reffile) != 0)
15512913Sgarrison                 {   strcpy(oldtext,refs[i].reffile);
15612913Sgarrison 		    if (oldtext[0]=='/')
15712913Sgarrison 		    {   /* absolute path */
15812913Sgarrison 			strcpy(str,oldtext);
15912913Sgarrison 		    } else
16012913Sgarrison 		    {   /* relative name */
16112913Sgarrison 			strncpy(str, oldname, pathlen);  str[pathlen]= NULL;
16212913Sgarrison 			strcat(str, oldtext);
16312913Sgarrison 		    }
16412913Sgarrison                     if (text) fclose(text);
16512913Sgarrison                     text= fopen(str, "r");
16612913Sgarrison                     if (text==NULL)
16712913Sgarrison                     {   fprintf(stderr, "locate: cannot open %s\n", str);
16812913Sgarrison 			strcpy(oldtext, "");
16912913Sgarrison                         return(NULL);
17012913Sgarrison                     }
17112913Sgarrison                 }
17212913Sgarrison             fseek(text, refs[i].start, 0);
17312913Sgarrison             for (j=0; j<refs[i].length; j++)    *next++ = getc(text);
17412913Sgarrison             *next++ = '\n';
17512913Sgarrison         }
17612913Sgarrison         *next = NULL;
17712913Sgarrison     return(allrefs);
17812913Sgarrison }
17912913Sgarrison 
18012913Sgarrison 
18112913Sgarrison 
18212913Sgarrison /*  stripkeys(line,key,max_klen, common):
18312913Sgarrison         assigns to key the first key in line
18412913Sgarrison         and returns a pointer to the position following the key
18512913Sgarrison */
18612913Sgarrison char *stripkeys(line,key,max_klen,common)
18712913Sgarrison char *line, *key;
18812913Sgarrison int  max_klen;
18912913Sgarrison char *common;
19012913Sgarrison {   char *p;
19112913Sgarrison 
19212913Sgarrison     do
19312913Sgarrison     {   while (isspace(*line))   line++;
19412913Sgarrison 
19512913Sgarrison         p= key;
19612913Sgarrison         while (*line!=NULL && !isspace(*line))
19712913Sgarrison         {   *p++ = *line++;
19812913Sgarrison         }
19912913Sgarrison         *p= NULL;
20012913Sgarrison 
20112913Sgarrison         makekey(key, max_klen, common);
20212913Sgarrison     }   while (*key==NULL && *line!=NULL);
20312913Sgarrison     return(line);
20412913Sgarrison }
20512913Sgarrison 
20612913Sgarrison /*  read a reference pair from stream into *ref.  if file not given,
20712913Sgarrison     use oldfile. return 1 if pair found, 0 ow.
20812913Sgarrison */
20912913Sgarrison int fetchref(stream, oldfile, ref)
21012913Sgarrison FILE *stream;
21112913Sgarrison char *oldfile;
21212913Sgarrison struct reftype *ref;
21312913Sgarrison {   char cntl;
21412913Sgarrison 
21512913Sgarrison     fscanf(stream, "%c", &cntl);
21612913Sgarrison     if (cntl=='\n') {return (0);}
21712913Sgarrison     if (cntl==':')  fscanf(stream, "%s", oldfile);
21812913Sgarrison     strcpy(ref->reffile, oldfile);
219*15062Sgarrison     fscanf(stream, "%D/%D", &ref->start, &ref->length);
22012913Sgarrison     return(1);
22112913Sgarrison }
222