xref: /csrg-svn/contrib/bib/src/locate.c (revision 13111)
112913Sgarrison #ifndef lint
2*13111Srrh static char sccsid[] = "@(#)locate.c	1.2	06/14/83";
3*13111Srrh #endif not lint
412913Sgarrison 
512913Sgarrison # include   "stdio.h"
612913Sgarrison # include   "streams.h"
712913Sgarrison # include   "ctype.h"
812913Sgarrison # define    maxrefs      200
912913Sgarrison 
1012913Sgarrison struct reftype{
1112913Sgarrison     char reffile[64];		/* rrh: still may be too short */
1212913Sgarrison     long int start, length;
1312913Sgarrison     };
1412913Sgarrison 
1512913Sgarrison char *malloc();
1612913Sgarrison char *rindex();
1712913Sgarrison char *stripkeys();
1812913Sgarrison int   fetchref();
1912913Sgarrison int fileflag;
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  char workbuf[10240];	/* work buffer */
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 
14212913Sgarrison     /* copy refs into the work buffer */
14312913Sgarrison         next= workbuf;
14412913Sgarrison         for (i=0; i<refcnt; i++)
14512913Sgarrison         {   /*  open text */
14612913Sgarrison                 if (strcmp(oldtext,refs[i].reffile) != 0)
14712913Sgarrison                 {   strcpy(oldtext,refs[i].reffile);
14812913Sgarrison 		    if (oldtext[0]=='/')
14912913Sgarrison 		    {   /* absolute path */
15012913Sgarrison 			strcpy(str,oldtext);
15112913Sgarrison 		    } else
15212913Sgarrison 		    {   /* relative name */
15312913Sgarrison 			strncpy(str, oldname, pathlen);  str[pathlen]= NULL;
15412913Sgarrison 			strcat(str, oldtext);
15512913Sgarrison 		    }
15612913Sgarrison                     if (text) fclose(text);
15712913Sgarrison                     text= fopen(str, "r");
15812913Sgarrison                     if (text==NULL)
15912913Sgarrison                     {   fprintf(stderr, "locate: cannot open %s\n", str);
16012913Sgarrison 			strcpy(oldtext, "");
16112913Sgarrison                         return(NULL);
16212913Sgarrison                     }
16312913Sgarrison                 }
16412913Sgarrison             fseek(text, refs[i].start, 0);
16512913Sgarrison 	    {
16612913Sgarrison 		register char *from;
16712913Sgarrison 		if (fileflag){
16812913Sgarrison 			from = oldtext;
16912913Sgarrison 			while(*next++ = *from++) /*VOID*/ ;
17012913Sgarrison 			next[-1] = '\n';
17112913Sgarrison 		}
17212913Sgarrison 	    }
17312913Sgarrison             for (j=0; j<refs[i].length; j++)    *next++ = getc(text);
17412913Sgarrison             *next++ = '\n';
17512913Sgarrison         }
17612913Sgarrison         *next = NULL;
17712913Sgarrison     allrefs = malloc(strlen(workbuf) + 1);
17812913Sgarrison     if (allrefs == NULL) {
17912913Sgarrison 	fprintf(stderr, "No space left for allrefs\n");
18012913Sgarrison 	exit(1);
18112913Sgarrison     }
18212913Sgarrison     strcpy(allrefs, workbuf);
18312913Sgarrison     return(allrefs);
18412913Sgarrison }
18512913Sgarrison 
18612913Sgarrison 
18712913Sgarrison 
18812913Sgarrison /*  stripkeys(line,key,max_klen, common):
18912913Sgarrison         assigns to key the first key in line
19012913Sgarrison         and returns a pointer to the position following the key
19112913Sgarrison */
19212913Sgarrison char *stripkeys(line,key,max_klen,common)
19312913Sgarrison char *line, *key;
19412913Sgarrison int  max_klen;
19512913Sgarrison char *common;
19612913Sgarrison {   char *p;
19712913Sgarrison 
19812913Sgarrison     do
19912913Sgarrison     {   while (isspace(*line))   line++;
20012913Sgarrison 
20112913Sgarrison         p= key;
20212913Sgarrison         while (*line!=NULL && !isspace(*line))
20312913Sgarrison         {   *p++ = *line++;
20412913Sgarrison         }
20512913Sgarrison         *p= NULL;
20612913Sgarrison 
20712913Sgarrison         makekey(key, max_klen, common);
20812913Sgarrison     }   while (*key==NULL && *line!=NULL);
20912913Sgarrison     return(line);
21012913Sgarrison }
21112913Sgarrison 
21212913Sgarrison /*  read a reference pair from stream into *ref.  if file not given,
21312913Sgarrison     use oldfile. return 1 if pair found, 0 ow.
21412913Sgarrison */
21512913Sgarrison int fetchref(stream, oldfile, ref)
21612913Sgarrison FILE *stream;
21712913Sgarrison char *oldfile;
21812913Sgarrison struct reftype *ref;
21912913Sgarrison {   char cntl;
22012913Sgarrison 
22112913Sgarrison     fscanf(stream, "%c", &cntl);
22212913Sgarrison     if (cntl=='\n') {return (0);}
22312913Sgarrison     if (cntl==':')  fscanf(stream, "%s", oldfile);
22412913Sgarrison     strcpy(ref->reffile, oldfile);
225*13111Srrh     fscanf(stream, "%ld/%ld", &ref->start, &ref->length);
22612913Sgarrison     return(1);
22712913Sgarrison }
228