summaryrefslogtreecommitdiff
path: root/biblio/tib/src/locate.c
diff options
context:
space:
mode:
Diffstat (limited to 'biblio/tib/src/locate.c')
-rw-r--r--biblio/tib/src/locate.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/biblio/tib/src/locate.c b/biblio/tib/src/locate.c
new file mode 100644
index 0000000000..fdd117d9e3
--- /dev/null
+++ b/biblio/tib/src/locate.c
@@ -0,0 +1,217 @@
+#include "stdio.h"
+#include "ctype.h"
+#include "tib.h"
+
+static struct reftype{
+ char reffile[MAXSTR];
+ long int start, length;
+ };
+
+char *malloc();
+char *rindex();
+char *stripkeys();
+int fetchref();
+
+/* locate(keys, name, max_klen, common):
+ Returns a string containing all references pointed to by name
+ that contain all keys in keys. Common is name of common word file.
+ Pointer returned comes from malloc. Use free to return storage.
+ NB A zero length string returned if nothing is found.
+ A NULL pointer indicates an error accessing the file "name".
+*/
+char *locate(keys,name,max_klen,common)
+char *keys, *name, *common;
+int max_klen; /* max key length */
+{ static char oldname[MAXSTR] = ""; /* oldname is name of stream index */
+ static FILE *index = NULL;
+ static long int i_size; /* size of index */
+ static char oldtext[MAXSTR]; /* oldtext is the path to stream */
+ static FILE *text = NULL; /* text. if it is a relative */
+ static int pathlen; /* path, it is relative to index */
+ /* directory. */
+ /* oldname[0..pathlen-1] is index */
+ /* directory */
+ int len;
+ char key[MAXSTR]; /* refs[i] is a line of index for */
+ struct reftype refs[MAXREFS]; /* all keys up to key */
+
+ int refcnt, copied, comp; /* refcnt = # of refs */
+ /* copied = # of refs copied */
+ /* comp = # of refs compared */
+ struct reftype ref;
+ char str[MAXSTR];
+ int more;
+
+ long int ans;
+ int i,j;
+ unsigned total;
+ char *allrefs, *next; /* all refs (separated by null line)*/
+ char *p;
+
+ /* open index */
+ if (strcmp(oldname,name)!=0)
+ { if (index) fclose(index);
+ if (text) fclose(text);
+ strcpy(oldname,name);
+ strcpy(oldtext,"");
+ /* determine pathlen */
+ p= rindex(oldname, '/');
+ if (p!=NULL) pathlen= p-oldname+1;
+ else pathlen= 0;
+
+ index= fopen(oldname,"r");
+ if (index==NULL)
+ { fprintf(stderr, "locate: cannot open %s\n", oldname);
+ strcpy(oldname, "");
+ return(NULL);
+ }
+ else
+ { fseek(index,0L,2); /* seeks last newline */
+ i_size= ftell(index);
+ }
+
+ }
+
+ /* load references to first key */
+ keys= stripkeys(keys,key, max_klen, common);
+ if (*key==NULL)
+ { fprintf(stderr,"locate: no keys for citation\n");
+ allrefs = malloc(1);
+ if (allrefs==NULL)
+ { fprintf(stderr,
+ "locate: insufficient space for references\n");
+ clnup();
+ exit(1);
+ }
+ *allrefs= NULL;
+ return(allrefs);
+ }
+ len= strlen(key);
+ strcat(key," ");
+ alpha_seek(index, key, i_size, 0);
+ key[len]= NULL; /* strip blank off */
+
+ refcnt= 0;
+ fscanf(index,"%s ", str);
+ if (strcmp(str,key) == 0)
+ { str[0]= NULL;
+ while (refcnt < MAXREFS && fetchref(index, str, &ref) )
+ { refs[refcnt]= ref;
+ refcnt++;
+ }
+ }
+
+ if (refcnt==MAXREFS)
+ fprintf(stderr,
+ "locate: first key (%s) matched too many refs\n", key);
+
+ /* intersect the reference sets for remaining keys with first set */
+ while (*keys!=NULL)
+ { keys= stripkeys(keys, key, max_klen, common);
+ if (*key==NULL) continue;
+
+ len= strlen(key);
+ strcat(key," ");
+ alpha_seek(index, key, i_size, 0);
+ key[len]= NULL;
+
+ fscanf(index,"%s ", str);
+ if (strcmp(str,key) != 0) refcnt= 0; /* no matching refs */
+
+ copied= 0; comp= 0; more= fetchref(index, str, &ref);
+ while (comp < refcnt && more)
+ { /* ans= ref-refs[comp] */
+ ans= strcmp(ref.reffile, refs[comp].reffile);
+ if (ans==0) ans= ref.start-refs[comp].start;
+ if (ans==0) ans= ref.length-refs[comp].length;
+ if (ans<0) more= fetchref(index, str, &ref);
+ if (ans==0) { refs[copied]= refs[comp]; comp++; copied++;
+ more= fetchref(index, str, &ref);}
+ if (ans>0) comp++;
+ }
+
+ refcnt= copied;
+ }
+
+ total= 0;
+ for (i=0; i<refcnt; i++) total += refs[i].length+1;
+
+ allrefs= malloc(total+1);
+ if (allrefs==NULL)
+ { fprintf(stderr, "locate: insufficient space for references\n");
+ clnup();
+ exit(1);
+ }
+
+ /* copy refs into allrefs */
+ next= allrefs;
+ for (i=0; i<refcnt; i++)
+ { /* open text */
+ if (strcmp(oldtext,refs[i].reffile) != 0)
+ { strcpy(oldtext,refs[i].reffile);
+ if (oldtext[0]=='/')
+ { /* absolute path */
+ strcpy(str,oldtext);
+ } else
+ { /* relative name */
+ strncpy(str, oldname, pathlen); str[pathlen]= NULL;
+ strcat(str, oldtext);
+ }
+ if (text) fclose(text);
+ text= fopen(str, "r");
+ if (text==NULL)
+ { fprintf(stderr, "locate: cannot open %s\n", str);
+ strcpy(oldtext, "");
+ return(NULL);
+ }
+ }
+ fseek(text, refs[i].start, 0);
+ for (j=0; j<refs[i].length; j++) *next++ = getc(text);
+ *next++ = '\n';
+ }
+ *next = NULL;
+ return(allrefs);
+}
+
+
+
+/* stripkeys(line,key,max_klen, common):
+ assigns to key the first key in line
+ and returns a pointer to the position following the key
+*/
+char *stripkeys(line,key,max_klen,common)
+char *line, *key;
+int max_klen;
+char *common;
+{ char *p;
+
+ do
+ { while (isspace(*line)) line++;
+
+ p= key;
+ while (*line!=NULL && !isspace(*line))
+ { *p++ = *line++;
+ }
+ *p= NULL;
+
+ makekey(key, max_klen, common);
+ } while (*key==NULL && *line!=NULL);
+ return(line);
+}
+
+/* read a reference pair from stream into *ref. if file not given,
+ use oldfile. return 1 if pair found, 0 ow.
+*/
+int fetchref(stream, oldfile, ref)
+FILE *stream;
+char *oldfile;
+struct reftype *ref;
+{ char cntl;
+
+ fscanf(stream, "%c", &cntl);
+ if (cntl=='\n') {return (0);}
+ if (cntl==':') fscanf(stream, "%s", oldfile);
+ strcpy(ref->reffile, oldfile);
+ fscanf(stream, "%D/%D", &ref->start, &ref->length);
+ return(1);
+}