/*
        tibargs

        read argument strings for tib and tiblist
        do name formatting, printing lines, other actions common to both

                                                        */
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "tib.h"

/* global variables */
   char bibfname[120];          /* file name currently being read            */
   int  biblineno;              /* line number currently being referenced    */
   int  abbrev       = false;   /* automatically abbreviate names            */
   int  capsmcap     = false;   /* print names in caps small caps (CACM form)*/
   int  numrev       = 0;       /* number of authors names to reverse        */
   int  edabbrev     = false;   /* abbreviate editors names ?                */
   int  edcapsmcap   = false;   /* print editors in cap small caps           */
   int  ednumrev     = 0;       /* number of editors to reverse              */
   int  sort         = false;   /* sort references ? (default no)            */
   int  foot         = false;   /* footnoted references ? (default endnotes) */
   int  c0           = false;   /* references in text ? (default no)         */
   int  hyphen       = false;   /* hypenate contiguous references            */
   int  ordcite      = true;    /* order multiple citations                  */
   int  specflag     = false;   /* use special flags                         */
   int  loccit       = false;   /* use ibid and loccit in footnotes          */
   int  onepage      = false;   /* print only first page of reference        */
   int  underline    = false;   /* underline multiple references             */
   int  silent       = false;   /* run silently                              */
   int  stndout      = false;   /* output on stdout                          */
   int  inputflag    = false;   /* process input/include files              */
   char sortstr[80]  = "1";     /* sorting template                          */
   char trailstr[80] = "";      /* trailing characters to output             */
   char pfile[120];             /* private file name                         */
   char dirname[120] ="";       /* private directory name                    */
   int  personal = false;       /* personal file given ? (default no)        */
   char citetemplate[80] = "1"; /* citation template                         */
   char *words[MAXDEFS];        /* defined words                             */
   char *defs[MAXDEFS];         /* defined word definitions                  */
   long int defpos[MAXDEFS];    /* position of defined words                 */
   long int link[MAXDEFS];      /* link for linking defined words on input   */
   long int jtop = 0;           /* entry for linked list                     */
   long int wordtop = -1;       /* top of defined words array                */
   int locflag[MAXREFS];        /* loc cit ?                                 */
   int ibidflag[MAXREFS];       /* ibid ?                                    */
   char dirsp2[]=DIRSEP;        /* directory separator character             */
   char optch2[]=OPTCH;         /* option character on program calls         */
   char suffix[5] = ".tex";	/* for appending to file names               */
   int startflag = 1;		/* starting count of Flags */
   
/* where output goes */
   extern FILE *tfd;
/* reference file information */
   extern long int refspos[];
   extern int unlmark[];
   extern char reffile[];
   extern FILE *rfd;
   extern char *citestr[];
   extern int numrefs;

/* doargs - read command argument line for both tib and tiblist
            set switch values
            call rdtext on file arguments, after dumping
            default style file if no alternative style is given
*/
   int doargs(argc, argv, defstyle)
   int argc;
   char **argv, defstyle[];
{  int numfiles, i, style;
   char bibfnamet[120];
   int pipeflag = false;
   int fileflag = false;
   char *p, *q, *walloc();
   FILE *fd, *np;
   char headerline[240], fname[240];
   char *tfgets(), *ptmac, *getenv();

   if (silent == false)
      fprintf(stderr, "Processing format commands ...\n");
   numfiles = 0;
   style = true;
   ptmac = getenv("TMACLIB");
   if (ptmac == NULL)
      ptmac = TMACLIB;
   words[0] = walloc("TMACLIB");
   strcpy(headerline,ptmac);
   strcat(headerline,dirsp2);
   defs[0]  = walloc(headerline);
   wordtop++;
   link[0] = -1;
   fprintf(tfd, "%cmessage {REFERENCE FORMATTING FILES:}\n", '\\');
   fprintf(tfd, "%cdef%cTMACLIB{%s%c}\n", '\\', '\\', ptmac, dirsp2[0]);
   fprintf(tfd, "%cinput %cTMACLIB Macros.ttx\n", '\\', '\\');

   for (i = 1; i < argc; i++)
      if (argv[i][0] == optch2[0] && argv[i][1] == 'd') {
         if (argv[i][2])
         p = &argv[i][2];
      else { /* take next arg */
         i++;
         if (i == argc) {
            fprintf(stderr,"command line: illegal switch %s\n", argv[i-1]);
            clnup();
            exit(1);
            }
         p = argv[i];
         }
      strcpy(dirname,p);
      break;
      }

   for (i = 1; i < argc; i++)
      if (argv[i][0] == optch2[0]) {
         switch(argv[i][1]) {

            case 'd':  if (argv[i][2])
                          p = &argv[i][2];
                       else { /* take next arg */
                          i++;
                          if (i == argc) {
                             fprintf(stderr,
                               "command line: illegal switch %s\n", argv[i-1]);
                             clnup();
                             exit(1);
                             }
                          p = argv[i];
                          }
                       strcpy(dirname,p);
                       break;
  
            case 'j':  inputflag = true;
                       break;

            case 'n':  if (argv[i][2])
                          startflag = atoi(&argv[i][2]);
                       else { /* take next arg */
                          i++;
                          if (i == argc) {
                             fprintf(stderr,
                               "command line: illegal switch %s\n", argv[i-1]);
                             clnup();
                             exit(1);
                             }
                          startflag = atoi(argv[i]);
                          }
                       break;

            case 'p':  if (argv[i][2])
                          p = &argv[i][2];
                       else {  /* take next arg */
                          i++;
                          if (i == argc) {
                             fprintf(stderr,
                               "command line: illegal switch %s\n", argv[i-1]);
                             clnup();
                             exit(1);
                             }
                          p = argv[i];
                          }
                       strcpy(pfile, p);
                       personal = true;
                       for (p = fname, q = pfile; ; q++)
                          if (*q == ',' || *q == 0) {
                             *p = 0;
                             np = fopen( fname, "r");
                             if (np == NULL) {
                                fprintf(stderr, "Can't open index %s\n",fname);
                                clnup();
                                exit(1);
                                }
                             else {
                                tfgets(headerline,240,np);      
                                fclose(np);
                                chkindex(fname, headerline, true);
                                }
                             if (*q == 0)
                                break;
                             p = fname;
                             }
                          else *p++ = *q;
                       break;

            case 's':  style = false;    /*fall through*/
            case 'i':  if (argv[i][2])
                          p = &argv[i][2];
                       else { /* take next arg */
                          i++;
                          if (i == argc) {
                             fprintf(stderr,
                               "command line: illegal switch %s\n", argv[i-1]);
                             clnup();
                             exit(1);
                             }
                          p = argv[i];
                          }
                       incfile(p);
                       break;

            case 'x':  stndout = true;
                       break;

            case 'z':  silent = true;
                       break;

            case '|':  pipeflag = true;
                       stndout = true;
                       break;

            default:   fprintf(stderr, "command line: invalid switch %s\n",
                                  argv[i]);
                       clnup();
                       exit(1);
            }
         }
      else { /* file name */
         numfiles++;
         fileflag = true;
         if (style) {
            style = false;
            incfile( defstyle );
            }
         strcpy(bibfname, argv[i]);
         fd = fopen(argv[i], "r");
         if (fd == NULL) {
               strcat(bibfname,suffix);
            fd=fopen(bibfname, "r");
            if (fd == NULL) {
               fprintf(stderr, "can't open %s or %s\n", argv[i], bibfname);
               clnup();
               exit(1);
               }
            }
         if (stndout == false && silent == false) {
            fprintf(stderr, "Reading input document file %s and looking up references ...\n", bibfname);
            }
         rdtext(fd);
         fclose(fd);
      }
   if (style) incfile( defstyle );
   if (fileflag == false)          /* no input file on command line */
      if (pipeflag == true) {
         strcpy(bibfname, "<stdin>");
         rdtext(stdin);
         numfiles++;
         }
      else {
         fprintf(stderr, "Enter input file: ");
         scanf("%s", bibfnamet);
         numfiles++;
         strcpy(bibfname, bibfnamet);
         fd = fopen(bibfnamet, "r");
         if (fd == NULL) {
            strcat(bibfname, ".tex");
            fd=fopen(bibfname, "r");
            if (fd == NULL) {
               fprintf(stderr, "can't open %s or %s\n",
                    bibfnamet, bibfname);
               clnup();
               exit(1);
               }
            }
         if (stndout == false && silent == false) {
            fprintf(stderr, "Reading input document file %s and looking up references ...\n", bibfname);
            }
         rdtext(fd);
         fclose(fd);
         }
   return(numfiles);
}

/* chkindex - check if index is up to date */
   int chkindex(indx, header, pflag)
   char *indx;
   char header[240];
   int pflag;
{  char *c, *q, *p;
   char indx0[240], indx00[80], *indx1, indx11[240];
   char *rindex();
   struct stat buf;
   FILE *np;
   int i, j, qflag;
   time_t timefile, timeindx;

   stat(indx, &buf);
   timeindx = buf.st_mtime;
   strcpy (indx0,indx);
   c = rindex(indx0, dirsp2[0]);
   if (c == NULL)
      indx00[0] = '\0';
   else {
      *++c = '\0';
      strcpy (indx00, indx0);
      }
   strcpy (indx0,indx00);
   qflag = true;
   for (q = header ; *q;) {
      for (;*q == ' ';q++);
      if (*q == '\0') break;
      for (indx1 = q; *q && *q != ' '; q++);
      if (*q)
         *q = '\0';
      else
         qflag = false;
      if (*indx1 != dirsp2[0]) {
         strcat (indx0,indx1);
         strcpy (indx11,indx0);
         }
      np = fopen(indx11,"r");
      if (np == NULL) {
         fprintf(stderr,"Cannot locate reference file %s\n", indx11);
         clnup();
         exit(1);
         }
      strcpy (indx0, indx00);
      stat(indx11, &buf);
      timefile = buf.st_mtime;
      if (qflag == true)
         *q = ' ';
      if (timeindx < timefile) {
         fprintf(stderr,"Index %s not up to date\n", indx);
         if (pflag)
            fprintf(stderr,"Use tibdex (in appropriate directory) with reference file(s)%s\n",header);
         else
            fprintf(stderr,"   Use: tibdex%s\n",header);
         clnup();
         exit(1);
         }
      }
   }
 
/* outfname - make output file name */
   char *outfname(mp)
   char *mp;
{  char *q;

   for (q=mp; *q; q++);
   if (*--q == 'x')
      if (*--q == 'e')
         if (*--q == 't')
            if (*--q == '.')
                *q='\0';
    strcat (mp, "-t.tex");
    return (mp);
}

/* incfile - read in an included file  */
incfile(np)
   char *np;
{  char name[120];
   FILE *fd;
   char *p, line[LINELENGTH], dline[LINELENGTH], word[80], *tfgets();
   int  i, j, k, getwrd();
   int located, j1;
   char *ptmac, *getenv();

   ptmac = getenv("TMACLIB");
   if (ptmac == NULL)
      ptmac = TMACLIB;
   strcpy(bibfname, np);
   fd = fopen(np, "r");
   if (fd == NULL && *np != dirsp2[0]) {
      strcpy(name, np);
      strcat(name, ".tib");
      strcpy(bibfname, name);
      fd = fopen(name, "r");
      }
   if (fd == NULL && *np != dirsp2[0])
      if (dirname[0] != '\0') {
         strcpy(name, dirname);
         strcat(name, dirsp2);
         strcat(name, np);
         strcpy(bibfname, name);
         fd = fopen(name, "r");
         }
   if (fd == NULL && *np != dirsp2[0])
      if (dirname[0] != '\0') {
         strcpy(name, dirname);
         strcat(name, dirsp2);
         strcat(name, np);
         strcat(name, ".tib");
         strcpy(bibfname, name);
         fd = fopen(name, "r");
         }
   if (fd == NULL && *np != dirsp2[0]) {
      strcpy(name, ptmac);
      strcat(name, dirsp2);
      strcat(name, np);
      strcpy(bibfname, name);
      fd = fopen(name, "r");
      }
   if (fd == NULL && *np != dirsp2[0]) {
      strcpy(name, ptmac);
      strcat(name, dirsp2);
      strcat(name, np);
      strcat(name, ".tib");
      strcpy(bibfname, name);
      fd = fopen(name, "r");
      }
   if (fd == NULL) {
      bibwarning("%s: can't open\n", np);
      clnup();
      exit(1);
      }

   /* now go off and process file */
   fprintf(tfd, "%cmessage {(%s}\n", '\\', np);
   biblineno = 1;
   while (tfgets(line, LINELENGTH, fd) != NULL) {
      biblineno++;
      switch(line[0]) {

         case '#': break;

         case 'A': for (p = &line[1]; *p && *p != ' '; p++) {
                      if (*p == 'A')
                         abbrev = true;
                      else if (*p == 'X')
                         capsmcap = true;
                      else if (*p == 'R') {
                         if (isdigit(*(p+1)))
                            numrev = atoi(p+1);
                         else
                            numrev = 1000;
                         }
                      }
                   break;

         case 'C': for (p = &line[1]; *p == ' '; p++) ;
                   strcpy(citetemplate, p);
                   for (p=citetemplate; *p && *p != ' '; p++);
                   *p=0;
                   if (citetemplate[0] == '0') c0 = true;
                   break;

         case 'D': if ((k = getwrd(line, 1, word)) == 0)
                      error("word expected in definition");

/* this creates a linked list for use in sortdefs and expnd2
   but it is fortran style, not good c style -- fix later     */

                   j=jtop;
                   for (located = false; located == false; ) {
                      i=strcmp(word, words[jtop]);
                      if (i == 0) {
                         located = true;
                         break;
                      }
                      if (i > 0) {
                         wordtop++;
                         if (wordtop > MAXDEFS)
                            error("too many definitions:");
                         link[wordtop] = jtop;
                         jtop = wordtop;
                         j = jtop;
                         words[wordtop] = walloc(word);
                         located = true;
                         break;
                      }
                      while (link[j] >= 0) {
                         j1 = link[j];
                         i = strcmp(word, words[j1]);
                         if (i == 0) {
                            j = j1;
                            located = true;
                            break;
                         }
                         if (i > 0) {
                            wordtop++;
                            if (wordtop > MAXDEFS)
                               error("too many definitions:");
                            link[wordtop] = j1;
                            link[j] = wordtop;
                            j = wordtop;
                            words[wordtop] = walloc(word);
                            located = true;
                            break;
                         }
                         j = j1;
                      }
                      if (located == false) {
                         wordtop++;
                         if (wordtop > MAXDEFS)
                            error("too many definitions:");
                         link[wordtop] = -1;
                         link[j] = wordtop;
                         j = wordtop;
                         words[wordtop] = walloc(word);
                         located = true;
                         break;
                      }
                   }
                   for (p = &line[k]; *p == ' '; p++) ;
                   for (strcpy(dline, p); dline[strlen(dline)-1] == '\\'; ){
                       dline[strlen(dline)-1] = '\n';
                       if (tfgets(line, LINELENGTH, fd) == NULL) break;
                       strcat(dline, line);
                       }
                   defs[j] = walloc(dline);
                   break;

         case 'E': for (p = &line[1]; *p && *p != ' '; p++) {
                      if (*p == 'A')
                         edabbrev = true;
                      else if (*p == 'X')
                         edcapsmcap = true;
                      else if (*p == 'R') {
                         if (isdigit(*(p+1)))
                            ednumrev = atoi(p+1);
                         else
                            ednumrev = 1000;
                         }
                      }
                   break;

         case 'f': foot = true;
                   hyphen = false;
                   break;

         case 'F': specflag = true;
                   break;

         case 'H': hyphen = ordcite = true;
                   break;

         case 'I': for (p = &line[1]; *p == ' '; p++);
                   expnd1(p);
                   incfile(p);
                   break;

         case 'L': loccit = true;
                   break;

         case 'N': for (p = &line[1]; *p == ' '; p++);
                      if (*p == 'A')
                         abbrev = false;
                      else if (*p == 'F')
                         specflag = false;
                      else if (*p == 'H')
                         hyphen = false;
                      else if (*p == 'O')
                         ordcite = false;
                      else if (*p == 'R')
                         numrev = 0;
                      else if (*p == 'S')
                         sort = false;
                      else if (*p == 'X')
                         capsmcap = false;
                   break;
         case 'O': ordcite = true;
                   break;

         case 'P': onepage = true;
                   break;

         case 'S': sort = true;
                   for (p = &line[1]; *p == ' '; p++) ;
                   strcpy(sortstr, p);
                   for (p=sortstr; *p && *p != ' '; p++);
                   *p=0;
                   break;

         case 'T': for (p = &line[1]; *p == ' '; p++) ;
                   strcpy(trailstr, p);
                   for (p=trailstr; *p && *p != ' '; p++);
                   *p=0;
                   break;

         case 'U': underline = true;
                   break;

         default:  fprintf(tfd, "%s\n", line);
                   while (fgets(line, LINELENGTH, fd) != NULL)
                      fputs(line, tfd);
                   fprintf(tfd, "%cmessage {)}", '\\');
                   return;
         }

   }
   /* close up */
   fprintf(tfd, "%cmessage{)}", '\\');
   fclose(fd);
}

/* bibwarning - print out a warning message */
  bibwarning(msg, arg)
  char *msg, *arg;
{
  fprintf(stderr, "`%s', line %d: ", bibfname, biblineno);
  fprintf(stderr, msg, arg);
}

/* error - report unrecoverable error message */
  error(str)
  char str[];
{
  bibwarning("%s\n", str);
  clnup();
  exit(1);
}

#ifdef READWRITE
/*
** fixrfd( mode ) -- re-opens the rfd file to be read or write, 
**      depending on the mode.  Uses a static int to save the current mode
**      and avoid unnecessary re-openings.
*/
fixrfd( mode )
register int mode;
{
	static int cur_mode = WRITE;    /* rfd open for writing initially */

	if (mode != cur_mode)
	{
		rfd = freopen(reffile, ((mode == READ)? "r" : "a"), rfd);
		cur_mode = mode;
		if (rfd == NULL)
		      error("Hell!  Couldn't re-open reference file");
	}
}
#endif


/* tfgets - fgets which trims off newline */
   char *tfgets(line, n, ptr)
   char line[];
   int  n;
   FILE *ptr;
{  char *p;

   p = fgets(line, n, ptr);
   if (p == NULL)
      return(NULL);
   else
      for (p = line; *p; p++)
         if (*p == '\n')
            *p = 0;
   return(line);
}

/* getwrd - place next word from in[i] into out */
int getwrd(in, i, out)
   char in[], out[];
   int i;
{  int j;

   j = 0;
   while (in[i] == ' ' || in[i] == '\n' || in[i] == '\t')
      i++;
   if (in[i])
      while (in[i] && in[i] != ' ' && in[i] != '\t' && in[i] != '\n')
         out[j++] = in[i++];
   else
      i = 0;    /* signals end of in[i..]   */
   out[j] = 0;
   return (i);
}

/* walloc - allocate enough space for a word */
char *walloc(word)
   char *word;
{  char *i, *malloc();
   i = malloc(1 + strlen(word));
   if (i == NULL)
      error("out of storage");
   strcpy(i, word);
   return(i);
}

/* isword - see if character is legit word char */
int iswordc(c)
char c;
{
   if (isalnum(c) || c == '&' || c == '_')
      return(true);
   return(false);
}

/* expnd1 - expand reference, replacing defined words, scrunching spaces */
   expnd1(line)
   char *line;
{  char line2[REFSIZE], word[LINELENGTH], *p, *q, *w;
   int  replaced, i;

   replaced  = true;
   while (replaced) {
      replaced = false;
      p = line;
      q = line2;
      while (*p) {
         if (isalnum(*p)) {
            for (w = word; *p && iswordc(*p); )
               *w++ = *p++;
            *w = 0;
            for (i = 0; i <= wordtop; i++)
               if (strcmp(word, words[i]) == 0) {
                  strcpy(word, defs[i]);
                  replaced = true;
                  break;
                  }
            for (w = word; *w; )
               *q++ = *w++;
            }
         else
            *q++ = *p++;
         }
      *q = 0;
      p = line;
      q = line2;
      while (*q != 0) {
         if (*q != ' ')
            *p++ = *q++;
         else
            q++;
         }
      *p = 0;
      }
}

/* expnd2 - expand reference, replacing defined words */
   expnd2(line)
   char *line;
{  char line2[REFSIZE], word[LINELENGTH], *p, *q, *w;
   int  replaced, toolong, i;

   toolong = false;		/* flag to indicate reference is too long */
   replaced  = true;
   while (replaced) {
      replaced = false;
      p = line;
      q = line2;
      while (*p) {
         if (*p != '|')
	   if (q - line2 >= REFSIZE-1){
	     toolong = true;	/* reference entry is too long */
	     *(q-1) = '\n';	/* make entry end with \n\0 */
	     break;
	   } else
	     *q++ = *p++;
         else {
            *p++;
            for (w = word; *p && *p != '|'; *w++ = *p++);
            *w = 0;
            if (locdef(word) == false) 
               fprintf(stderr,"word %s not defined in definition list\n",
                  word);
            else
               replaced = true;
            if (*p == '|')
               p++;
            for (w = word; *w; *q++ = *w++)
	      if (q - line2 >= REFSIZE-1){
		toolong = true; /* reference entry is too long */
		*(q-1) = '\n';	/* make entry end with \n\0 */
		break;
	      }
	  }
       }
   *q = 0;
   p = line;
   q = line2;
   while (*p++ = *q++);
   }
   if(toolong && silent == false) { /* print truncation warning */
     fprintf(stderr,
     "Truncated following reference after expanding defined words: \n");
     fprintf(stderr,"-------------\n%s\n-------------\n",line);
   }
}

/* locdef - locate a definition */
   int locdef(word)
   char *word;
{  long int lower, upper, mid, i;
   int strcmp();
   char *w, *w1;

   lower = 0;
   upper = wordtop;
   if (strcmp(word, words[defpos[lower]]) == 0) {
      for (w = word, w1 = defs[defpos[lower]]; *w1; *w++ = *w1++);
      *w = 0;
      return(true);
      }
   if (strcmp(word, words[defpos[upper]]) == 0) {
      for (w = word, w1 = defs[defpos[upper]]; *w1; *w++ = *w1++);
      *w = 0;
      return(true);
      }
   while (lower+1 < upper) {
      mid = (lower + upper)/2;
      i = strcmp(word, words[defpos[mid]]);
         if (i == 0) {
         for (w = word, w1 = defs[defpos[mid]]; *w1; *w++ = *w1++);
         *w = 0;
         return(true);
         }
      if (i > 0)
         lower = mid;
      else
         upper = mid;
      }
   return (false);
}    

/* rdref - read text for an already cited reference */
   rdref(i, ref)
   long int  i;
   char ref[REFSIZE];
{
   ref[0] = 0;
#ifdef READWRITE
   fixrfd( READ );                      /* fix access mode of rfd, if nec. */
#endif
   fseek(rfd, i, 0);
   fread(ref, 1, REFSIZE, rfd);
}

/* breakname - break a name into first and last name */
   breakname(line, first, last)
   char line[], first[], last[];
{  char *p, *q, *r, *t, *f;

   for (t = line; *t != '\n'; t++);
   for (t--; isspace(*t); t--);

   /* now strip off last name */
   for (q = t; isspace(*q) == 0 || ((*q == ' ') & (*(q-1) == '\\')); q--) {
      if (*q == '}') {
         while (*q != '{') {
            q--;
            if (q == line) {
               fprintf (stderr, "bad brackets in string %s in references\n",
                   line);
               clnup();
               exit(1);
            }
         }
      }
      if (q == line)
         break;
   }
   f = q;
   if (q != line) {
      q++;
      for (; isspace(*f); f--);
      f++;
      }

   /* first name is start to f, last name is q to t */

   for (r = first, p = line; p != f; )
      *r++ = *p++;
   *r = 0;
   for (r = last, p = q, t++; q != t; )
      *r++ = *q++;
   *r = 0;

}

/* match - see if string1 is a substring of string2 (case independent)*/
   int match(str1, str2)
   char str1[], str2[];
{  int  i, j;
   char a, b;

   for (i = 0; str2[i]; i++) {
      for (j = 0; str1[j]; j++) {
         if (isupper(a = str2[i+j]))
            a = (a - 'A') + 'a';
         if (isupper(b = str1[j]))
            b = (b - 'A') + 'a';
         if (a != b)
            break;
         }
      if (str1[j] == 0)
         return(true);
      }
   return(false);
}

/* scopy - append a copy of one string to another */
   char *scopy(p, q)
   char *p, *q;
{
   while (*p++ = *q++)
      ;
   return(--p);
}

/* makecites - make citation strings */
   makecites(citestr)
   char *citestr[];
{  char ref[REFSIZE], tempcite[100], *malloc();
   int  i;

   for (i = 0; i <= numrefs; i++) {
      rdref(refspos[i], ref);
      bldcite(tempcite, i, ref);
      citestr[i] = malloc(2 + strlen(tempcite)); /* leave room for disambig */
      if (citestr[i] == NULL)
         error("out of storage");
      strcpy(citestr[i], tempcite);
      }
}

/* sortdefs - make array of pointers to defined words */
   sortdefs()
{  long int i, j;

   i = wordtop;
   for (j = jtop; j >= 0; j = link[j]) {
      defpos[i] = j;
      i--;
   }
}

/* rcomp1 - revised reference comparison routine for qsort utility */
   int rcomp1(ap, bp)
   long int *ap, *bp;
{  char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD];
   char alpha1[REFSIZE], alpha2[REFSIZE];
   char *p, *q, *getfield();
   int  neg, res;
   int n, m1, m2, num;
   int getname();
   char last1[MAXFIELD], last2[MAXFIELD], first1[MAXFIELD], first2[MAXFIELD];
   int alphabits();
   char *fstcap();

   rdref(*ap, ref1);
   rdref(*bp, ref2);
   for (p = sortstr, q=p; *p ; p=q) {
      if (*p == '-') {
         p++;
         neg = true;
         }
      else
         neg = false;
      res=0;
      if (*p == 'A') {
         p++;
         if (isdigit(*p))
             for (num=0; isdigit(*p); p++)
                num=10*num+(*p-'0');
         else
             num=100;
         q=p;
         for (n=1; n <= num; n++) {
             m1=getname (n, last1, first1, ref1);
             m2=getname (n, last2, first2, ref2);
             if (m1 == 0 && m2 == 0)
                break;
             alphabits(alpha1, last1);
             alphabits(alpha2, last2);
/*             res = strcmp (fstcap(alphabits(last1)), fstcap(alphabits(last2)));
             alpha11 = fstcap(alphastring1);
             alpha21 = fstcap(alphastring2);*/
             res = strcmp (fstcap(alpha1), fstcap(alpha2));
             if (res) break;
             alphabits(alpha1, first1);
             alphabits(alpha2, first2);
             res = strcmp (fstcap(alpha1), fstcap(alpha2));
             if (res != 0) break;
          }
      }
      else {
          q++;
          getfield(p, field1, ref1);
          getfield(p, field2, ref2);
          res = strcmp (field1, field2);
      }
      if (neg)
         res = - res;
      if (res != 0)
         break;
   }
   if (res == 0) {
      if (ap < bp)
         res = -1;
      else
         res = 1;
   }
   return(res);
}

/* alphabits - reduce string to alpha characters */
   alphabits(stringout, stringin)
   char *stringin, *stringout;
{  char *p, *q;

   q = stringout;
   p = stringin;
   while (*p) {
      if (isalpha(*p) || isspace(*p))
         *q++ = *p++;
      else if (*p == '{') {
         for (; *p && *p != '}'; p++);
         if (*p == 0) {
            fprintf(stderr, "bad brackets in string %s in references\n", 
               stringin);
            clnup();
            exit(1);
            }
         else {
            for (p--; isalpha(*p); p--);
            for (p++; isalpha(*p); *q++ = *p++);
            }
         }
       else p++;
       }
   *q = 0;
}

/* fstcap - find first capital letter in string */
   char *fstcap(string)
   char *string;
{  char *ptr;

   for(ptr=string; *ptr && (isupper(*ptr) == 0); ptr++);
   return (ptr);
}

/* capbrackets - find if string in brackets is capital, also capitalize it */
   capbrackets(stringout, stringin)
   char *stringout, *stringin;
{  char *p, *q;
   int cap;

   cap = false;
   q = stringout;
   p = stringin;
   for (; *p && *p != '}'; *q++ = *p++);
   if (*p == 0) {
      fprintf(stderr, "bad brackets in string %s in references\n", 
         stringin);
      clnup();
      exit(1);
      }
   *q++ = '}';
   *q = 0;
   q--;
   for (q--; isalpha(*q); q--) {
      if (isupper (*q))
         cap = true;
      else {
         cap = false;
         *q = (*q - 'a') + 'A';
         }
      }
   return (cap);
}

/* undrline - underline successive identical authors */
   undrline()
{  char line[REFSIZE], line1[REFSIZE], last[REFSIZE], first[REFSIZE];
   char ref[REFSIZE];
   int m, i;

   line1[0] = 0;
   for (m=numrefs; m >= 0; m--) {
      rdref(refspos[m], ref);
      line[0] = 0;
      for (i=1; getname(i, last, first, ref); i++) {
         strcat(line, last);
         strcat(line, first);
         }
      if (strcmp(line, line1) == 0)
         unlmark[m] = true;
      else
         unlmark[m] = false;
      strcpy(line1, line);
   }
}


/* bldcite - build a single citation string */
   bldcite(cp, i, ref)
   char *cp, ref[];
   int  i;
{  char *p, *q, c, *fp, field[REFSIZE], *getfield(), *aabet(), *nmdt();

   getfield("F", field, ref);
   if (field[0] != 0 && specflag)
      for (p = field; *p; p++)
         *cp++ = *p;
   else {
      p = citetemplate;
      field[0] = 0;
      while (c = *p++) {
         if (isalpha(c)) {                      /* field name   */
            q = getfield(p-1, field, ref);
            if (q != 0) {
               p = q;
               cp=scopy(cp, "\\Citebreak ");
               for (fp = field; *fp; )
                  *cp++ = *fp++;
               }
            }
         else if (c == '0') {                   /* empty citation */
            *cp = '\0';
	  }
         else if (c == '1') {                   /* numeric  order */
            sprintf(field, "%d", startflag + i);
            for (fp = field; *fp; )
               *cp++ = *fp++;
            }
         else if (c == '2')                     /* alternate alphabetic */
            cp = aabet(cp, ref);
         else if (c == '3')                     /* names */
            cp = nmdt(cp, ref);
/*       else if (c == '4')          here is how to add new styles */
/*       else if (c == '{') { 
            while (*p != '}')
               if (*p == 0)
                  error("unexpected end of citation template");
               else
                  *cp++ = *p++;
            p++;
            }    */
         else if (c == '<') {
            while (*p != '>') {
               if (*p == 0)
                  error("unexpected end of citation template");
               else
                  *cp++ = *p++;
               }
            p++;
            }
         else if (c != '@')
            *cp++ = c;
         }
      }
   *cp++ = 0;
}

/* alternate alphabetic citation style */
   char *aabet(cp, ref)
   char *cp, ref[];
{  char field[REFSIZE], temp[100], *np, *fp;
   char string11[80], string12[80], string13[80], string2[80], string3[80];
   char bracketstring[80];
   int getname(), i;

   if (getname(1, field, temp, ref)) {
      fp = field;
      for (np = string11; *fp; fp++) {
         if (isupper(*fp)) {
            *np++ = *fp;
            break;
            }
         else if (*fp == '{') {
            if (capbrackets(bracketstring, fp) == 0)
               for (; *fp != '}'; fp++);
            else {
               for (; *fp != '}'; *np++ = *fp++);
               *np++ = '}';
               break;
               }
            }
         }
      if (*fp) fp++;
      *np = 0;
      for (np = string12; *fp && isalpha(*fp) == 0 && *fp != '{'; 
         *np++ = *fp++);
      if (*fp != '{')
         *np++ = *fp;
      else {
         capbrackets(bracketstring, fp);
         for (; *fp != '}'; *np++ = *fp++);
         *np++ = '}';
         }
      if (*fp) fp++;
      *np = 0;
      for (np = string13; *fp && isalpha(*fp) == 0 && *fp != '{'; 
         *np++ = *fp++);
      if (*fp != '{')
         *np++ = *fp;
      else {
         capbrackets(bracketstring, fp);
         for (; *fp != '}'; *np++ = *fp++);
         *np++ = '}';
         }
      *np = 0;
      }
   if (getname(2, field, temp, ref) == 0) {
      strcpy (field, string11);
      strcat (field, string12);
      strcat (field, string13);
      }
   else {
      fp = field;
      for (np = string2; *fp; fp++) {
         if (isupper(*fp)) {
            *np++ = *fp;
            break;
            }
         if (*fp == '{') {
            if (capbrackets(bracketstring, fp) == 0)
               for (; *fp != '}'; fp++);
            else {
               for (; *fp != '}'; *np++ = *fp++);
               *np++ = '}';
               break;
               }
            }
         }
      *np = 0;
      if (getname(3, field, temp, ref) == 0) {
         strcpy (field, string11);
         strcat (field, string12);
         strcat (field, string2);
         }
      else {
         fp = field;
         for (np = string3; *fp; fp++) {
            if (isupper(*fp)) {
               *np++ = *fp;
               break;
               }
            if (*fp == '{') {
               if (capbrackets(bracketstring, fp) == 0)
                  for (; *fp != '}'; fp++);
               else {
                  for (; *fp != '}'; *np++ = *fp++);
                  *np++ = '}';
                  break;
                  }
               }
            }
         *np = 0;
         strcpy (field, string11);
         strcat (field, string2);
         strcat (field, string3);
         }
      }
   for (i=0; field[i]; i++)
      *cp++ = field[i];
   return (cp);
}

/* names style
        if 1 author - last name date
        if 2 authors - last name and last name date
        if 3 authors - last name, last name and last name date
        if 4 or more authors - last name et al. date */
   char *nmdt(cp, ref)
   char *cp, ref[];
{  char name1[100], name2[100], name3[100], temp[100], *fp;
   int getname();

   if (getname(1, name1, temp, ref)) {
      for (fp = name1; *fp; )
         *cp++ = *fp++;
      if (getname(4, name3, temp, ref)) {
         for (fp = " et al."; *fp; )
            *cp++ = *fp++;
         }
      else if (getname(2, name2, temp, ref)) {
         if (getname(3, name3, temp, ref)) {
            for (fp = "\\Namecomma "; *fp; )
               *cp++ = *fp++;
            for (fp = name2; *fp; )
               *cp++ = *fp++;
            for (fp = "\\Nameandd "; *fp; )
               *cp++ = *fp++;
            for (fp = name3; *fp; )
               *cp++ = *fp++;
            }
         else {
            for (fp = "\\Nameand "; *fp; )
               *cp++ = *fp++;
            for (fp = name2; *fp; )
               *cp++ = *fp++;
            }
         }
    }
return(cp);
}

/* getfield - get a single field from reference */
   char *getfield(ptr, field, ref)
   char *ptr, field[], ref[];
{  char *p, *q, temp[100];
   int  n, len, i, getname();

   field[0] = 0;
   if (*ptr == 'A')
      getname(1, field, temp, ref);
   else
      for (p = ref; *p; p++)
         if (*p == '%' && *(p+1) == *ptr) {
            for (p = p + 2; *p == ' '; p++)
               ;
            for (q = field; (*p != '\n') && (*p != '\0'); )
               *q++ = *p++;
            *q = 0;
            break;
            }
   n = 0;
   len = strlen(field);
   if (*++ptr == '-') {
      for (ptr++; isdigit(*ptr); ptr++)
         n = 10 * n + (*ptr - '0');
      if (n > len)
         n = 0;
      else
         n = len - n;
      for (i = 0; field[i] = field[i+n]; i++)
         ;
      }
   else if (isdigit(*ptr)) {
      for (; isdigit(*ptr); ptr++)
         n = 10 * n + (*ptr - '0');
      if (n > len)
         n = len;
      field[n] = 0;
      }

   if (*ptr == 'u') {
      ptr++;
      for (p = field; *p; p++)
         if (islower(*p))
            *p = (*p - 'a') + 'A';
      }
   else if (*ptr == 'l') {
      ptr++;
      for (p = field; *p; p++)
         if (isupper(*p))
            *p = (*p - 'A') + 'a';
      }
   return(ptr);
}

/* getname - get the nth name field from reference, breaking into
             first and last names */
   int getname(n, last, first, ref)
   int  n;
   char last[], first[], ref[];
{  char *p;
   int  m;

   last[0]='\0';
   first[0]='\0';
   m = n;
   for (p = ref; *p; p++)
      if (*p == '%' & *(p+1) == 'A') {
         n--;
         if (n == 0) {
            for (p = p + 2; *p == ' '; p++) ;
            breakname(p, first, last) ;
            return(true);
            }
         }

   if (n == m)          /* no authors, try editors */
      for (p = ref; *p; p++)
         if (*p == '%' & *(p+1) == 'E') {
            n--;
            if (n == 0) {
               for (p = p + 2; *p == ' '; p++) ;
               breakname(p, first, last) ;
               return(true);
               }
            }

   if (n == m && n == 1) {        /* no editors, either, try institution */
      first[0] = last[0] = '\0';
      getfield("I", last, ref);
      if (last[0] != '\0')
         return(true);
      }

   return(false);
}

/* disambiguate - compare adjacent citation strings, and if equal, add
                  single character disambiguators */
   disambiguate()
{  int i, j;
   char adstr[2];

   for (i = 0; i < numrefs; i = j) {
      j = i + 1;
      if (strcmp(citestr[i], citestr[j])==0) {
         adstr[0] = 'a'; adstr[1] = 0;
         for (j = i+1; strcmp(citestr[i], citestr[j]) == 0; j++) {
            adstr[0] = 'a' + (j-i);
            strcat(citestr[j], adstr);
            if (j == numrefs)
               break;
            }
         adstr[0] = 'a';
         strcat(citestr[i], adstr);
         }
     }
}


/* bldname - build a name field
             doing abbreviations, reversals, and caps/small caps
*/
   bldnm1(first, last, name, reverse)
   char *first, *last, name[];
   int reverse;
{
   char newfirst[120], newlast[120], *p, *q, *f, *l, *scopy();
   int  flag;

   if (abbrev) {
      p = first;
      q = newfirst;
      flag = false;
      while (*p) {
         while (*p == ' ')
            p++;
         if (*p == 0)
            break;
         if (isupper(*p)) {
            if (flag)           /* between initial gap */
               q = scopy(q, "\\Initgap ");
            flag = true;
            *q++ = *p;
            q = scopy(q, "\\Initper ");
            }
         if (*++p == '.')
            p++;
         else while (*p != 0 && ! isspace(*p))
            p++;
         }
      *q = 0;
      f = newfirst;
      }
   else
      f = first;

   if (capsmcap) {
      p = last;
      q = newlast;
      flag = 0;  /* 1 - printing cap, 2 - printing small */
      while (*p)
         if (islower(*p)) {
            if (flag != 2)
               q = scopy(q, "\\bgroup\\Smallcapsfont ");
            flag = 2;
            *q++ = (*p++ - 'a') + 'A';
            }
         else {
            if (flag == 2)
               q = scopy(q, "\\egroup ");
            flag = 1;
            *q++ = *p++;
            }
      if (flag == 2)
         q = scopy(q, "\\egroup ");
      *q = 0;
      l = newlast;
      }
   else
      l = last;

   if (f[0] == 0)
      sprintf(name, "%s\n", l);
   else if (reverse)
      sprintf(name, "%s%cRevcomma %s\n", l, '\\', f);
   else
      sprintf(name, "%s %s\n", f, l);
}

/* capssmallcaps - put field in capssmallcaps */
   capssmallcaps(stringout, stringin)
   char *stringout, *stringin;
{  char *p, *q, *scopy();
   int flag, bflag;
   char bracketfield[REFSIZE];

   p = stringin;
   q = stringout;
   *q = 0;
   flag = 0;  /* 1 - printing cap, 2 - printing small */
   while (*p) {
      if (*p == '\\')
         *p++;
      if (*p == ' ') {
         if (flag == 2)
            q = scopy(q, "\\egroup{}");
         flag = 1;
/*         *q++ = '\\';*/
         *q++ = ' ';
         p++;
         }
      if (*p == '~') {
         if (flag == 2)
            q = scopy(q, "\\egroup{}");
         flag = 1;
         *q++ = *p++;
         }
      if (*p == '{')
         bflag = capbrackets(bracketfield, p);
      else
         bflag = 1;
      if (islower(*p) || bflag == 0) {
         if (flag != 2)
            q = scopy(q, "\\bgroup\\Smallcapsfont ");
         flag = 2;
         if (*p == '{') {
            q = scopy(q, bracketfield);
            for (; *p != '}'; p++);
            p++;
            }
         else
            *q++ = (*p++ - 'a') + 'A';
         }
      else {
         if (flag == 2)
            q = scopy(q, "\\egroup{}");
         flag = 1;
         if (*p == '{') {
            q = scopy(q, bracketfield);
            for (; *p != '}'; p++);
            p++;
            }
         else
            *q++ = *p++;
         }
      }
   if (flag == 2)
      q = scopy(q, "\\egroup{}");
   *q = 0;
}

   bldname(first, last, name, reverse, capsmcap)
   char *first, *last, name[];
   int reverse, capsmcap;
{
   char newfirst[120], newlast[120], *p, *q, *f, *f1, *l, *scopy();
   char newnewfirst[120];
   char bracketfield[20];
   int  flag;
   int hflag, bflag;

   if (abbrev) {
      p = first;
      q = newfirst;
      flag = false;
      hflag = false;
      bflag = false;
      while (*p) {
         while (*p == ' ')
            p++;
         if (*p == '{')
            bflag = capbrackets(bracketfield, p);
         if (isupper(*p) || bflag) {
            if (flag && hflag)           /* between initial gap */
               q = scopy(q, "\\Initgap ");
            flag = true;
            if (bflag) {
               for (; *p != '}'; *q++ = *p++);
               bflag = false;
               }
            *q++ = *p;
            for (p++;; p++) {
               if (isupper(*p)) {
                  hflag = true;
                  break;
                  }
               else if (*p == '-' || *p == '\'') {
                  hflag = false;
                  *q++ = *p++;
                  break;
                  }
               else if (*p == '.' ) {
                  hflag = true;
                  q = scopy(q, "\\Initper ");
                  p++;
                  break;
                  }
               else if (*p == ' ' ) {
                  hflag = true;
                  q = scopy(q, "\\Initper ");
                  p++;
                  break;
                  }
               else if (*p == '~') {
                  hflag = true;
                  q = scopy(q, "\\Initper ");
                  p++;
                  break;
                  }
               else if (*p == 0) {
                  q = scopy(q, "\\Initper ");
                  break;
                  }
               else if (*p == '{') {
                  bflag = capbrackets(bracketfield, p);
                     if (bflag) break;
                     else
                        for (; *p != '}'; p++);
                  }
               }
            }
         else
            *q++ = *p++;
         }
      *q = 0;
      f1 = newfirst;
      }
   else
      f1 = first;

   if (capsmcap) {
      capssmallcaps(newlast,last);
      l = newlast;
      if (abbrev == 0) {
         capssmallcaps(newnewfirst,f1);
         f = newnewfirst;
         }
      else
         f = f1;
      }
   else {
      f = f1;
      l = last;
      }
   if (f[0] == 0)
      sprintf(name, "%s\n", l);
   else if (reverse)
      sprintf(name, "%s%cRevcomma %s\n", l, '\\', f);
   else
      sprintf(name, "%s %s\n", f, l);
}

/* prtauth - print author or editor field */
   prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev)
   char c, *line;
   int  num, max, abbrev, capsmcap, numrev;
   FILE *ofd;
{  char first[LINELENGTH], last[LINELENGTH];
   char *s1;
  
   if (num <= numrev || abbrev || capsmcap) {
      breakname(line, first, last);
      bldname(first, last, line, num <= numrev, capsmcap);
      }
   for (s1=line;*s1!='\0';s1++) if (*s1=='\n') *s1='\0';
   if (num == 1) {
      fprintf(ofd, "}%c\n%cdef%c%ctest{ }", '\%', '\\', '\\', c);
      if (index(trailstr, c))
         fprintf(ofd, "%cdef%c%ctrail{%c}",
            '\\', '\\', c, line[strlen(line)-2]);
      fprintf(ofd, "%cdef%c%cstr{%s", 
         '\\', '\\', c, line);
      }
   else if (num < max)
      fprintf(ofd, "%c\n  %c%ccomma %s", '\%', '\\', c, line);
   else if (max == 2)
      fprintf(ofd, "%c\n  %c%cand %s", '\%', '\\', c, line);
   else
      fprintf(ofd, "%c\n  %c%candd %s", '\%', '\\', c, line);
}

/* doline - actually print out a line of reference information */
   doline(c, line, numauths, maxauths, numeds, maxeds, 
               numrevs, maxrevs, numtrans, maxtrans, ofd)
   char c, *line;
   int numauths, maxauths, numeds, maxeds;
   int numrevs, maxrevs, numtrans, maxtrans;
   FILE *ofd;
{
   char *s1;
   char *dbldash();
   char line1[REFSIZE];

   switch(c) {
      case '\\':
      case '\%':
          for (s1=line;*s1!='\0';s1++)
              if (*s1=='\n') *s1='\0';
          fprintf(ofd, "}%c\n%c%s{", '\%', c , line);
          break;

      case 'A':
          prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev);
          break;

       case 'E':
          if (maxauths)
             prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, 
                 ednumrev);
          else
             prtauth(c, line, numeds, maxeds, ofd, abbrev, capsmcap, numrev);
          break;

       case 'a':
          prtauth(c, line, numtrans, maxtrans, ofd, edabbrev, edcapsmcap,
             ednumrev);
         break;

       case 'e':
          prtauth(c, line, numrevs, maxrevs, ofd, edabbrev, edcapsmcap, 
             ednumrev);
          break;

       case 'P':
       case 'p':
          fprintf(ofd, "}%c\n%cdef%c%ctest{ }", '\%', '\\', '\\', c);
          if (onepage) {
             opage(line);
             fprintf(ofd, "%cdef%c%ccnt{}", '\\', '\\', c);
             }
          else {
             if (index (line, '-')) {
                line = dbldash(line);
                fprintf(ofd, "%cdef%c%ccnt{ }", '\\', '\\', c);
             }
             else
                fprintf(ofd, "%cdef%c%ccnt{}", '\\', '\\', c);
          }
          if (index(trailstr, c))
             fprintf(ofd, "%cdef%c%ctrail{%c}%c\n", '\\', '\\', c, 
                     line[strlen(line)-2], '\%');
          for (s1 = line; *s1 != '\0'; s1++)
              if (*s1=='\n') *s1='\0';
          fprintf(ofd, "%cdef%c%cstr{%s", '\\', '\\', c, 
              line);
          break;

       case 'F':
       case 'K': break;

       case 'I':
          if (numauths == 0 && numeds == 0 && capsmcap) {
             capssmallcaps(line1, line);
             strcpy(line, line1);
             }

       default:
          fprintf(ofd, "}%c\n%cdef%c%ctest{ }", '\%', '\\', '\\', c);
          if (index(trailstr, c))
             fprintf(ofd, "%cdef%c%ctrail{%c}", '\\', '\\', c, 
             line[strlen(line)-2]);
          for (s1=line;*s1!='\0';s1++)
              if (*s1=='\n') *s1='\0';
          fprintf(ofd, "%cdef%c%cstr{%s", 
              '\\', '\\', c, line);
          }
}

/* dbldash - double the hyphen in the P field (see below)*/
   char *dbldash(line)
   char *line;
{  char *p;
   char newline[120];

   for (p = newline; *line && *line != '-'; *p++ = *line++);
   if (*line == 0) return (line);
   if (*++line != '-')
      *p++ = '-';
   *p++ = '-';
   for (*p = *line; *line; *p++ = *line++);
   *p='\0';
   return (newline);
}

/* following works on some machines where above fails
char *dbldash(line)
char *line;
{  char *p;
   static char newline[120];

   for (p = newline; *p = *line; ++p, ++line)
      if (line[0] == '-' && line[1] != '-')
          *++p = '-';
   return(newline);
} */

/* opage - print only first page number */
   int opage(line)
   char *line;
{  char *p;

   for (p = line; *p && *p != '-'; *p++);
   *p=0;
}

/* dumpref - dump reference number i */
   dumpref(i, ofd)
   int i;
   FILE *ofd;
{  char ref[REFSIZE], *p, line[REFSIZE];
   int numauths, maxauths, numeds, maxeds;
   int numrevs, maxrevs, numtrans, maxtrans;

   fprintf(ofd, "%cbgroup%cResetstrings%c\n", '\\', '\\' , '\%');
   rdref(refspos[i], ref);
   maxauths = maxeds = maxrevs = maxtrans = 0;
   numauths = numeds = numrevs = numtrans = 0;
   for (p = ref; *p; p++)
      if (*p == '%')
         if (*(p+1) == 'A') maxauths++;
         else if (*(p+1) == 'E') maxeds++;
         else if (*(p+1) == 'a') maxtrans++;
         else if (*(p+1) == 'e') maxrevs++;
   if (loccit) {
      if (locflag[i])
         fprintf(ofd, "%cdef%cLoccittest{ }", '\\', '\\');
      else
         fprintf(ofd, "%cdef%cLoccittest{}", '\\', '\\');
      if (ibidflag[i])
         fprintf(ofd, "%cdef%cIbidtest{ }", '\\', '\\');
      else
         fprintf(ofd, "%cdef%cIbidtest{}", '\\', '\\');
   }
   else
      fprintf(ofd, "%cdef%cLoccittest{}", '\\', '\\');
   if (abbrev) 
      fprintf(ofd, "%cdef%cAbbtest{ }", '\\', '\\');
   else
      fprintf(ofd, "%cdef%cAbbtest{}", '\\', '\\');
   if (capsmcap) 
      fprintf(ofd, "%cdef%cCapssmallcapstest{ }", '\\', '\\');
   else
      fprintf(ofd, "%cdef%cCapssmallcapstest{}", '\\', '\\');
   if (edabbrev) 
      fprintf(ofd, "%cdef%cEdabbtest{ }", '\\', '\\');
   else
      fprintf(ofd, "%cdef%cEdabbtest{}", '\\', '\\');
   if (edcapsmcap) 
      fprintf(ofd, "%cdef%cEdcapsmallcapstest{ }", '\\', '\\');
   else
      fprintf(ofd, "%cdef%cEdcapsmallcapstest{}", '\\', '\\');
   if (underline) 
      fprintf(ofd, "%cdef%cUnderlinetest{ }%c\n", '\\', '\\', '\%');
   else
      fprintf(ofd, "%cdef%cUnderlinetest{}%c\n", '\\', '\\', '\%');
   fprintf(ofd, "%cdef%cNoArev{%d}%cdef%cNoErev{%d}%cdef%cAcnt{%d}", 
      '\\', '\\', numrev, '\\', '\\', ednumrev, '\\', '\\', maxauths);
   fprintf(ofd, "%cdef%cEcnt{%d}%cdef%cacnt{%d}%cdef%cecnt{%d}%c\n", 
      '\\', '\\', maxeds, '\\', '\\', 
      maxtrans, '\\', '\\', maxrevs, '\%');
   fprintf(ofd, "%cdef%cFtest{ }", '\\', '\\');
          if (index(trailstr, 'F'))
             fprintf(ofd, "%cdef%c%ctrail{%c}", '\\', '\\', 'F', 
             citestr[i][strlen(citestr[i])-1]);
   fprintf(ofd, "%cdef%cFstr{%s", '\\', '\\', 
      citestr[i]);
   fseek(rfd, (long) refspos[i], 0);
   while (fgets(line, REFSIZE, rfd) != NULL) {
      if (line[0] == 0)        break;
      else if (line[0] == '%') {
            for (p = &line[2]; *p == ' '; p++);
            if (line[1] == 'A')       numauths++;
            else if (line[1] == 'E')  numeds++;
            else if (line[1] == 'a')  numtrans++;
            else if (line[1] == 'e')  numrevs++;

            doline(line[1], p, numauths, maxauths, numeds, maxeds, 
               numrevs, maxrevs, numtrans, maxtrans, ofd);
            }
      else if (line[0] == '\\')
         fprintf(ofd, "}%c\n%s{", '\%', line);
      else fprintf(ofd, "%s", line);
      }
   if (underline && unlmark[i-1]) {
      if (maxauths) fprintf (ofd, "}%c\n%cdef%cAstr{%cUnderlinemark", '\%', 
         '\\', '\\', '\\');
      else if (maxeds) fprintf (ofd, "}%c\n%cdef%cEstr{%cUnderlinemark", '\%', 
         '\\', '\\', '\\');
      else fprintf (ofd, "}%c\n%cdef%cIstr{%cUnderlinemark", '\%', '\\', 
         '\\', '\\');
      }
   fprintf(ofd, "}%c\n%cRefformat%cegroup%c\n", '\%', '\\', '\\', '\%');
   if ((!foot) && (!c0)) fprintf(ofd, "\n");
}