xref: /csrg-svn/contrib/bib/src/bibargs.c (revision 60507)
113110Srrh #ifndef lint
2*60507Sbostic static char sccsid[] = "@(#)bibargs.c	2.13	05/27/93";
313110Srrh #endif not lint
415061Sgarrison /*
515061Sgarrison         Authored by: Tim Budd, University of Arizona, 1983.
615061Sgarrison                 version 7/4/83
713110Srrh 
815061Sgarrison         Various modifications suggested by:
915061Sgarrison                 David Cherveny - Duke University Medical Center
1015061Sgarrison                 Phil Garrison - UC Berkeley
1115061Sgarrison                 M. J. Hawley - Yale University
1215061Sgarrison 
1315061Sgarrison 
14*60507Sbostic 	       version 8/23/1988
15*60507Sbostic 
16*60507Sbostic 	 Adapted to use TiB style macro calls (i.e. |macro|)
17*60507Sbostic 	       A. Dain Samples
1815061Sgarrison 
1915061Sgarrison 
20*60507Sbostic 
21*60507Sbostic 
2212910Sgarrison         read argument strings for bib and listrefs
2312910Sgarrison         do name formatting, printing lines, other actions common to both
2412910Sgarrison                                                         */
2512910Sgarrison # include <stdio.h>
2612910Sgarrison # include <ctype.h>
2712910Sgarrison # include "bib.h"
2812910Sgarrison # define LINELENGTH 1024
2912910Sgarrison # define MAXDEFS     500             /* maximum number of defined words */
3012910Sgarrison 
3112910Sgarrison /* global variables */
3215061Sgarrison    char bibfname[120];          /* file name currently being read            */
3315061Sgarrison    int  biblineno;              /* line number currently being referenced    */
3412910Sgarrison    int  abbrev       = false;   /* automatically abbreviate names            */
3512910Sgarrison    int  capsmcap     = false;   /* print names in caps small caps (CACM form)*/
36*60507Sbostic    int  TibOption    = false;   /* expect files in TiB format                */
37*60507Sbostic    int	TibxOption   = false;   /* to create files for bib2tib               */
3812910Sgarrison    int  numrev       = 0;       /* number of authors names to reverse        */
3912910Sgarrison    int  edabbrev     = false;   /* abbreviate editors names ?                */
4012910Sgarrison    int  edcapsmcap   = false;   /* print editors in cap small caps           */
4112910Sgarrison    int  ednumrev     = 0;       /* number of editors to reverse              */
4223485Sgarrison    int	max_klen     = 6;	/* max size of key			     */
4312910Sgarrison    int  sort         = false;   /* sort references ? (default no)            */
4412910Sgarrison    int  foot         = false;   /* footnoted references ? (default endnotes) */
45*60507Sbostic    int  doacite      = true;    /* place citations ?                         */
46*60507Sbostic    int	redefWarning = false;	/* warnings on attempted redefs ?	     */
4712910Sgarrison    int  hyphen       = false;   /* hypenate contiguous references            */
4812910Sgarrison    int  ordcite      = true;    /* order multiple citations                  */
4912910Sgarrison    char sortstr[80]  = "1";     /* sorting template                          */
5012910Sgarrison    char trailstr[80] = "";      /* trailing characters to output             */
5125528Sgarrison    char pfile[400];             /* private file name                         */
5212910Sgarrison    int  personal = false;       /* personal file given ? (default no)        */
5312910Sgarrison    char citetemplate[80] = "1"; /* citation template                         */
5415903Srrh    struct wordinfo words[MAXDEFS];     /* defined words */
5515903Srrh    struct wordinfo *wordhash[HASHSIZE];
5615903Srrh    struct wordinfo *wordsearch();
5715903Srrh    int  wordtop = 0;           /* number of defined words         */
58*60507Sbostic    char letterSeen[128];   /* keeps track of keyletters
59*60507Sbostic 		       * so we know whether to emit a .ds
60*60507Sbostic 		       * or a .as
61*60507Sbostic 		      /* */
6212910Sgarrison 
6312910Sgarrison /* where output goes */
6412910Sgarrison    extern FILE *tfd;
6515061Sgarrison /* reference file information */
6615903Srrh    extern struct refinfo refinfo[];
6715061Sgarrison    extern char reffile[];
6815903Srrh #ifndef INCORE
6915061Sgarrison    extern FILE *rfd;
7015903Srrh #endif not INCORE
7115061Sgarrison    extern int numrefs;
72*60507Sbostic    extern char *programName;
7312910Sgarrison 
74*60507Sbostic char *usageArr[] = {
75*60507Sbostic "-aa    abbreviate authors' first names",
76*60507Sbostic "-arN   reverse first N authors' names; no N, do all",
77*60507Sbostic "-ax    print authors' last names in Caps-Small",
78*60507Sbostic "-cS    use template S for citations",
79*60507Sbostic "-d	change the default directory",
80*60507Sbostic "-ea    abbreviate editors' first names",
81*60507Sbostic "-ex    print editors' last names in Caps-Small",
82*60507Sbostic "-erN   reverse first N editors' names; no N, do all",
83*60507Sbostic "-f     dump reference after citation for footnotes",
84*60507Sbostic "-iFILE process FILE (e.g. a file of definitions)",
85*60507Sbostic "-h     hyphenate sequences of citations (turns on -o)",
86*60507Sbostic "-nS    turn off options; S is composed of the option letters 'afhosx'",
87*60507Sbostic "-pFILE search these FILEs (comma separated list) instead of INDEX",
88*60507Sbostic "-R	print warnings when duplicate definitions of names are ignored",
89*60507Sbostic "-sS    sort references according to template S",
90*60507Sbostic "-tTYPE use the style TYPE",
91*60507Sbostic "-Tib   expect files to be in TiB format (which see)",
92*60507Sbostic "-Tibx	write a file for converting bib to TiB-style |macros|",
93*60507Sbostic "",
94*60507Sbostic 0
95*60507Sbostic };
96*60507Sbostic 
97*60507Sbostic void
usageErr(argv0,opt,str)98*60507Sbostic usageErr(argv0, opt, str)
99*60507Sbostic     char *argv0;
100*60507Sbostic     char *opt;
101*60507Sbostic     char *str;
102*60507Sbostic {
103*60507Sbostic     char  **p;
104*60507Sbostic     fprintf(stderr, "Illegal invocation of %s.  Acceptable options:\n",
105*60507Sbostic                                             argv0);
106*60507Sbostic     fprintf(stderr, "Argument: %s\n", opt);
107*60507Sbostic     fprintf(stderr, "Problem:  %s\n", str);
108*60507Sbostic     for (p = usageArr; *p != 0; p++) {
109*60507Sbostic         fprintf(stderr, "    %s\n", *p);
110*60507Sbostic         }
111*60507Sbostic }
112*60507Sbostic 
113*60507Sbostic /* bibwarning - print out a warning message */
114*60507Sbostic   /*VARARGS1*/
bibwarning(msg,a1,a2)115*60507Sbostic   bibwarning(msg, a1, a2)
116*60507Sbostic   char *msg;
117*60507Sbostic {
118*60507Sbostic   fprintf(stderr,"%s: `%s', line %d: ", programName, bibfname, biblineno);
119*60507Sbostic   fprintf(stderr, msg, a1, a2);
120*60507Sbostic   fprintf(stderr, "\n");
121*60507Sbostic }
122*60507Sbostic 
123*60507Sbostic 
124*60507Sbostic 
12512910Sgarrison /* doargs - read command argument line for both bib and listrefs
12612910Sgarrison             set switch values
12712910Sgarrison             call rdtext on file arguments, after dumping
12812910Sgarrison             default style file if no alternative style is given
12912910Sgarrison */
130*60507Sbostic 
doargs(argc,argv,defstyle)13112910Sgarrison    int doargs(argc, argv, defstyle)
13212910Sgarrison    int argc;
13312910Sgarrison    char **argv, defstyle[];
13412910Sgarrison {  int numfiles, i, style;
13512910Sgarrison    char *p, *q, *walloc();
13612910Sgarrison    FILE *fd;
13712910Sgarrison 
13812910Sgarrison    numfiles = 0;
13912910Sgarrison    style = true;
140*60507Sbostic    TibxOption = false;
14117248Srrh    newbibdir(BMACLIB);
14212910Sgarrison 
143*60507Sbostic    programName = argv[0];
14412910Sgarrison    for (i = 1; i < argc; i++)
14512910Sgarrison       if (argv[i][0] == '-')
14612910Sgarrison          switch(argv[i][1]) {
14715061Sgarrison             case 'a':  for (p = &argv[i][2]; *p; p++)
14815061Sgarrison                           if (*p == 'a' || *p == 0)
14912961Sgarrison                              abbrev = true;
15012961Sgarrison                            else if (*p == 'x')
15112961Sgarrison                              capsmcap = true;
15212961Sgarrison                            else if (*p == 'r') {
15312961Sgarrison                              if (*(p+1))
15412961Sgarrison                                 numrev = atoi(p+1);
15512961Sgarrison                               else
15612961Sgarrison                                 numrev = 1000;
15712961Sgarrison                               break;
15812961Sgarrison                               }
15912910Sgarrison                        break;
16012910Sgarrison 
16112910Sgarrison             case 'c':  if (argv[i][2] == 0)
16215903Srrh                           error("citation string expected for 'c'");
16312910Sgarrison                        else
16412910Sgarrison                           for (p = citetemplate,q = &argv[i][2]; *p++ = *q++; );
16512910Sgarrison                        break;
16612910Sgarrison 
167*60507Sbostic 	    case 'd':  if (argv[i][2])
168*60507Sbostic 			    p = &argv[i][2];
169*60507Sbostic 		       else {  /* take next arg */
170*60507Sbostic 			    i++;
171*60507Sbostic 			    p = argv[i];
172*60507Sbostic 			    }
173*60507Sbostic 		       newbibdir(p);
174*60507Sbostic 		       break;
175*60507Sbostic 
17612910Sgarrison             case 'e':  for (p = &argv[i][2]; *p; p++)
17712910Sgarrison                           if (*p == 'a')
17812910Sgarrison                              edabbrev = true;
17912910Sgarrison                            else if (*p == 'x')
18012910Sgarrison                              edcapsmcap = true;
18112910Sgarrison                            else if (*p == 'r') {
18212910Sgarrison                              if (*(p+1))
18312910Sgarrison                                 ednumrev = atoi(p+1);
18412910Sgarrison                               else
18512910Sgarrison                                 ednumrev = 1000;
18612910Sgarrison                               break;
18712910Sgarrison                               }
18812910Sgarrison                        break;
18912910Sgarrison 
190*60507Sbostic             case 'f':  CASE_f:
191*60507Sbostic 		       foot = true;
192*60507Sbostic                        hyphen = false;
193*60507Sbostic                        break;
194*60507Sbostic 
195*60507Sbostic             case 'i':  CASE_i:
196*60507Sbostic 		       if (argv[i][2])
197*60507Sbostic                           p = &argv[i][2];
198*60507Sbostic                        else { /* take next arg */
199*60507Sbostic                           i++;
200*60507Sbostic                           p = argv[i];
201*60507Sbostic                           }
202*60507Sbostic                        incfile(p);
203*60507Sbostic                        break;
204*60507Sbostic 
20523485Sgarrison 	    case 'l':  if (argv[i][2]){
20623485Sgarrison                           max_klen  = atoi(&argv[i][2]);
20723485Sgarrison 			  if (max_klen > REFSIZE)
20823485Sgarrison 			      error("too long key size");
20923485Sgarrison 		       } else {
21023485Sgarrison 			  error("-l needs a numeric value");
21123485Sgarrison 		       }
21223485Sgarrison 		       break;
21323485Sgarrison 
21412910Sgarrison             case 'h':  hyphen = ordcite = true;
21512910Sgarrison                        break;
21612910Sgarrison 
21712910Sgarrison             case 'n':  for (p = &argv[i][2]; *p; p++)
21812910Sgarrison                           if (*p == 'a')
21912910Sgarrison                              abbrev = false;
22012910Sgarrison                           else if (*p == 'f')
22112910Sgarrison                              foot = false;
22212910Sgarrison                           else if (*p == 'h')
22312910Sgarrison                              hyphen = false;
22412910Sgarrison                           else if (*p == 'o')
22512910Sgarrison                              ordcite = false;
226*60507Sbostic                           else if (*p == 'R')
227*60507Sbostic                              redefWarning = false;
22812910Sgarrison                           else if (*p == 'r')
22912910Sgarrison                              numrev = 0;
23012910Sgarrison                           else if (*p == 's')
23112910Sgarrison                              sort = false;
23212910Sgarrison                           else if (*p == 'x')
23312910Sgarrison                              capsmcap = false;
234*60507Sbostic                           else if (*p == 'v')
235*60507Sbostic                              doacite = true;
23612910Sgarrison                        break;
23712910Sgarrison 
23812910Sgarrison             case 'o':  ordcite = true;
23912910Sgarrison                        break;
24012910Sgarrison 
24112910Sgarrison             case 'p':  if (argv[i][2])
24212910Sgarrison                           p = &argv[i][2];
24312910Sgarrison                        else {  /* take next arg */
24412910Sgarrison                           i++;
24512910Sgarrison                           p = argv[i];
24612910Sgarrison                           }
24712910Sgarrison                        strcpy(pfile, p);
24812910Sgarrison                        personal = true;
24912910Sgarrison                        break;
25012910Sgarrison 
251*60507Sbostic 	    case 'R':  redefWarning = true;
252*60507Sbostic 		       break;
253*60507Sbostic 
254*60507Sbostic             case 'r':  if (argv[i][2] == 0)  /* synonym -ar */
25512910Sgarrison                           numrev = 1000;
25612910Sgarrison                        else
25712910Sgarrison                           numrev = atoi(&argv[i][2]);
25812910Sgarrison                        break;
25912910Sgarrison 
26012910Sgarrison             case 's':  sort = true;
26112910Sgarrison                        if (argv[i][2])
26212910Sgarrison                           for (p = sortstr,q = &argv[i][2]; *p++ = *q++; );
26312910Sgarrison                        break;
26412910Sgarrison 
265*60507Sbostic             case 't':  style = false;
266*60507Sbostic 		       goto CASE_i;
26712910Sgarrison 
268*60507Sbostic 	   case 'T':   if (strcmp("Tib", &(argv[i][1])) == 0)
269*60507Sbostic 			   TibOption = true;
270*60507Sbostic 		       else if (strcmp("Tibx",&(argv[i][1])) == 0)
271*60507Sbostic 			   TibxOption = true;
272*60507Sbostic 		       else {
273*60507Sbostic 			    usageErr(argv[0], argv[i],
274*60507Sbostic 				    "Did you want the Tib option?");
275*60507Sbostic 			    error("'%s' invalid switch", argv[i]);
276*60507Sbostic 			    }
277*60507Sbostic 		       break;
278*60507Sbostic 
279*60507Sbostic             case 'v':  doacite = false;
280*60507Sbostic 		       goto CASE_f;
281*60507Sbostic 
282*60507Sbostic             case 'x':  capsmcap = true; /* synonym for -ax */
28312910Sgarrison                        break;
28412910Sgarrison 
28512910Sgarrison             case 0:    if (style) {  /* no style command given, take default */
28612910Sgarrison                           style = false;
28712910Sgarrison                           incfile( defstyle );
28812910Sgarrison                           }
28915061Sgarrison                        strcpy(bibfname,"<stdin>");
29012910Sgarrison                        rdtext(stdin);
29112910Sgarrison                        numfiles++;
29212910Sgarrison                        break;
29312910Sgarrison 
294*60507Sbostic             default:   usageErr(argv[0], argv[i], "Invalid switch");
29515903Srrh                        error("'%c' invalid switch", argv[i][1]);
29612910Sgarrison             }
29712910Sgarrison       else { /* file name */
29812910Sgarrison          numfiles++;
29912910Sgarrison          if (style) {
30012910Sgarrison             style = false;
30112910Sgarrison             incfile( defstyle );
30212910Sgarrison             }
30312910Sgarrison          fd = fopen(argv[i], "r");
30412910Sgarrison          if (fd == NULL) {
30515903Srrh             error("can't open file %s", argv[i]);
30612910Sgarrison             }
30712910Sgarrison          else {
30815061Sgarrison             strcpy(bibfname, argv[i]);
30912910Sgarrison             rdtext(fd);
31012910Sgarrison             fclose(fd);
31112910Sgarrison             }
31212910Sgarrison          }
31312910Sgarrison 
31412910Sgarrison    if (style) incfile( defstyle );
315*60507Sbostic    if (TibxOption) {
316*60507Sbostic      /*
317*60507Sbostic      Emits m4 macros that allow easy transformation of old bib-style
318*60507Sbostic      bibliographic databases into tib-style.  The primary problem
319*60507Sbostic      (although not the only one) is the change of |macro| calls.
320*60507Sbostic       */
321*60507Sbostic       reg struct wordinfo *wp;
322*60507Sbostic       FILE *outf;
323*60507Sbostic       outf = fopen("bib.m4.in","w");
324*60507Sbostic       for (i=0; i<HASHSIZE; i++) {
325*60507Sbostic 	 for (wp = wordhash[i]; wp != NULL; wp = wp->wi_hp) {
326*60507Sbostic 	    fprintf(outf,"define(%s,|%s__m4_|)dnl\n",wp->wi_word,wp->wi_word);
327*60507Sbostic 	    }
328*60507Sbostic 	 }
329*60507Sbostic       fclose(outf);
330*60507Sbostic       }
33112910Sgarrison    return(numfiles);
33212910Sgarrison 
33312910Sgarrison }
33412910Sgarrison 
newbibdir(name)33517248Srrh newbibdir(name)
33617248Srrh 	char *name;
33717248Srrh {
338*60507Sbostic    strreplace(COMFILE, BMACLIB, name);
339*60507Sbostic    strreplace(DEFSTYLE, BMACLIB, name);
340*60507Sbostic    strcpy(BMACLIB, name);
341*60507Sbostic    wordrestuff("BMACLIB", BMACLIB);
342*60507Sbostic    fprintf(tfd, ".ds l] %s\n", BMACLIB);
34317248Srrh }
34417248Srrh 
34512910Sgarrison /* incfile - read in an included file  */
incfile(np)34612910Sgarrison incfile(np)
34712910Sgarrison    char *np;
34812910Sgarrison {  char name[120];
34912910Sgarrison    FILE *fd;
35015061Sgarrison    char *p, line[LINELENGTH], dline[LINELENGTH], word[80], *tfgets();
35116244Srrh    int  i, getwrd();
35212910Sgarrison 
353*60507Sbostic    strcpy(line, bibfname); /* temporary save in case of errors */
354*60507Sbostic    /* first try ./<yourfile> */
355*60507Sbostic       strcpy(bibfname, np);
356*60507Sbostic       fd = fopen(bibfname, "r");
357*60507Sbostic    /* try BMACLIB/<yourfile> */
35812910Sgarrison    if (fd == NULL && *np != '/') {
359*60507Sbostic       strcpy(name, BMACLIB); strcat(name, "/"); strcat(name, np);
36015061Sgarrison       strcpy(bibfname, name);
361*60507Sbostic       fd = fopen(bibfname, "r");
36212910Sgarrison       }
363*60507Sbostic    /* try BMACLIB/tibmacs/<yourfile> */
364*60507Sbostic    if (TibOption && fd == NULL && *np != '/') {
365*60507Sbostic       strcpy(name, BMACLIB); strcat(name, "/tibmacs/"); strcat(name, np);
366*60507Sbostic       strcpy(bibfname, name);
367*60507Sbostic       fd = fopen(bibfname, "r");
368*60507Sbostic       }
369*60507Sbostic    /* try BMACLIB/bibmacs/<yourfile> */
370*60507Sbostic    if (!TibOption && fd == NULL && *np != '/') {
371*60507Sbostic       strcpy(name, BMACLIB); strcat(name, "/bibmacs/"); strcat(name, np);
372*60507Sbostic       strcpy(bibfname, name);
373*60507Sbostic       fd = fopen(bibfname, "r");
374*60507Sbostic       }
375*60507Sbostic    /* try ./bib.<yourfile> */
37612910Sgarrison    if (fd == NULL && *np != '/') {
377*60507Sbostic       strcpy(name, "bib."); strcat(name, np);
37815061Sgarrison       strcpy(bibfname, name);
379*60507Sbostic       fd = fopen(bibfname, "r");
38012910Sgarrison       }
381*60507Sbostic    /* try BMACLIB/bib.<yourfile> */
382*60507Sbostic    if (fd == NULL && *np != '/') {
383*60507Sbostic       strcpy(name,BMACLIB); strcat(name, "/bib."); strcat(name, np);
384*60507Sbostic       strcpy(bibfname, name);
385*60507Sbostic       fd = fopen(bibfname, "r");
386*60507Sbostic       }
38712910Sgarrison    if (fd == NULL) {
388*60507Sbostic       /* unsave old name */
389*60507Sbostic       strcpy(bibfname, line);
390*60507Sbostic       bibwarning("%s: can't find", np);
39115061Sgarrison       exit(1);
39212910Sgarrison       }
39312910Sgarrison 
39415061Sgarrison    /* now go off and process file */
39515061Sgarrison    biblineno = 1;
39615061Sgarrison    while (tfgets(line, LINELENGTH, fd) != NULL) {
39715061Sgarrison       biblineno++;
39812910Sgarrison       switch(line[0]) {
39912910Sgarrison 
40012910Sgarrison          case '#': break;
40112910Sgarrison 
40212961Sgarrison          case 'A': for (p = &line[1]; *p; p++)
40315061Sgarrison                       if (*p == 'A' || *p == '\0')
40412961Sgarrison                          abbrev = true;
40512961Sgarrison                       else if (*p == 'X')
40612961Sgarrison                          capsmcap = true;
40712961Sgarrison                       else if (*p == 'R') {
40812961Sgarrison                          if (*(p+1))
40912961Sgarrison                             numrev = atoi(p+1);
41012961Sgarrison                          else
41112961Sgarrison                             numrev = 1000;
41212961Sgarrison                          break;
41312961Sgarrison                          }
41412910Sgarrison                    break;
41512910Sgarrison 
41612910Sgarrison          case 'C': for (p = &line[1]; *p == ' '; p++) ;
41712910Sgarrison                    strcpy(citetemplate, p);
41812910Sgarrison                    break;
41912910Sgarrison 
42012910Sgarrison          case 'D': if ((i = getwrd(line, 1, word)) == 0)
42112910Sgarrison                       error("word expected in definition");
42223492Sgarrison 		   if (wordsearch(word)) { /* already there-toss rest of def.*/
423*60507Sbostic 			if (redefWarning)
424*60507Sbostic 			   bibwarning("Attempted redefine of %s ignored.",word);
42523492Sgarrison 			while(line[strlen(line)-1] == '\\' ) {
42623492Sgarrison                             if (tfgets(line, LINELENGTH, fd) == NULL) break;
42723492Sgarrison 			}
42815903Srrh 			break;
42923492Sgarrison 		   }
430*60507Sbostic                    for (p = &line[i]; isspace(*p); p++) ;
43112910Sgarrison                    for (strcpy(dline, p); dline[strlen(dline)-1] == '\\'; ){
43212910Sgarrison                        dline[strlen(dline)-1] = '\n';
43315061Sgarrison                        if (tfgets(line, LINELENGTH, fd) == NULL) break;
43412910Sgarrison                        strcat(dline, line);
43512910Sgarrison                        }
43615903Srrh 		   wordstuff(word, dline);
43712910Sgarrison                    break;
43812910Sgarrison 
43912910Sgarrison          case 'E': for (p = &line[1]; *p; p++)
44012910Sgarrison                       if (*p == 'A')
44112910Sgarrison                          edabbrev = true;
44212910Sgarrison                       else if (*p == 'X')
44312910Sgarrison                          edcapsmcap = true;
44412910Sgarrison                       else if (*p == 'R') {
44512910Sgarrison                          if (*(p+1))
44612910Sgarrison                             ednumrev = atoi(p+1);
44712910Sgarrison                          else
44812910Sgarrison                             ednumrev = 1000;
44912910Sgarrison                          break;
45012910Sgarrison                          }
45112910Sgarrison                    break;
45212910Sgarrison 
45312910Sgarrison          case 'F': foot = true;
45412910Sgarrison                    hyphen = false;
45512910Sgarrison                    break;
45612910Sgarrison 
45712910Sgarrison          case 'I': for (p = &line[1]; *p == ' '; p++);
45812910Sgarrison                    expand(p);
45912910Sgarrison                    incfile(p);
46012910Sgarrison                    break;
46112910Sgarrison 
46212910Sgarrison          case 'H': hyphen = ordcite = true;
46312910Sgarrison                    break;
46412910Sgarrison 
46512910Sgarrison          case 'O': ordcite = true;
46612910Sgarrison                    break;
46712910Sgarrison 
46815061Sgarrison          case 'R': if (line[1] == 0)  /* this is now replaced by AR */
46912910Sgarrison                       numrev = 1000;
47012910Sgarrison                    else
47112910Sgarrison                       numrev = atoi(&line[1]);
47212910Sgarrison                    break;
47312910Sgarrison 
47412910Sgarrison          case 'S': sort = true;
47512910Sgarrison                    for (p = &line[1]; *p == ' '; p++) ;
47612910Sgarrison                    strcpy(sortstr, p);
47712910Sgarrison                    break;
47812910Sgarrison 
47912910Sgarrison          case 'T': for (p = &line[1]; *p == ' '; p++) ;
48012910Sgarrison                    strcpy(trailstr, p);
48112910Sgarrison                    break;
48212910Sgarrison 
48315061Sgarrison          case 'X': capsmcap = true;     /* this is now replace by AX */
48412910Sgarrison                    break;
48512910Sgarrison 
48612910Sgarrison          default:  fprintf(tfd,"%s\n",line);
48715061Sgarrison                    while (fgets(line, LINELENGTH, fd) != NULL)
48812910Sgarrison                       fputs(line, tfd);
48912910Sgarrison                    return;
49012910Sgarrison          }
49115061Sgarrison 
49215061Sgarrison    }
49315061Sgarrison    /* close up */
49415061Sgarrison    fclose(fd);
49512910Sgarrison }
49612910Sgarrison 
49715061Sgarrison /* error - report unrecoverable error message */
49815903Srrh   /*VARARGS1*/
error(str,a1,a2)49915903Srrh   error(str, a1, a2)
50015903Srrh   char *str;
50115061Sgarrison {
50215903Srrh   bibwarning(str, a1, a2);
50315903Srrh   /*
50415903Srrh    *	clean up temp files and exit
50515903Srrh    */
50615903Srrh   cleanup(1);
50715061Sgarrison }
50815061Sgarrison 
50915903Srrh #ifndef INCORE
51015061Sgarrison #ifdef READWRITE
51115061Sgarrison /*
51215061Sgarrison ** fixrfd( mode ) -- re-opens the rfd file to be read or write,
51315061Sgarrison **      depending on the mode.  Uses a static int to save the current mode
51415061Sgarrison **      and avoid unnecessary re-openings.
51515061Sgarrison */
fixrfd(mode)51615061Sgarrison fixrfd( mode )
51715061Sgarrison register int mode;
51815061Sgarrison {
51915061Sgarrison 	static int cur_mode = WRITE;    /* rfd open for writing initially */
52015061Sgarrison 
52115061Sgarrison 	if (mode != cur_mode)
52215061Sgarrison 	{
52315061Sgarrison 		rfd = freopen(reffile, ((mode == READ)? "r" : "a"), rfd);
52415061Sgarrison 		cur_mode = mode;
52515061Sgarrison 		if (rfd == NULL)
52615903Srrh 		      error("Hell!  Couldn't re-open reference file %s",
52715903Srrh 			reffile);
52815061Sgarrison 	}
52915061Sgarrison }
53015061Sgarrison #endif
53115903Srrh #endif not INCORE
53215061Sgarrison 
53315061Sgarrison 
53415061Sgarrison /* tfgets - fgets which trims off newline */
tfgets(line,n,ptr)53515061Sgarrison    char *tfgets(line, n, ptr)
53615061Sgarrison    char line[];
53715061Sgarrison    int  n;
53815061Sgarrison    FILE *ptr;
53915903Srrh {  reg char *p;
54015061Sgarrison 
54115061Sgarrison    p = fgets(line, n, ptr);
54215061Sgarrison    if (p == NULL)
54315061Sgarrison       return(NULL);
54415061Sgarrison    else
54515061Sgarrison       for (p = line; *p; p++)
54615061Sgarrison          if (*p == '\n')
54715061Sgarrison             *p = 0;
54815061Sgarrison    return(line);
54915061Sgarrison }
55015061Sgarrison 
55115061Sgarrison /* getwrd - place next word from in[i] into out */
getwrd(in,i,out)55215061Sgarrison int getwrd(in, i, out)
55315903Srrh    reg char in[], out[];
55415903Srrh    reg int i;
55515061Sgarrison {  int j;
55615061Sgarrison 
55715061Sgarrison    j = 0;
558*60507Sbostic    while (isspace(in[i]))
55915061Sgarrison       i++;
560*60507Sbostic    if (in[i] != '\0')
561*60507Sbostic       while (in[i]  != '\0' && !isspace(in[i]))
56215061Sgarrison          out[j++] = in[i++];
56315061Sgarrison    else
56415061Sgarrison       i = 0;    /* signals end of in[i..]   */
56515061Sgarrison    out[j] = 0;
56615061Sgarrison    return (i);
56715061Sgarrison }
56815061Sgarrison 
56915061Sgarrison /* walloc - allocate enough space for a word */
walloc(word)57015061Sgarrison char *walloc(word)
57115061Sgarrison    char *word;
57215061Sgarrison {  char *i, *malloc();
57315061Sgarrison    i = malloc(1 + strlen(word));
57415061Sgarrison    if (i == NULL)
57515061Sgarrison       error("out of storage");
57615061Sgarrison    strcpy(i, word);
57715061Sgarrison    return(i);
57815061Sgarrison }
57915061Sgarrison 
58012910Sgarrison /* isword - see if character is legit word char */
581*60507Sbostic #define iswordc(c) (isalnum(c) || c == '&' || c == '_')
582*60507Sbostic 
expand(line)58312910Sgarrison    expand(line)
58412910Sgarrison    char *line;
585*60507Sbostic {  char line2[REFSIZE], word[REFSIZE];
58615903Srrh    reg	struct wordinfo *wp;
58715903Srrh    reg	char *p, *q, *w;
58812910Sgarrison 
589*60507Sbostic    q = line2;
590*60507Sbostic    if (TibOption) {
591*60507Sbostic       /* expand only macro names in |name| vertical bars; name must exist */
592*60507Sbostic       for (p = line; *p != '\0'; /* VOID */ ) {
593*60507Sbostic 	 if (*p == '|') {
594*60507Sbostic 	    p++;
595*60507Sbostic 	    w = word;
596*60507Sbostic 	    while (*p != '|' && *p != '\0' && !isspace(*p)) { *w++ = *p++; }
597*60507Sbostic 	    *w = '\0';
598*60507Sbostic 	    /* skip second '|', if present */
599*60507Sbostic 	    if (*p++ != '|') {
600*60507Sbostic 	       --p;
601*60507Sbostic 	       bibwarning("Unbalanced |macro| bars\n");
602*60507Sbostic 	       }
603*60507Sbostic 	    else if ((wp = wordsearch(word)) != 0) {
604*60507Sbostic 	       strcpy(word, wp->wi_def);
605*60507Sbostic 	       if (wp->wi_expanding) {
606*60507Sbostic 		  bibwarning("Recursive definition for |%s|\n", word);
607*60507Sbostic 		  }
608*60507Sbostic 	       else {
609*60507Sbostic 		  wp->wi_expanding = true;
610*60507Sbostic 		  expand(word);
611*60507Sbostic 		  wp->wi_expanding = false;
612*60507Sbostic 		  }
613*60507Sbostic 	       }
614*60507Sbostic 	    else {
615*60507Sbostic 	       char errword[REFSIZE];
616*60507Sbostic 	       bibwarning("word |%s| not defined\n", word);
617*60507Sbostic 	       strcpy(errword, "?");
618*60507Sbostic 	       strcat(errword, word);
619*60507Sbostic 	       strcat(errword, "?");
620*60507Sbostic 	       wordstuff(word, errword);
621*60507Sbostic 	       strcpy(word, errword);
622*60507Sbostic 	       }
623*60507Sbostic 	    for (w = word; *w != '\0'; *q++ = *w++);
624*60507Sbostic 	    }
625*60507Sbostic 	 else {
626*60507Sbostic 	    *q++ = *p++;
627*60507Sbostic 	    }
628*60507Sbostic 	 }
629*60507Sbostic       }
630*60507Sbostic    else {
631*60507Sbostic       for (p = line; *p != '\0'; /*VOID*/){
632*60507Sbostic 	 if (isalnum(*p)) {
633*60507Sbostic 	    for (w = word; *p && iswordc(*p); ) *w++ = *p++;
634*60507Sbostic 	    *w = 0;
635*60507Sbostic 	    if (wp = wordsearch(word)){
636*60507Sbostic 	       if (wp->wi_expanding)
637*60507Sbostic 		  bibwarning("Recursive definition for %s\n", word);
638*60507Sbostic 	       else {
639*60507Sbostic 		  strcpy(word, wp->wi_def);
640*60507Sbostic 		  wp->wi_expanding = true;
641*60507Sbostic 		  expand(word);
642*60507Sbostic 		  wp->wi_expanding = false;
643*60507Sbostic 		  }
644*60507Sbostic 	       }
645*60507Sbostic 	    for (w = word; *w != '\0'; *q++ = *w++);
646*60507Sbostic 	    }
647*60507Sbostic 	 else if (*p == '\\' && *(p+1) != '\0') {
648*60507Sbostic 	    *q++ = *p++;
649*60507Sbostic 	    *q++ = *p++;
650*60507Sbostic 	    }
651*60507Sbostic 	 else {
652*60507Sbostic 	    *q++ = *p++;
653*60507Sbostic 	    }
654*60507Sbostic 	 }
655*60507Sbostic       }
656*60507Sbostic    *q = 0;
657*60507Sbostic    strcpy(line, line2);
65812910Sgarrison }
65912910Sgarrison 
66015903Srrh /* wordstuff- save a word and its definition, building a hash table */
wordstuff(word,def)66115903Srrh    wordstuff(word, def)
66215903Srrh    char *word, *def;
66315903Srrh {
66415903Srrh    int i;
66515903Srrh    if (wordtop >= MAXDEFS)
66615903Srrh 	error("too many definitions, max of %d", MAXDEFS);
66715903Srrh    words[wordtop].wi_length = strlen(word);
668*60507Sbostic    words[wordtop].wi_word = word ? walloc(word) : NULL;
669*60507Sbostic    words[wordtop].wi_def = def ? walloc(def) : NULL;
67015903Srrh    i = strhash(word);
671*60507Sbostic    words[wordtop].wi_expanding = false;
67215903Srrh    words[wordtop].wi_hp = wordhash[i];
67315903Srrh    wordhash[i] = &words[wordtop];
67415903Srrh    wordtop++;
67515903Srrh }
wordsearch(word)67615903Srrh    struct wordinfo *wordsearch(word)
67715903Srrh    char *word;
67815903Srrh {
67915903Srrh    reg int lg;
68015903Srrh    reg struct wordinfo *wp;
68115903Srrh    lg = strlen(word);
68215903Srrh    for (wp = wordhash[strhash(word)]; wp; wp = wp->wi_hp){
68315903Srrh 	if (wp->wi_length == lg && (strcmp(wp->wi_word, word) == 0)){
68415903Srrh 		return(wp);
68515903Srrh 	}
68615903Srrh    }
68715903Srrh    return(0);
68815903Srrh }
689*60507Sbostic /* wordrestuff - save a word and its definition, but replace any existing
690*60507Sbostic  * definition; this could be more efficient, but it is only used to
691*60507Sbostic  * redefine BMACLIB at the present.  -ads 8/88
692*60507Sbostic  */
wordrestuff(word,def)693*60507Sbostic    wordrestuff(word, def)
694*60507Sbostic    char *word, *def;
695*60507Sbostic {
696*60507Sbostic    struct wordinfo *wp = wordsearch(word);
697*60507Sbostic    if (wp == NULL) wordstuff(word, def);
698*60507Sbostic    else {
699*60507Sbostic       if (wp->wi_word != NULL) free(wp->wi_word);
700*60507Sbostic       if (wp->wi_def != NULL) free(wp->wi_def);
701*60507Sbostic       wp->wi_length = strlen(word);
702*60507Sbostic       wp->wi_word = word ? walloc(word) : NULL;
703*60507Sbostic       wp->wi_def = def ? walloc(def) : NULL;
704*60507Sbostic       wp->wi_expanding = false;
705*60507Sbostic       }
706*60507Sbostic }
70715903Srrh 
strhash(str)70815903Srrh    int strhash(str)
70915903Srrh    reg char *str;
71015903Srrh {
71115903Srrh    reg int value = 0;
71215903Srrh    for (value = 0; *str; value <<= 2, value += *str++)/*VOID*/;
71315903Srrh    value %= HASHSIZE;
71415903Srrh    if (value < 0)
71515903Srrh 	value += HASHSIZE;
71615903Srrh    return(value);
71715903Srrh }
71815903Srrh 
71915061Sgarrison /* rdref - read text for an already cited reference */
72015903Srrh    rdref(p, ref)
72115903Srrh    struct refinfo *p;
72215061Sgarrison    char ref[REFSIZE];
72315061Sgarrison {
72415061Sgarrison    ref[0] = 0;
72515903Srrh #ifndef INCORE
72615061Sgarrison #ifdef READWRITE
72715061Sgarrison    fixrfd( READ );                      /* fix access mode of rfd, if nec. */
72815061Sgarrison #endif
72915903Srrh    fseek(rfd, p->ri_pos, 0);
73015903Srrh    fread(ref, p->ri_length, 1, rfd);
73115903Srrh #else INCORE
73215903Srrh    strcpy(ref, p->ri_ref);
73315903Srrh #endif INCORE
73415061Sgarrison }
73515061Sgarrison 
73615903Srrh /* wrref - write text for a new reference */
73715903Srrh    wrref(p, ref)
73815903Srrh    struct refinfo *p;
73915903Srrh    char ref[REFSIZE];
74015903Srrh {
74115903Srrh #ifndef INCORE
74215903Srrh #ifdef READWRITE
74315903Srrh     fixrfd( WRITE );                 /* fix access mode of rfd, if nec. */
74415903Srrh #else
74515903Srrh     fseek(rfd, p->ri_pos, 0);        /* go to end of rfd */
74615903Srrh #endif
74715903Srrh     fwrite(ref, p->ri_length, 1, rfd);
74815903Srrh #else INCORE
74915903Srrh    p->ri_ref = walloc(ref);
75015903Srrh #endif INCORE
75115903Srrh }
75215903Srrh 
75312910Sgarrison /* breakname - break a name into first and last name */
breakname(line,first,last)75412910Sgarrison    breakname(line, first, last)
75512910Sgarrison    char line[], first[], last[];
75615903Srrh {  reg char *t, *f, *q, *r, *p;
75712910Sgarrison 
75812910Sgarrison    for (t = line; *t != '\n'; t++);
75912910Sgarrison    for (t--; isspace(*t); t--);
76012910Sgarrison 
76112910Sgarrison    /* now strip off last name */
76212910Sgarrison    for (q = t; isspace(*q) == 0 || ((*q == ' ') & (*(q-1) == '\\')); q--)
76312910Sgarrison       if (q == line)
76412910Sgarrison          break;
76512910Sgarrison    f = q;
76615061Sgarrison    if (q != line) {
76712910Sgarrison       q++;
76815061Sgarrison       for (; isspace(*f); f--);
76915061Sgarrison       f++;
77015061Sgarrison       }
77112910Sgarrison 
77212910Sgarrison    /* first name is start to f, last name is q to t */
77312910Sgarrison 
77415061Sgarrison    for (r = first, p = line; p != f; )
77512910Sgarrison       *r++ = *p++;
77612910Sgarrison    *r = 0;
77712910Sgarrison    for (r = last, p = q, t++; q != t; )
77812910Sgarrison       *r++ = *q++;
77912910Sgarrison    *r = 0;
78015061Sgarrison 
78112910Sgarrison }
78212910Sgarrison 
78312910Sgarrison /* match - see if string1 is a substring of string2 (case independent)*/
match(str1,str2)78412910Sgarrison    int match(str1, str2)
78515903Srrh    reg char str1[], str2[];
78615903Srrh {  reg int  j, i;
78712910Sgarrison    char a, b;
78812910Sgarrison 
78912910Sgarrison    for (i = 0; str2[i]; i++) {
79012910Sgarrison       for (j = 0; str1[j]; j++) {
79112910Sgarrison          if (isupper(a = str2[i+j]))
79212910Sgarrison             a = (a - 'A') + 'a';
79312910Sgarrison          if (isupper(b = str1[j]))
79412910Sgarrison             b = (b - 'A') + 'a';
79512910Sgarrison          if (a != b)
79612910Sgarrison             break;
79712910Sgarrison          }
79812910Sgarrison       if (str1[j] == 0)
79912910Sgarrison          return(true);
80012910Sgarrison       }
80112910Sgarrison    return(false);
80212910Sgarrison }
80312910Sgarrison 
80412910Sgarrison /* scopy - append a copy of one string to another */
scopy(p,q)80512910Sgarrison    char *scopy(p, q)
80615903Srrh    reg char *p, *q;
80712910Sgarrison {
80812910Sgarrison    while (*p++ = *q++)
80912910Sgarrison       ;
81012910Sgarrison    return(--p);
81112910Sgarrison }
81212910Sgarrison 
81315061Sgarrison /* rcomp - reference comparison routine for qsort utility */
rcomp(ap,bp)81415061Sgarrison    int rcomp(ap, bp)
81515903Srrh    struct refinfo *ap, *bp;
81615061Sgarrison {  char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD];
81715903Srrh    reg	char *p, *q;
81815903Srrh    char *getfield();
81915061Sgarrison    int  neg, res;
82015061Sgarrison    int  fields_found;
82115061Sgarrison 
82215903Srrh    rdref(ap, ref1);
82315903Srrh    rdref(bp, ref2);
82415061Sgarrison    for (p = sortstr; *p; p = q) {
82515061Sgarrison       if (*p == '-') {
82615061Sgarrison          p++;
82715061Sgarrison          neg = true;
82815061Sgarrison          }
82915061Sgarrison       else
83015061Sgarrison          neg = false;
83115061Sgarrison       q = getfield(p, field1, ref1);
83215061Sgarrison       fields_found = true;
83315061Sgarrison       if (q == 0) {
83415061Sgarrison 	 res = 1;
83515061Sgarrison 	 fields_found = false;
83615061Sgarrison       } else if (strcmp (field1, "") == 0) {	/* field not found */
83715061Sgarrison          if (*p == 'A') {
83815061Sgarrison             getfield("F", field1, ref1);
83915061Sgarrison 	    if (strcmp (field1, "") == 0) {
84015061Sgarrison                getfield("I", field1, ref1);
84115061Sgarrison 	       if (strcmp (field1, "") == 0) {
84215061Sgarrison 	          res = 1;
84315061Sgarrison 		  fields_found = false;
84415061Sgarrison 	       }
84515061Sgarrison 	    }
84615061Sgarrison 	 } else {
84715061Sgarrison 	    res = 1;
84815061Sgarrison 	    fields_found = false;
84915061Sgarrison 	 }
85015061Sgarrison       }
85115061Sgarrison 
85215061Sgarrison       if (getfield(p, field2, ref2) == 0) {
85315061Sgarrison 	 res = -1;
85415061Sgarrison 	 fields_found = false;
85515061Sgarrison       } else if (strcmp (field2, "") == 0) {	/* field not found */
85615061Sgarrison          if (*p == 'A') {
85715061Sgarrison             getfield("F", field2, ref2);
85815061Sgarrison 	    if (strcmp (field2, "") == 0) {
85915061Sgarrison                getfield("I", field2, ref2);
86015061Sgarrison 	       if (strcmp (field2, "") == 0) {
86115061Sgarrison 	          res = -1;
86215061Sgarrison 		  fields_found = false;
86315061Sgarrison 	       }
86415061Sgarrison 	    }
86515061Sgarrison 	 } else {
86615061Sgarrison 	    res = -1;
86715061Sgarrison 	    fields_found = false;
86815061Sgarrison 	 }
86915061Sgarrison       }
87015061Sgarrison       if (fields_found) {
87115061Sgarrison          if (*p == 'A') {
87215061Sgarrison             if (isupper(field1[0]))
87315061Sgarrison                field1[0] -= 'A' - 'a';
87415061Sgarrison             if (isupper(field2[0]))
87515061Sgarrison                field2[0] -= 'A' - 'a';
87615061Sgarrison             }
87715061Sgarrison          res = strcmp(field1, field2);
87815061Sgarrison          }
87915061Sgarrison       if (neg)
88015061Sgarrison          res = - res;
88115061Sgarrison       if (res != 0)
88215061Sgarrison          break;
88315061Sgarrison       }
88415061Sgarrison    if (res == 0)
88515061Sgarrison       if (ap < bp)
88615061Sgarrison          res = -1;
88715061Sgarrison       else
88815061Sgarrison          res = 1;
88915061Sgarrison    return(res);
89015061Sgarrison }
89115061Sgarrison 
89216244Srrh /* makecites - make standard citation strings, using citetemplate currently in effect */
makecites()89315903Srrh    makecites()
89415061Sgarrison {  char ref[REFSIZE], tempcite[100], *malloc();
89515903Srrh    reg int  i;
89615061Sgarrison 
89715903Srrh    for (i = 0; i < numrefs; i++) {
89815903Srrh       rdref(&refinfo[i], ref);
89915061Sgarrison       bldcite(tempcite, i, ref);
90016244Srrh       refinfo[i].ri_cite = malloc(2 + strlen(tempcite));
90115903Srrh       if (refinfo[i].ri_cite == NULL)
90215061Sgarrison          error("out of storage");
90315903Srrh       strcpy(refinfo[i].ri_cite, tempcite);
90415061Sgarrison       }
90515061Sgarrison }
90615061Sgarrison 
90715061Sgarrison /* bldcite - build a single citation string */
bldcite(cp,i,ref)90815061Sgarrison    bldcite(cp, i, ref)
90915061Sgarrison    char *cp, ref[];
91015061Sgarrison    int  i;
91115903Srrh {  reg char *p, *q, *fp;
91215903Srrh    char c;
91315903Srrh    char field[REFSIZE];
91431947Sbostic    char *getfield(), *aabet(), *aabetlast(),
91531947Sbostic         *fullaabet(), *multfull();
91615061Sgarrison 
91715061Sgarrison    getfield("F", field, ref);
91815061Sgarrison    if (field[0] != 0)
91915061Sgarrison       for (p = field; *p; p++)
92015061Sgarrison          *cp++ = *p;
92115061Sgarrison    else {
92215061Sgarrison       p = citetemplate;
92315061Sgarrison       field[0] = 0;
92415061Sgarrison       while (c = *p++) {
92515061Sgarrison          if (isalpha(c)) {                      /* field name   */
92615061Sgarrison             q = getfield(p-1, field, ref);
92715061Sgarrison             if (q != 0) {
92815061Sgarrison                p = q;
92915061Sgarrison                for (fp = field; *fp; )
93015061Sgarrison                   *cp++ = *fp++;
93115061Sgarrison                }
93215061Sgarrison             }
93315061Sgarrison          else if (c == '1') {                   /* numeric  order */
93415061Sgarrison             sprintf(field,"%d",1 + i);
93515061Sgarrison             for (fp = field; *fp; )
93615061Sgarrison                *cp++ = *fp++;
93715061Sgarrison             }
93815061Sgarrison          else if (c == '2')                     /* alternate alphabetic */
93915061Sgarrison             cp = aabet(cp, ref);
94015061Sgarrison          else if (c == '3')                     /* Astrophysical Journal style*/
94131947Sbostic             cp = multfull(cp, ref, 3);
94231947Sbostic          else if (c == '4')                     /* Computing Surveys style*/
94331947Sbostic             cp = multfull(cp, ref, 2);
94423485Sgarrison 	 else if (c == '8')			/* Full alphabetic */
94523485Sgarrison 	    cp = fullaabet(cp, ref);
94615890Srrh          else if (c == '9')                     /* Last name of Senior Author*/
94715890Srrh             cp = aabetlast(cp, ref);
94817246Srrh 	 else if (c == '0') {			/* print nothing */
94917246Srrh             for (fp = field; *fp; )
95017246Srrh                *cp++ = *fp++;
95117246Srrh             }
95215061Sgarrison          else if (c == '{') {                   /* other information   */
95315061Sgarrison             while (*p != '}')
95415061Sgarrison                if (*p == 0)
95515061Sgarrison                   error("unexpected end of citation template");
95615061Sgarrison                else
95715061Sgarrison                   *cp++ = *p++;
95815061Sgarrison             p++;
95915061Sgarrison             }
96015061Sgarrison          else if (c == '<') {
96115061Sgarrison             while (*p != '>') {
96215061Sgarrison                if (*p == 0)
96315061Sgarrison                   error("unexpected end of citation template");
96415061Sgarrison                else
96515061Sgarrison                   *cp++ = *p++;
96615061Sgarrison                }
96715061Sgarrison             p++;
96815061Sgarrison             }
96915061Sgarrison          else if (c != '@')
97015061Sgarrison             *cp++ = c;
97115061Sgarrison          }
97215061Sgarrison       }
97315061Sgarrison    *cp++ = 0;
97415061Sgarrison }
97515061Sgarrison 
97615061Sgarrison /* alternate alphabetic citation style -
97715061Sgarrison         if 1 author - first three letters of last name
97815061Sgarrison         if 2 authors - first two letters of first, followed by first letter of
97915061Sgarrison                                 seond
98015061Sgarrison         if 3 or more authors - first letter of first three authors */
aabet(cp,ref)98115061Sgarrison    char *aabet(cp, ref)
98215061Sgarrison    char *cp, ref[];
98315903Srrh {  char field[REFSIZE], temp[100];
98415903Srrh    reg char *np, *fp;
98515061Sgarrison    int j, getname();
98615061Sgarrison 
98715061Sgarrison    if (getname(1, field, temp, ref)) {
98815061Sgarrison       np = cp;
98915061Sgarrison       fp = field;
99015061Sgarrison       for (j = 1; j <= 3; j++)
99115061Sgarrison          if (*fp != 0)
99215061Sgarrison             *cp++ = *fp++;
99315061Sgarrison       if (getname(2, field, temp, ref))
99415061Sgarrison          np[2] = field[0];
99515061Sgarrison       if (getname(3, field, temp, ref)) {
99615061Sgarrison          np[1] = np[2];
99715061Sgarrison          np[2] = field[0];
99815061Sgarrison          }
99915061Sgarrison       }
100015061Sgarrison return(cp);
100115061Sgarrison }
100215061Sgarrison 
100315890Srrh /* alternate alphabetic citation style -
100423485Sgarrison 	first two characters of last names of all authors
100523485Sgarrison 	up to max_klen characters.
100623485Sgarrison */
fullaabet(cp,ref)100723485Sgarrison    char *fullaabet(cp, ref)
100823485Sgarrison    char *cp, ref[];
100923485Sgarrison {  char field[REFSIZE], temp[100];
101023485Sgarrison    reg char	*fp;
101123485Sgarrison    char	*lastcp;
101223485Sgarrison    int getname();
101323485Sgarrison    int i;
101423485Sgarrison 
101523485Sgarrison    lastcp = cp + max_klen;
101623485Sgarrison    for (i= 1; getname(i, field, temp, ref); i++) {
101723485Sgarrison       for (fp = field; *fp && (fp < &(field[3])); )
101823485Sgarrison 	 if (cp > lastcp)
101923485Sgarrison 	     break;
102023485Sgarrison          else if (isalpha(*fp))
102123485Sgarrison 	     *cp++ = *fp++;
102223485Sgarrison 	 else
102323485Sgarrison 	     fp++;
102423485Sgarrison    }
102523485Sgarrison    return(cp);
102623485Sgarrison }
102723485Sgarrison 
102823485Sgarrison 
102923485Sgarrison /* alternate alphabetic citation style -
103015890Srrh 	entire last name of senior author
103115890Srrh */
aabetlast(cp,ref)103215890Srrh    char *aabetlast(cp, ref)
103315890Srrh    char *cp, ref[];
103415890Srrh {  char field[REFSIZE], temp[100];
103515903Srrh    reg char	*fp;
103615890Srrh    int getname();
103715890Srrh 
103815890Srrh    if (getname(1, field, temp, ref)) {
103915890Srrh       for (fp = field; *fp; )
104015890Srrh          *cp++ = *fp++;
104115890Srrh    }
104215890Srrh    return(cp);
104315890Srrh }
104415890Srrh 
104531947Sbostic /*
104631947Sbostic   Multiple full authors last names (1, 2 or 3 full names).
104731947Sbostic 
104831947Sbostic   If maxauthors<3
104915061Sgarrison         if 1 author - last name date
105015061Sgarrison         if 2 authors - last name and last name date
105131947Sbostic         if 3 or more authors - last name et al. date
105231947Sbostic   If maxauthors>=3
105331947Sbostic         if 1 author - last name date
105431947Sbostic         if 2 authors - last name and last name date
105515061Sgarrison         if 3 authors - last name, last name and last name date
105615061Sgarrison         if 4 or more authors - last name et al. date */
multfull(cp,ref,maxauthors)105731947Sbostic    char *multfull(cp, ref, maxauthors)
105815061Sgarrison    char *cp, ref[];
105931947Sbostic    int maxauthors;
106015903Srrh {  char name1[100], name2[100], name3[100], temp[100];
106115903Srrh    reg char *fp;
106215061Sgarrison    int getname();
106315061Sgarrison 
106415061Sgarrison    if (getname(1, name1, temp, ref)) {
106515061Sgarrison       for (fp = name1; *fp; )
106615061Sgarrison          *cp++ = *fp++;
106732623Sgarrison       if (((maxauthors >= 3) && (getname(4, name3, temp, ref)))
106832623Sgarrison 	  || ((maxauthors < 3) && (getname(3, name3, temp, ref)))) {
106931947Sbostic          for (fp = " \\*(e]"; *fp; )
107015061Sgarrison             *cp++ = *fp++;
107115061Sgarrison          }
107215061Sgarrison       else if (getname(2, name2, temp, ref)) {
107315061Sgarrison          if (getname(3, name3, temp, ref)) {
107415061Sgarrison             for (fp = "\\*(c]"; *fp; )
107515061Sgarrison                *cp++ = *fp++;
107615061Sgarrison             for (fp = name2; *fp; )
107715061Sgarrison                *cp++ = *fp++;
107815061Sgarrison             for (fp = "\\*(m]"; *fp; )
107915061Sgarrison                *cp++ = *fp++;
108015061Sgarrison             for (fp = name3; *fp; )
108115061Sgarrison                *cp++ = *fp++;
108215061Sgarrison             }
108315061Sgarrison          else {
108415061Sgarrison             for (fp = "\\*(n]"; *fp; )
108515061Sgarrison                *cp++ = *fp++;
108615061Sgarrison             for (fp = name2; *fp; )
108715061Sgarrison                *cp++ = *fp++;
108815061Sgarrison             }
108915061Sgarrison          }
109015061Sgarrison     }
109115061Sgarrison return(cp);
109215061Sgarrison }
109315061Sgarrison 
109415061Sgarrison /* getfield - get a single field from reference */
getfield(ptr,field,ref)109515061Sgarrison    char *getfield(ptr, field, ref)
109615061Sgarrison    char *ptr, field[], ref[];
109715903Srrh {  reg	char *p, *q;
109815903Srrh    char	temp[100];
109915061Sgarrison    int  n, len, i, getname();
110015061Sgarrison 
110115061Sgarrison    field[0] = 0;
110215061Sgarrison    if (*ptr == 'A')
110315061Sgarrison       getname(1, field, temp, ref);
110415061Sgarrison    else
1105*60507Sbostic       for (p = ref; *p != '\0'; p++)
110615061Sgarrison          if (*p == '%' && *(p+1) == *ptr) {
1107*60507Sbostic             for (p = p + 2; isspace(*p); p++)
110815061Sgarrison                ;
110915061Sgarrison             for (q = field; (*p != '\n') && (*p != '\0'); )
111015061Sgarrison                *q++ = *p++;
111115061Sgarrison             *q = 0;
111215061Sgarrison             break;
111315061Sgarrison             }
111415061Sgarrison    n = 0;
111515061Sgarrison    len = strlen(field);
111615061Sgarrison    if (*++ptr == '-') {
111715061Sgarrison       for (ptr++; isdigit(*ptr); ptr++)
111815061Sgarrison          n = 10 * n + (*ptr - '0');
111915061Sgarrison       if (n > len)
112015061Sgarrison          n = 0;
112115061Sgarrison       else
112215061Sgarrison          n = len - n;
112315061Sgarrison       for (i = 0; field[i] = field[i+n]; i++)
112415061Sgarrison          ;
112515061Sgarrison       }
112615061Sgarrison    else if (isdigit(*ptr)) {
112715061Sgarrison       for (; isdigit(*ptr); ptr++)
112815061Sgarrison          n = 10 * n + (*ptr - '0');
112915061Sgarrison       if (n > len)
113015061Sgarrison          n = len;
113115061Sgarrison       field[n] = 0;
113215061Sgarrison       }
113315061Sgarrison 
113415061Sgarrison    if (*ptr == 'u') {
113515061Sgarrison       ptr++;
113615061Sgarrison       for (p = field; *p; p++)
113715061Sgarrison          if (islower(*p))
113815061Sgarrison             *p = (*p - 'a') + 'A';
113915061Sgarrison       }
114015061Sgarrison    else if (*ptr == 'l') {
114115061Sgarrison       ptr++;
114215061Sgarrison       for (p = field; *p; p++)
114315061Sgarrison          if (isupper(*p))
114415061Sgarrison             *p = (*p - 'A') + 'a';
114515061Sgarrison       }
114615061Sgarrison    return(ptr);
114715061Sgarrison }
114815061Sgarrison 
114915061Sgarrison /* getname - get the nth name field from reference, breaking into
115015061Sgarrison              first and last names */
getname(n,last,first,ref)115115061Sgarrison    int getname(n, last, first, ref)
115215061Sgarrison    int  n;
115315061Sgarrison    char last[], first[], ref[];
115415903Srrh {  reg char *p;
115515061Sgarrison    int  m;
115615061Sgarrison 
115715061Sgarrison    m = n;
115815061Sgarrison    for (p = ref; *p; p++)
115915061Sgarrison       if (*p == '%' & *(p+1) == 'A') {
116015061Sgarrison          n--;
116115061Sgarrison          if (n == 0) {
116215061Sgarrison             for (p = p + 2; *p == ' '; p++) ;
116315061Sgarrison             breakname(p, first, last) ;
116415061Sgarrison             return(true);
116515061Sgarrison             }
116615061Sgarrison          }
116715061Sgarrison 
116815061Sgarrison    if (n == m)          /* no authors, try editors */
116915061Sgarrison       for (p = ref; *p; p++)
117015061Sgarrison          if (*p == '%' & *(p+1) == 'E') {
117115061Sgarrison             n--;
117215061Sgarrison             if (n == 0) {
117315061Sgarrison                for (p = p + 2; *p == ' '; p++) ;
117415061Sgarrison                breakname(p, first, last) ;
117515061Sgarrison                return(true);
117615061Sgarrison                }
117715061Sgarrison             }
117815061Sgarrison 
117915061Sgarrison    if (n == m) {        /* no editors, either, try institution */
118015061Sgarrison       first[0] = last[0] = '\0';
118115061Sgarrison       getfield("I", last, ref);
118215061Sgarrison       if (last[0] != '\0')
118315061Sgarrison          return(true);
118415061Sgarrison       }
118515061Sgarrison 
118615061Sgarrison    return(false);
118715061Sgarrison }
118815061Sgarrison 
118915061Sgarrison /* disambiguate - compare adjacent citation strings, and if equal, add
119015061Sgarrison                   single character disambiguators */
disambiguate()119115061Sgarrison    disambiguate()
119215903Srrh {  reg int i, j;
119316244Srrh 	char adstr;
119415061Sgarrison 
119523492Sgarrison    for (i = 0; i < numrefs-1; i = j) {
119615061Sgarrison       j = i + 1;
119715903Srrh       if (strcmp(refinfo[i].ri_cite, refinfo[j].ri_cite)==0) {
119816244Srrh          adstr = 'a';
119923492Sgarrison          for(j = i+1;
120023492Sgarrison 	     j<numrefs && strcmp(refinfo[i].ri_cite,refinfo[j].ri_cite) == 0;
120123492Sgarrison 	     j++) {
120216244Srrh             adstr = 'a' + (j-i);
120316244Srrh 	    refinfo[j].ri_disambig[0] = adstr;
120415061Sgarrison             }
120516244Srrh 	 refinfo[i].ri_disambig[0] = 'a';
120615061Sgarrison          }
120715061Sgarrison      }
120816244Srrh   for (i = 0; i < numrefs; i++){
120916244Srrh 	strcat(refinfo[i].ri_cite, refinfo[i].ri_disambig);
121016244Srrh   }
121115061Sgarrison }
121215061Sgarrison 
121315061Sgarrison 
121412910Sgarrison /* bldname - build a name field
121512910Sgarrison              doing abbreviations, reversals, and caps/small caps
121612910Sgarrison */
bldname(first,last,name,reverse)121712910Sgarrison    bldname(first, last, name, reverse)
121812910Sgarrison    char *first, *last, name[];
121912910Sgarrison    int reverse;
122012910Sgarrison {
122115903Srrh    char newfirst[120], newlast[120];
122215903Srrh    reg char *p, *q, *f, *l;
122315903Srrh    char *scopy();
122412910Sgarrison    int  flag;
122512910Sgarrison 
122612910Sgarrison    if (abbrev) {
122712910Sgarrison       p = first;
122812910Sgarrison       q = newfirst;
122912910Sgarrison       flag = false;
123012910Sgarrison       while (*p) {
123112910Sgarrison          while (*p == ' ')
123212910Sgarrison             p++;
123312910Sgarrison          if (*p == 0)
123412910Sgarrison             break;
123512910Sgarrison          if (isupper(*p)) {
123615061Sgarrison             if (flag)           /* between initial gap */
123712910Sgarrison                q = scopy(q, "\\*(a]");
123812910Sgarrison             flag = true;
123912910Sgarrison             *q++ = *p;
124015061Sgarrison             q = scopy(q, "\\*(p]");
124112910Sgarrison             }
124212910Sgarrison          if (*++p == '.')
124312910Sgarrison             p++;
124412910Sgarrison          else while (*p != 0 && ! isspace(*p))
124512910Sgarrison             p++;
124612910Sgarrison          }
124712910Sgarrison       *q = 0;
124812910Sgarrison       f = newfirst;
124912910Sgarrison       }
125012910Sgarrison    else
125112910Sgarrison       f = first;
125212910Sgarrison 
125312910Sgarrison    if (capsmcap) {
125412910Sgarrison       p = last;
125512910Sgarrison       q = newlast;
125612910Sgarrison       flag = 0;  /* 1 - printing cap, 2 - printing small */
125712910Sgarrison       while (*p)
125812910Sgarrison          if (islower(*p)) {
125912910Sgarrison             if (flag != 2)
126012910Sgarrison                q = scopy(q, "\\s-2");
126112910Sgarrison             flag = 2;
126212910Sgarrison             *q++ = (*p++ - 'a') + 'A';
126312910Sgarrison             }
126412910Sgarrison          else {
126512910Sgarrison             if (flag == 2)
126612910Sgarrison                q = scopy(q,"\\s+2");
126712910Sgarrison             flag = 1;
126812910Sgarrison             *q++ = *p++;
126912910Sgarrison             }
127012910Sgarrison       if (flag == 2)
127112910Sgarrison          q = scopy(q, "\\s+2");
127212910Sgarrison       *q = 0;
127312910Sgarrison       l = newlast;
127412910Sgarrison       }
127512910Sgarrison    else
127612910Sgarrison       l = last;
127712910Sgarrison 
127815061Sgarrison    if (f[0] == 0)
127915061Sgarrison       sprintf(name, "%s\n", l);
128015061Sgarrison    else if (reverse)
128115061Sgarrison       sprintf(name, "%s\\*(b]%s\n", l, f);
128212910Sgarrison    else
128312910Sgarrison       sprintf(name, "%s %s\n", f, l);
128412910Sgarrison }
128512910Sgarrison 
128612910Sgarrison /* prtauth - print author or editor field */
prtauth(c,line,num,max,ofd,abbrev,capsmcap,numrev)128712910Sgarrison    prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev)
128812910Sgarrison    char c, *line;
128912910Sgarrison    int  num, max, abbrev, capsmcap, numrev;
129012910Sgarrison    FILE *ofd;
129112910Sgarrison {  char first[LINELENGTH], last[LINELENGTH];
129212910Sgarrison 
129312910Sgarrison    if (num <= numrev || abbrev || capsmcap) {
129412910Sgarrison       breakname(line, first, last);
129512910Sgarrison       bldname(first, last, line, num <= numrev);
129612910Sgarrison       }
129712910Sgarrison    if (num == 1)
129812910Sgarrison       fprintf(ofd,".ds [%c %s", c, line);
129912910Sgarrison    else if (num < max)
130012910Sgarrison       fprintf(ofd,".as [%c \\*(c]%s", c, line);
130112910Sgarrison    else if (max == 2)
130212910Sgarrison       fprintf(ofd,".as [%c \\*(n]%s", c, line);
130312910Sgarrison    else
130412910Sgarrison       fprintf(ofd,".as [%c \\*(m]%s", c, line);
130512910Sgarrison    if (num == max && index(trailstr, c))
130612910Sgarrison       fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
130712910Sgarrison }
130812910Sgarrison 
130912910Sgarrison /* doline - actually print out a line of reference information */
doline(c,line,numauths,maxauths,numeds,maxeds,ofd)131012910Sgarrison    doline(c, line, numauths, maxauths, numeds, maxeds, ofd)
131112910Sgarrison    char c, *line;
131212910Sgarrison    int numauths, maxauths, numeds, maxeds;
131312910Sgarrison    FILE *ofd;
131412910Sgarrison {
1315*60507Sbostic    int appending;
131612910Sgarrison 
131712910Sgarrison    switch(c) {
131812910Sgarrison       case 'A':
131912910Sgarrison           prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev);
132012910Sgarrison           break;
132112910Sgarrison 
1322*60507Sbostic       case 'E':
132312910Sgarrison           prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, ednumrev);
132412910Sgarrison           if (numeds == maxeds)
132512910Sgarrison              fprintf(ofd,".nr [E %d\n", maxeds);
132612910Sgarrison           break;
132712910Sgarrison 
1328*60507Sbostic       case 'P':
132912910Sgarrison           if (index(line, '-'))
133012910Sgarrison              fprintf(ofd,".nr [P 1\n");
133112910Sgarrison           else
133212910Sgarrison              fprintf(ofd,".nr [P 0\n");
133312910Sgarrison           fprintf(ofd,".ds [P %s",line);
133412910Sgarrison           if (index(trailstr, 'P'))
133512910Sgarrison              fprintf(ofd,".ds ]P %c\n",line[strlen(line)-2]);
133612910Sgarrison           break;
133712910Sgarrison 
1338*60507Sbostic       case 'F': break;
133912910Sgarrison 
1340*60507Sbostic       /* these now accumulate their entries */
1341*60507Sbostic       /* defined by official bib documentation */
1342*60507Sbostic       case 'K': case 'O': case 'W':
1343*60507Sbostic       /* not defined by official bib documentation */
1344*60507Sbostic       case 'H': case 'L': case 'M': case 'Q': case 'U': case 'X': case 'Y':
1345*60507Sbostic       case 'Z':
1346*60507Sbostic 	 appending = letterSeen[c];
1347*60507Sbostic 	 letterSeen[c] = true;
1348*60507Sbostic 	 if (appending)
1349*60507Sbostic 	    fprintf(ofd, ".as [%c , %s", c, line);
1350*60507Sbostic 	 else
1351*60507Sbostic 	    fprintf(ofd, ".ds [%c %s", c, line);
1352*60507Sbostic 	 if (index(trailstr, c))
1353*60507Sbostic 	    fprintf(ofd, ".ds ]%c %c\n", c, line[strlen(line) - 2]);
1354*60507Sbostic 	 break;
1355*60507Sbostic 
1356*60507Sbostic       default:
1357*60507Sbostic 	  if (!isupper(c)) break; /* ignore what you don't understand */
135812910Sgarrison           fprintf(ofd,".ds [%c %s", c, line);
135912910Sgarrison           if (index(trailstr, c))
136012910Sgarrison              fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
136112910Sgarrison           }
136212910Sgarrison }
136312910Sgarrison 
136415061Sgarrison /* dumpref - dump reference number i */
dumpref(i,ofd)136515061Sgarrison    dumpref(i, ofd)
136615061Sgarrison    int i;
136715061Sgarrison    FILE *ofd;
136815903Srrh {  char ref[REFSIZE], line[REFSIZE];
136915903Srrh    reg char *p, *q;
137015903Srrh    char *from;
137115061Sgarrison    int numauths, maxauths, numeds, maxeds;
1372*60507Sbostic    int j;
137315061Sgarrison 
137431947Sbostic    if ( i < 0 ) ref[0] = 0; /* ref not found */
137531947Sbostic    else {
137631947Sbostic 	   rdref(&refinfo[i], ref);
137731947Sbostic 	   maxauths = maxeds = 0;
137831947Sbostic 	   numauths = numeds = 0;
1379*60507Sbostic 	   for (j=0; j < 128; j++) letterSeen[j] = 0;
138031947Sbostic 	   for (p = ref; *p; p++)
138131947Sbostic 	      if (*p == '%')
138231947Sbostic 	         if (*(p+1) == 'A') maxauths++;
138331947Sbostic 	         else if (*(p+1) == 'E') maxeds++;
138431947Sbostic 	   fprintf(ofd, ".[-\n");
138531947Sbostic 	   fprintf(ofd, ".ds [F %s\n", refinfo[i].ri_cite);
138615903Srrh #ifndef INCORE
138731947Sbostic 	   fseek(rfd, (long)refinfo[i].ri_pos, 0);
138831947Sbostic 	   while (fgets(line, REFSIZE, rfd) != NULL) {
138915903Srrh #else INCORE
139031947Sbostic 	   for (q = line, from = refinfo[i].ri_ref; *from; /*VOID*/) { /*} */
139131947Sbostic 		if (*from == '\n'){
139231947Sbostic 			*q++ = '\n';
139331947Sbostic 			*q = 0;
139431947Sbostic 			q = line;
139531947Sbostic 			from++;
139631947Sbostic 		} else {
139731947Sbostic 			*q++ = *from++;
139831947Sbostic 			continue;
139931947Sbostic 		}
140015903Srrh #endif INCORE
140131947Sbostic 		switch(line[0]){
140231947Sbostic 		case 0:
140331947Sbostic 			goto doneref;
140431947Sbostic 		case '.':
140531947Sbostic 			fprintf(ofd, "%s", line);
140631947Sbostic 			break;
140731947Sbostic 		case '%':
140831947Sbostic 			switch(line[1]){
140931947Sbostic 			case 'A':	numauths++;	break;
141031947Sbostic 			case 'E':	numeds++;	break;
141131947Sbostic 			}
141231947Sbostic 			for (p = &line[2]; *p == ' '; p++) /*VOID*/;
141331947Sbostic 			doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd);
141415903Srrh 		}
141531947Sbostic 	   }
141631947Sbostic 	   doneref:;
141731947Sbostic 	   fprintf(ofd,".][\n");
141815903Srrh    }
141915061Sgarrison }
1420