BSD 4_4 release
[unix-history] / usr / src / contrib / bib / src / bib.c
index 2ddc996..e072eb5 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)bib.c      2.3     %G%";
+static char sccsid[] = "@(#)bib.c      2.11    5/27/93";
 #endif not lint
 /*
         Bib - bibliographic formatter
 #endif not lint
 /*
         Bib - bibliographic formatter
@@ -14,10 +14,13 @@ static char sccsid[] = "@(#)bib.c   2.3     %G%";
                 Phil Garrison - UC Berkeley
                 M. J. Hawley - Yale University
 
                 Phil Garrison - UC Berkeley
                 M. J. Hawley - Yale University
 
-
-
+              version 8/23/1988
+        
+        Adapted to use TiB style macro calls (i.e. |macro|)
+              A. Dain Samples
 
                                                         */
 
                                                         */
+
 # include <stdio.h>
 # include <ctype.h>
 # include "bib.h"
 # include <stdio.h>
 # include <ctype.h>
 # include "bib.h"
@@ -32,55 +35,70 @@ static char sccsid[] = "@(#)bib.c   2.3     %G%";
 
 /* global variables */
    FILE *rfd;                   /* reference temporary file              */
 
 /* global variables */
    FILE *rfd;                   /* reference temporary file              */
+#ifndef INCORE
    char reffile[] = TMPREFFILE ;/* temporary file (see bib.h)            */
    char reffile[] = TMPREFFILE ;/* temporary file (see bib.h)            */
-   long int refspos[MAXREFS];   /* reference seek positions              */
+#endif not INCORE
+   struct refinfo refinfo[MAXREFS];    /* reference information */
+   struct refinfo *refssearch();
+   struct refinfo *refshash[HASHSIZE];
    long int rend = 1;           /* last position in rfd (first char unused)*/
    long int rend = 1;           /* last position in rfd (first char unused)*/
-   int numrefs = -1;            /* number of references generated so far */
+   int numrefs = 0;            /* number of references generated so far */
    FILE *tfd;                   /* output of pass 1 of file(s)           */
    FILE *tfd;                   /* output of pass 1 of file(s)           */
-   char tmpfile[] = TMPTEXTFILE ; /* output of pass 1                    */
-   char common[] = COMFILE ;    /* common word file                      */
-   char *citestr[MAXREFS];      /* citation strings                      */
+   char bibtmpfile[] = TMPTEXTFILE ; /* output of pass 1                    */
+   char *common = COMFILE;       /* common word file                      */
    int  findex = false;         /* can we read the file INDEX ?          */
 
    int  findex = false;         /* can we read the file INDEX ?          */
 
+char *programName;
+
 /* global variables in bibargs */
 /* global variables in bibargs */
-   extern int foot, sort, personal;
+   extern int foot, doacite, sort, max_klen, personal;
    extern int hyphen, ordcite, biblineno;
    extern char sortstr[], pfile[], citetemplate[], bibfname[];
    extern int hyphen, ordcite, biblineno;
    extern char sortstr[], pfile[], citetemplate[], bibfname[];
+   extern int TibOption;
 
 
+#include <signal.h>
 
 main(argc, argv)
    int argc;
    char **argv;
 {  int rcomp();
 
 main(argc, argv)
    int argc;
    char **argv;
 {  int rcomp();
+   int intr();
 
    /* the file INDEX in the current directory is the default index,
       if it is present */
 
 
    /* the file INDEX in the current directory is the default index,
       if it is present */
 
+   InitDirectory(BMACLIB,N_BMACLIB);
+   InitDirectory(COMFILE,N_COMFILE);
+   InitDirectory(DEFSTYLE,N_DEFSTYLE);
+
+   signal(SIGINT, intr);
    rfd = fopen( INDXFILE , "r");
    if (rfd != NULL) {
       findex = true;
       fclose(rfd);
       }
 
    rfd = fopen( INDXFILE , "r");
    if (rfd != NULL) {
       findex = true;
       fclose(rfd);
       }
 
+#ifndef INCORE
    /* open temporaries, reffile will contain references collected in
    /* open temporaries, reffile will contain references collected in
-      pass 1, and tmpfile will contain text.
+      pass 1, and bibtmpfile will contain text.
    */
    mktemp(reffile);
    rfd = fopen(reffile,"w+");
    if (rfd == NULL)
    */
    mktemp(reffile);
    rfd = fopen(reffile,"w+");
    if (rfd == NULL)
-      error("can't open temporary reference file");
+      error("can't open temporary reference file, %s", reffile);
    putc('x', rfd);      /* put garbage in first position (not used) */
    putc('x', rfd);      /* put garbage in first position (not used) */
-   mktemp(tmpfile);
-   tfd = fopen(tmpfile,"w");
+#endif not INCORE
+   mktemp(bibtmpfile);
+   tfd = fopen(bibtmpfile,"w");
    if (tfd == NULL)
    if (tfd == NULL)
-      error("can't open temporary output file");
+      error("can't open temporary output file, %s", bibtmpfile);
 
     /*
        pass1 - read files, looking for citations
                arguments are read by doargs (bibargs.c)
     */
 
 
     /*
        pass1 - read files, looking for citations
                arguments are read by doargs (bibargs.c)
     */
 
-   if (doargs(argc, argv, DEFSTYLE ) == 0) {
+   if (doargs(argc, argv, DEFSTYLE ) == 0) { /* may not return */
       strcpy(bibfname, "<stdin>");
       rdtext(stdin);
       }
       strcpy(bibfname, "<stdin>");
       rdtext(stdin);
       }
@@ -90,8 +108,8 @@ main(argc, argv)
    */
 
    if (sort)
    */
 
    if (sort)
-      qsort(refspos, numrefs+1, sizeof(long), rcomp);
-   makecites(citestr);
+      qsort(refinfo, numrefs, sizeof(struct refinfo), rcomp);
+   makecites();
    disambiguate();
 
    /*
    disambiguate();
 
    /*
@@ -99,25 +117,32 @@ main(argc, argv)
    */
 
    fclose(tfd);
    */
 
    fclose(tfd);
-   tfd = fopen(tmpfile,"r");
+   tfd = fopen(bibtmpfile,"r");
    if (tfd == NULL)
    if (tfd == NULL)
-      error("can't open temporary output file for reading");
-
+      error("can't open temporary output file %s for reading", bibtmpfile);
    /*
    pass 2 - reread files, replacing references
    */
    /*
    pass 2 - reread files, replacing references
    */
-
    pass2(tfd, stdout);
    pass2(tfd, stdout);
-
-   /*
-   clean up
-   */
-
+   cleanup(0);
+}
+/* interrupt processing */
+intr()
+{
+   cleanup(1);
+}
+/* clean up and exit */
+cleanup(val)
+{
    fclose(tfd);
    fclose(tfd);
+#ifndef INCORE
    fclose(rfd);
    fclose(rfd);
-   unlink(tmpfile);
    unlink(reffile);
    unlink(reffile);
-   exit(0);
+#endif INCORE
+#ifndef DEBUG
+   unlink(bibtmpfile);
+#endif DEBUG
+   exit(val);
 }
 
 /* rdtext - read and process a text file, looking for [. commands */
 }
 
 /* rdtext - read and process a text file, looking for [. commands */
@@ -168,46 +193,28 @@ main(argc, argv)
    rdcite(fd, ch)
    FILE *fd;
    char ch;
    rdcite(fd, ch)
    FILE *fd;
    char ch;
-{  long int n, getref();
+{  int getref();
    char huntstr[HUNTSIZE], c, info[HUNTSIZE];
 
    if (ch == '[')
    char huntstr[HUNTSIZE], c, info[HUNTSIZE];
 
    if (ch == '[')
-      fputs("\\*([[", tfd);
+      if (doacite) fputs("\\*([[", tfd);
    else
    else
-      fputs("\\*([{", tfd);
+      if (doacite) fputs("\\*([{", tfd);
    huntstr[0] = info[0] = 0;
    while (getch(c, fd) != EOF)
       switch (c) {
          case ',':
    huntstr[0] = info[0] = 0;
    while (getch(c, fd) != EOF)
       switch (c) {
          case ',':
-            n = getref(huntstr);
-            if (n > 0)
-               fprintf(tfd, "%c%ld%c%s%c", CITEMARK, n, CITEMARK, info, CITEEND);
-            else
-               fprintf(tfd, "%c0%c%s%s%c", CITEMARK, CITEMARK,
-                                           huntstr, info, CITEEND);
+           citemark(info, huntstr, "");
             huntstr[0] = info[0] = 0;
             break;
             huntstr[0] = info[0] = 0;
             break;
-
          case '.':
             while (getch(c, fd) == '.') ;
             if (c == ']') {
          case '.':
             while (getch(c, fd) == '.') ;
             if (c == ']') {
-               n = getref(huntstr);
-               if (n > 0)
-                  fprintf(tfd, "%c%ld%c%s%c\\*(]]", CITEMARK, n,
-                                                  CITEMARK, info, CITEEND);
-               else
-                  fprintf(tfd, "%c0%c%s%s%c\\*(]]", CITEMARK, CITEMARK,
-                                              huntstr, info, CITEEND);
+              citemark(info, huntstr, "\\*(]]");
                return;
                }
             else if (c == '}') {
                return;
                }
             else if (c == '}') {
-               n = getref(huntstr);
-               if (n > 0)
-                  fprintf(tfd, "%c%ld%c%s%c\\*(}]", CITEMARK, n,
-                                                    CITEMARK, info, CITEEND);
-               else
-                  fprintf(tfd, "%c0%c%s%s%c\\*(}]", CITEMARK, CITEMARK,
-                                              huntstr, info, CITEEND);
+              citemark(info, huntstr, "\\*(}]");
                return;
                }
             else
                return;
                }
             else
@@ -217,8 +224,7 @@ main(argc, argv)
          case '{':
             while (getch(c, fd) != '}')
                if (c == EOF) {
          case '{':
             while (getch(c, fd) != '}')
                if (c == EOF) {
-                  fprintf(stderr, "Error: ill formed reference\n");
-                  exit(1);
+                  error("ill formed reference");
                   }
                 else
                   addc(info, c);
                   }
                 else
                   addc(info, c);
@@ -234,85 +240,158 @@ main(argc, argv)
          }
    error("end of file reading citation");
 }
          }
    error("end of file reading citation");
 }
+char   ncitetemplate[64];
+int    changecite;
+citemark(info, huntstr, tail)
+       char *info, *huntstr, *tail;
+{
+       char c = CITEMARK;
+        long int  n;
+       /*
+        *      getref sets ncitetemplate as a side effect
+        */
+       n = getref(huntstr);
+       if (ncitetemplate[0]){
+               fprintf(tfd, "%c%s%c", FMTSTART, ncitetemplate, FMTEND);
+               ncitetemplate[0] = 0;
+       }
+       fprintf(tfd, "%c%d%c%s%c%s", c ,n, c, info, CITEEND, doacite?tail:"");
+
+}
 
 /* addc - add a character to hunt string */
 
 /* addc - add a character to hunt string */
-   addc(huntstr, c)
+addc(huntstr, c)
    char huntstr[HUNTSIZE], c;
 {  int  i;
 
    i = strlen(huntstr);
    if (i > HUNTSIZE)
    char huntstr[HUNTSIZE], c;
 {  int  i;
 
    i = strlen(huntstr);
    if (i > HUNTSIZE)
-      error("citation too long");
+      error("citation too long, max of %d", HUNTSIZE);
    huntstr[i] = c;
    huntstr[i+1] = 0;
 }
 
    huntstr[i] = c;
    huntstr[i+1] = 0;
 }
 
-/* getref - if an item was already referenced, return its pointer in
-                the reference file, otherwise create a new entry */
-   long int getref(huntstr)
+/* getref - if an item was already referenced, return its reference index
+                otherwise create a new entry */
+int getref(huntstr)
    char huntstr[HUNTSIZE];
    char huntstr[HUNTSIZE];
-{  char rf[REFSIZE], ref[REFSIZE], *r, *hunt();
-   int  i, match(), getwrd();
-
-   r = hunt(huntstr);
+{  char rf[REFSIZE], *r, *hunt();
+   int match(), getwrd();
+   char        *realhstr;
+   int hash;
+   struct refinfo *rp;
+   int lg;
+
+   realhstr = huntstr;
+   if (strncmp(huntstr, "$C$", 3) == 0){
+       char *from, *to;
+       changecite++;
+       for(from = huntstr + 3, to = ncitetemplate; *from; from++, to++){
+               switch(*from){
+               case '\0':
+               case ' ':
+               case '\n':
+               case '\t':      goto outcopy;
+               default:        *to = *from;
+               }
+       }
+   outcopy: ;
+       *to = 0;
+       *from = 0;
+       realhstr = from + 1;
+   }
+   r = hunt(realhstr);
    if (r != NULL) {
    if (r != NULL) {
-      /* exapand defined string */
+      /* expand defined string */
       strcpy(rf, r);
       free(r);
       expand(rf);
       strcpy(rf, r);
       free(r);
       expand(rf);
-
       /* see if reference has already been cited */
       /* see if reference has already been cited */
-
-      if (foot == false)
-         for (i = 0; i <= numrefs; i++) {
-             rdref(refspos[i], ref);
-             if (strcmp(ref, rf) == 0)
-                return(refspos[i]);
-          }
-
+      if (foot == false && (rp = refssearch(rf))){
+               return(rp - refinfo);
+      }
       /* didn't match any existing reference, create new one */
       /* didn't match any existing reference, create new one */
-
-      numrefs++;
-      refspos[numrefs] = rend;
-#ifdef READWRITE
-      fixrfd( WRITE );                 /* fix access mode of rfd, if nec. */
-#else
-      fseek(rfd, rend, 0);             /* go to end of rfd */
-#endif
-      i = strlen(rf) + 1;
-      fwrite(rf, 1, i, rfd);
-      rend = rend + i;
-      return(refspos[numrefs]);
+      if (numrefs >= MAXREFS)
+       error("too many references, max of %d", MAXREFS);
+      hash = strhash(rf);
+      lg = strlen(rf) + 1;
+      refinfo[numrefs].ri_pos = rend;
+      refinfo[numrefs].ri_length = lg;
+      refinfo[numrefs].ri_hp = refshash[hash];
+      refinfo[numrefs].ri_n = numrefs;
+      refshash[hash] = &refinfo[numrefs];
+      wrref(&refinfo[numrefs], rf);
+      return(numrefs++);
       }
    else {
       }
    else {
-      bibwarning("no reference matching %s\n", huntstr);
-      return( (long) -1 );
+      bibwarning("no reference matching %s\n", realhstr);
+      return(-1);
       }
 }
 
       }
 }
 
+struct refinfo *refssearch(rf)
+   char *rf;
+{
+   char ref[REFSIZE];
+   reg int i;
+   int lg;
+   reg struct refinfo *rp;
+   lg = strlen(rf) + 1;
+   for (rp = refshash[strhash(rf)]; rp; rp = rp->ri_hp){
+            if (rp->ri_length == lg){
+                    rdref(rp, ref);
+                    if (strcmp(ref, rf) == 0)
+                       return(rp);
+            }
+   }
+   return(0);
+}
 /* hunt - hunt for reference from either personal or system index */
 /* hunt - hunt for reference from either personal or system index */
-   char *hunt(huntstr)
+/* the old versions would stop at the first index file where a citation
+ * matched.  This is NOT what is desired.  I have changed it so that it still
+ * returns the first citation found, but also reports the existence of
+ * duplicate entries in an INDEX file as well as across INDEX files.
+ * Also, we do NOT assume that the SYSINDEX has been Tib'd.  Therefore,
+ * if tib style expansion is in effect, the SYSINDEX is not searched.
+ * (Besides which, on Sun systems at least, the SYSINDEX files are
+ * created by refer, not bib, so we can't use them very effectively
+ * anyway.  Besides which again, everything in SYSINDEX is in our
+ * local files anyway.)
+ *                   - ads 8/88
+ */
+char *hunt(huntstr)
    char huntstr[];
    char huntstr[];
-{  char *fhunt(), *r, *p, *q, fname[120];
+{  char *found, *fhunt(), *r, *tp, *sp, fname[120];
 
 
+   found = NULL;
    if (personal) {
    if (personal) {
-      for (p = fname, q = pfile; ; q++)
-         if (*q == ',' || *q == 0) {
-            *p = 0;
-            if ((r = fhunt(fname, huntstr)) != NULL)
-               return(r);
-            else if (*q == 0)
+      for (tp = fname, sp = pfile; ; sp++)
+         if (*sp == ',' || *sp == '\0') {
+            *tp = '\0';
+            if ((r = fhunt(fname, huntstr)) != NULL) {
+               if (found != NULL) {
+                   /* we need an option to suppress this message -ads 5/89 */
+                   bibwarning("multiple INDEX files match citation %s\n",
+                                                       huntstr);
+                   return (found);
+                   }
+               found = r;
+               }
+            if (*sp == '\0')
                break;
                break;
-            p = fname;
+            tp = fname;
             }
             }
-         else *p++ = *q;
+         else *tp++ = *sp;
+      if (found != NULL) return (found);
       }
    else if (findex) {
       }
    else if (findex) {
-      if ((r = fhunt( INDXFILE , huntstr)) != NULL)
+      if ((r = fhunt(INDXFILE , huntstr)) != NULL)
          return(r);
       }
          return(r);
       }
-   if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
-      return(r);
+   if (!TibOption) {
+      if ((r = fhunt(SYSINDEX , huntstr)) != NULL)
+        return(r);
+      }
    return(NULL);
 }
 
    return(NULL);
 }
 
@@ -321,7 +400,7 @@ main(argc, argv)
    char file[], huntstr[];
 {  char *p, *r, *locate();
 
    char file[], huntstr[];
 {  char *p, *r, *locate();
 
-   r = locate(huntstr, file, 6, common);
+   r = locate(huntstr, file, max_klen, common);
 
    if (r == NULL)
       return(NULL);  /* error */
 
    if (r == NULL)
       return(NULL);  /* error */
@@ -340,90 +419,132 @@ main(argc, argv)
             *p = ' ';
    return(r);
 }
             *p = ' ';
    return(r);
 }
+struct cite{
+       int     num;
+       char    *info;
+};
+citesort(p1, p2)
+       struct cite *p1, *p2;
+{
+       return(p1->num - p2->num);
+}
 
 /* putrefs - gather contiguous references together, sort them if called
    for, hyphenate if necessary, and dump them out */
 int putrefs(ifd, ofd, footrefs, fn)
 FILE *ifd, *ofd;
 int  fn, footrefs[];
 
 /* putrefs - gather contiguous references together, sort them if called
    for, hyphenate if necessary, and dump them out */
 int putrefs(ifd, ofd, footrefs, fn)
 FILE *ifd, *ofd;
 int  fn, footrefs[];
-{  int  citenums[MAXATONCE];   /* reference numbers */
-   char *citeinfo[MAXATONCE];  /* reference information */
-   char infoword[HUNTSIZE];    /* information line */
-   int  rtop, n, i, j;         /* number of citations being dumped */
-   char c, *p, *walloc();
-
-/* first gather contiguous references together, and order them if
-   required      */
-
-   rtop = -1;
-   do {
-      n = 0;
-      while (isdigit(getch(c, ifd)))
-         n = 10 * n + (c - '0');
-      if (c ^= CITEMARK)
-         error("inconsistant citation found in pass two");
-      if (n == 0) {     /* reference not found */
-         rtop++;
-         j = rtop;
-         citenums[j] = -1;
-         citeinfo[j] = 0;
-         }
-      else {
-         for (i = 0; i <= numrefs; i++)
-            if (refspos[i] == n) { /* its the ith item in reference list */
-               rtop++;
-               j = rtop;
-               if (ordcite)
-                  for ( ; j > 0 && citenums[j-1] > i; j--) {
-                     citenums[j] = citenums[j-1];
-                     citeinfo[j] = citeinfo[j-1];
-                     }
-               citenums[j] = i;
-               citeinfo[j] = 0;
-               break;
-               }
-         if (i > numrefs)
-            error("citation not found in pass two");
-         }
-      if (getch(c, ifd) != CITEEND) {
-         for (p = infoword; c != CITEEND ; ) {
-            *p++ = c;
-            getch(c, ifd);
-            }
-         *p = 0;
-         citeinfo[j] = walloc(infoword);
-         }
-      getch(c, ifd);
-      }  while (c == CITEMARK);
-   ungetc(c, ifd);
-
-   /* now dump out values */
-   for (i = 0; i <= rtop; i++) {
-      if (citenums[i] >= 0)
-         fputs(citestr[citenums[i]], ofd);
-      if (citeinfo[i]) {
-         fputs(citeinfo[i], ofd);
-         free(citeinfo[i]);
-         }
-      if (hyphen) {
-         for (j = 1; j + i <= rtop && citenums[i+j] == citenums[i] + j; j++);
-         if (j + i > rtop) j = rtop;
-         else j = j + i - 1;
-         }
-      else
-         j = i;
-      if (j > i + 1) {
-         fputs("\\*(]-", ofd);
-         i = j - 1;
-         }
-      else if (i != rtop)
-         fputs("\\*(],", ofd);
-      if (foot) {
-         fn++;
-         footrefs[fn] = citenums[i];
-         }
-      }
-   return(fn);
+{
+       struct cite cites[MAXATONCE];
+       char    infoword[HUNTSIZE];    /* information line */
+       reg     int i;
+       reg     char *p;
+       reg     int  ncites, n, j;         /* number of citations being dumped */
+       char    c, *walloc();
+       int neg;
+       /*
+        * first gather contiguous references together,
+        * and order them if required     
+        */
+
+       ncites = 0;
+       do {
+               neg = 1;
+               n = 0;
+               do{
+                       getch(c, ifd);
+                       if (isdigit(c))
+                               n = 10 * n + (c - '0');
+                       else if (c == '-')
+                               neg *= -1;
+                       else if (c == CITEMARK)
+                               break;
+                       else
+                               error("bad cite char 0%03o in pass two",c);
+               } while(1);
+               if (neg < 0) {     /* reference not found */
+                       cites[ncites].num = -1;
+                       cites[ncites].info = 0;
+                       ncites++;
+               } else {
+                       /*
+                        * Find reference n in the references
+                        */
+                       int i;
+                       for (i = 0; i < numrefs; i++){
+                               if (refinfo[i].ri_n == n){
+                                       cites[ncites].num = i;
+                                       cites[ncites].info = 0;
+                                       ncites++;
+                                       break;
+                               }
+                       }
+                       if (i == numrefs)
+                               error("citation %d not found in pass 2", n);
+               }
+               if (getch(c, ifd) != CITEEND) {
+                       for (p = infoword; c != CITEEND ; ) {
+                               *p++ = c;
+                               getch(c, ifd);
+                       }
+                       *p = 0;
+                       cites[ncites-1].info = walloc(infoword);
+               }
+               getch(c, ifd);
+       } while (c == CITEMARK);
+       ungetc(c, ifd);
+       if (ordcite)
+               qsort(cites, ncites, sizeof(struct cite), citesort);
+
+       /* now dump out values */
+       for (i = 0; i < ncites; i++) {
+               if (cites[i].num >= 0) {
+                       if (changecite){
+                               char tempcite[128];
+                               char ref[REFSIZE];
+                               struct refinfo *p;
+                               /*
+                                * rebuild the citation string,
+                                * using the current template in effect
+                                */
+                               p = &refinfo[cites[i].num];
+                               rdref(p, ref);
+                               bldcite(tempcite, cites[i].num, ref);
+                               strcat(tempcite, p->ri_disambig);
+                               if (doacite) fputs(tempcite, ofd);
+                       } else {
+                               if (doacite) fputs(refinfo[cites[i].num].ri_cite, ofd);
+                       }
+                       if (!doacite) fputs("\\&", ofd);
+               }
+               if (cites[i].info) {
+                       if (doacite) fputs(cites[i].info, ofd);
+                       if (!doacite) fputs("\\&", ofd);
+                       free(cites[i].info);
+               }
+               if (hyphen) {
+                       for (j = 1;
+                            j + i <= ncites && cites[i+j].num == cites[i].num + j;
+                            j++)/*VOID*/;
+                       if (j + i > ncites)
+                               j = ncites;
+                       else
+                               j = j + i - 1;
+               } else {
+                       j = i;
+               }
+               if (j > i + 1) {
+                       fputs("\\*(]-", ofd);
+                       i = j - 1;
+               } else if (i != ncites - 1) {
+                       fputs("\\*(],", ofd);
+               }
+               if (foot) {
+                       fn++;
+                       footrefs[fn] = cites[i].num;
+               }
+       }
+       return(fn);
 }
 
 /* pass2 - read pass 1 files entering citation */
 }
 
 /* pass2 - read pass 1 files entering citation */
@@ -449,12 +570,15 @@ int  fn, footrefs[];
                   while (echoc(c, ifd, ofd) != '\n')
                      ;
                   dumped = true;
                   while (echoc(c, ifd, ofd) != '\n')
                      ;
                   dumped = true;
-                  for (i = 0; i <= numrefs; i++)
+                  for (i = 0; i < numrefs; i++){
                      dumpref(i, ofd);
                      dumpref(i, ofd);
+                 }
                   getch(c, ifd);
                   }
          }
                   getch(c, ifd);
                   }
          }
-      if (c == CITEMARK)
+      if (c == FMTSTART)
+        changefmt(ifd);
+      else if (c == CITEMARK)
          fn = putrefs(ifd, ofd, footrefs, fn);
       else if (c != EOF)
          putc(c, ofd);
          fn = putrefs(ifd, ofd, footrefs, fn);
       else if (c != EOF)
          putc(c, ofd);
@@ -462,3 +586,17 @@ int  fn, footrefs[];
    if (dumped == false)
       bibwarning("Warning: references never dumped\n","");
 }
    if (dumped == false)
       bibwarning("Warning: references never dumped\n","");
 }
+/*
+ *     change citation format
+ */
+changefmt(ifd)
+       FILE    *ifd;
+{
+       char    c;
+       char    *to;
+       to = ncitetemplate;
+       while (getch(c, ifd) != FMTEND)
+               *to++ = c;
+       *to = 0;
+       strcpy(citetemplate, ncitetemplate);
+}