xref: /csrg-svn/contrib/bib/src/bibargs.c (revision 17248)
113110Srrh #ifndef lint
2*17248Srrh static char sccsid[] = "@(#)bibargs.c	2.7	10/12/84";
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 
1415061Sgarrison 
1515061Sgarrison 
1612910Sgarrison         read argument strings for bib and listrefs
1712910Sgarrison         do name formatting, printing lines, other actions common to both
1812910Sgarrison                                                         */
1912910Sgarrison # include <stdio.h>
2012910Sgarrison # include <ctype.h>
2112910Sgarrison # include "bib.h"
2212910Sgarrison # define LINELENGTH 1024
2312910Sgarrison # define MAXDEFS     500             /* maximum number of defined words */
2412910Sgarrison 
2512910Sgarrison /* global variables */
2615061Sgarrison    char bibfname[120];          /* file name currently being read            */
2715061Sgarrison    int  biblineno;              /* line number currently being referenced    */
2812910Sgarrison    int  abbrev       = false;   /* automatically abbreviate names            */
2912910Sgarrison    int  capsmcap     = false;   /* print names in caps small caps (CACM form)*/
3012910Sgarrison    int  numrev       = 0;       /* number of authors names to reverse        */
3112910Sgarrison    int  edabbrev     = false;   /* abbreviate editors names ?                */
3212910Sgarrison    int  edcapsmcap   = false;   /* print editors in cap small caps           */
3312910Sgarrison    int  ednumrev     = 0;       /* number of editors to reverse              */
3412910Sgarrison    int  sort         = false;   /* sort references ? (default no)            */
3512910Sgarrison    int  foot         = false;   /* footnoted references ? (default endnotes) */
3617246Srrh    int  doacite      = true;    /* place citations ? */
3712910Sgarrison    int  hyphen       = false;   /* hypenate contiguous references            */
3812910Sgarrison    int  ordcite      = true;    /* order multiple citations                  */
3912910Sgarrison    char sortstr[80]  = "1";     /* sorting template                          */
4012910Sgarrison    char trailstr[80] = "";      /* trailing characters to output             */
4112910Sgarrison    char pfile[120];             /* private file name                         */
4212910Sgarrison    int  personal = false;       /* personal file given ? (default no)        */
4312910Sgarrison    char citetemplate[80] = "1"; /* citation template                         */
4415903Srrh    struct wordinfo words[MAXDEFS];     /* defined words */
4515903Srrh    struct wordinfo *wordhash[HASHSIZE];
4615903Srrh    struct wordinfo *wordsearch();
4715903Srrh    int  wordtop = 0;           /* number of defined words         */
4812910Sgarrison 
4912910Sgarrison /* where output goes */
5012910Sgarrison    extern FILE *tfd;
5115061Sgarrison /* reference file information */
5215903Srrh    extern struct refinfo refinfo[];
5315061Sgarrison    extern char reffile[];
5415903Srrh #ifndef INCORE
5515061Sgarrison    extern FILE *rfd;
5615903Srrh #endif not INCORE
5715061Sgarrison    extern int numrefs;
5812910Sgarrison 
5912910Sgarrison /* doargs - read command argument line for both bib and listrefs
6012910Sgarrison             set switch values
6112910Sgarrison             call rdtext on file arguments, after dumping
6212910Sgarrison             default style file if no alternative style is given
6312910Sgarrison */
6412910Sgarrison    int doargs(argc, argv, defstyle)
6512910Sgarrison    int argc;
6612910Sgarrison    char **argv, defstyle[];
6712910Sgarrison {  int numfiles, i, style;
6812910Sgarrison    char *p, *q, *walloc();
6912910Sgarrison    FILE *fd;
7012910Sgarrison 
7112910Sgarrison    numfiles = 0;
7212910Sgarrison    style = true;
73*17248Srrh    newbibdir(BMACLIB);
7412910Sgarrison 
7512910Sgarrison    for (i = 1; i < argc; i++)
7612910Sgarrison       if (argv[i][0] == '-')
7712910Sgarrison          switch(argv[i][1]) {
78*17248Srrh 			case 'd':
79*17248Srrh 				if (argv[i][2])
80*17248Srrh 					p = &argv[i][2];
81*17248Srrh 				else {  /* take next arg */
82*17248Srrh 					i++;
83*17248Srrh 					p = argv[i];
84*17248Srrh 			}
85*17248Srrh 			newbibdir(p);
8615061Sgarrison             case 'a':  for (p = &argv[i][2]; *p; p++)
8715061Sgarrison                           if (*p == 'a' || *p == 0)
8812961Sgarrison                              abbrev = true;
8912961Sgarrison                            else if (*p == 'x')
9012961Sgarrison                              capsmcap = true;
9112961Sgarrison                            else if (*p == 'r') {
9212961Sgarrison                              if (*(p+1))
9312961Sgarrison                                 numrev = atoi(p+1);
9412961Sgarrison                               else
9512961Sgarrison                                 numrev = 1000;
9612961Sgarrison                               break;
9712961Sgarrison                               }
9812910Sgarrison                        break;
9912910Sgarrison 
10012910Sgarrison             case 'c':  if (argv[i][2] == 0)
10115903Srrh                           error("citation string expected for 'c'");
10212910Sgarrison                        else
10312910Sgarrison                           for (p = citetemplate,q = &argv[i][2]; *p++ = *q++; );
10412910Sgarrison                        break;
10512910Sgarrison 
10612910Sgarrison             case 'e':  for (p = &argv[i][2]; *p; p++)
10712910Sgarrison                           if (*p == 'a')
10812910Sgarrison                              edabbrev = true;
10912910Sgarrison                            else if (*p == 'x')
11012910Sgarrison                              edcapsmcap = true;
11112910Sgarrison                            else if (*p == 'r') {
11212910Sgarrison                              if (*(p+1))
11312910Sgarrison                                 ednumrev = atoi(p+1);
11412910Sgarrison                               else
11512910Sgarrison                                 ednumrev = 1000;
11612910Sgarrison                               break;
11712910Sgarrison                               }
11812910Sgarrison                        break;
11912910Sgarrison 
12017246Srrh             case 'v':  doacite = false;
12117246Srrh 			/*FALLTHROUGH*/
12212910Sgarrison             case 'f':  foot = true;
12312910Sgarrison                        hyphen = false;
12412910Sgarrison                        break;
12512910Sgarrison 
12612910Sgarrison             case 'h':  hyphen = ordcite = true;
12712910Sgarrison                        break;
12812910Sgarrison 
12912910Sgarrison             case 'n':  for (p = &argv[i][2]; *p; p++)
13012910Sgarrison                           if (*p == 'a')
13112910Sgarrison                              abbrev = false;
13217246Srrh                           else if (*p == 'v')
13317246Srrh                              doacite = true;
13412910Sgarrison                           else if (*p == 'f')
13512910Sgarrison                              foot = false;
13612910Sgarrison                           else if (*p == 'h')
13712910Sgarrison                              hyphen = false;
13812910Sgarrison                           else if (*p == 'o')
13912910Sgarrison                              ordcite = false;
14012910Sgarrison                           else if (*p == 'r')
14112910Sgarrison                              numrev = 0;
14212910Sgarrison                           else if (*p == 's')
14312910Sgarrison                              sort = false;
14412910Sgarrison                           else if (*p == 'x')
14512910Sgarrison                              capsmcap = false;
14612910Sgarrison                        break;
14712910Sgarrison 
14812910Sgarrison             case 'o':  ordcite = true;
14912910Sgarrison                        break;
15012910Sgarrison 
15112910Sgarrison             case 'p':  if (argv[i][2])
15212910Sgarrison                           p = &argv[i][2];
15312910Sgarrison                        else {  /* take next arg */
15412910Sgarrison                           i++;
15512910Sgarrison                           p = argv[i];
15612910Sgarrison                           }
15712910Sgarrison                        strcpy(pfile, p);
15812910Sgarrison                        personal = true;
15912910Sgarrison                        break;
16012910Sgarrison 
16115061Sgarrison             case 'r':  if (argv[i][2] == 0)  /* this is now replaced by -ar */
16212910Sgarrison                           numrev = 1000;
16312910Sgarrison                        else
16412910Sgarrison                           numrev = atoi(&argv[i][2]);
16512910Sgarrison                        break;
16612910Sgarrison 
16712910Sgarrison             case 's':  sort = true;
16812910Sgarrison                        if (argv[i][2])
16912910Sgarrison                           for (p = sortstr,q = &argv[i][2]; *p++ = *q++; );
17012910Sgarrison                        break;
17112910Sgarrison 
17215061Sgarrison             case 't':  style = false;           /* fall through */
17315061Sgarrison             case 'i':  if (argv[i][2])
17412910Sgarrison                           p = &argv[i][2];
17512910Sgarrison                        else { /* take next arg */
17612910Sgarrison                           i++;
17712910Sgarrison                           p = argv[i];
17812910Sgarrison                           }
17912910Sgarrison                        incfile(p);
18012910Sgarrison                        break;
18112910Sgarrison 
18215061Sgarrison             case 'x':  capsmcap = true; /* this is now replaced by -ax */
18312910Sgarrison                        break;
18412910Sgarrison 
18512910Sgarrison             case 0:    if (style) {  /* no style command given, take default */
18612910Sgarrison                           style = false;
18712910Sgarrison                           incfile( defstyle );
18812910Sgarrison                           }
18915061Sgarrison                        strcpy(bibfname,"<stdin>");
19012910Sgarrison                        rdtext(stdin);
19112910Sgarrison                        numfiles++;
19212910Sgarrison                        break;
19312910Sgarrison 
19412910Sgarrison             default:   fputs(argv[i], stderr);
19515903Srrh                        error("'%c' invalid switch", argv[i][1]);
19612910Sgarrison             }
19712910Sgarrison       else { /* file name */
19812910Sgarrison          numfiles++;
19912910Sgarrison          if (style) {
20012910Sgarrison             style = false;
20112910Sgarrison             incfile( defstyle );
20212910Sgarrison             }
20312910Sgarrison          fd = fopen(argv[i], "r");
20412910Sgarrison          if (fd == NULL) {
20515903Srrh             error("can't open file %s", argv[i]);
20612910Sgarrison             }
20712910Sgarrison          else {
20815061Sgarrison             strcpy(bibfname, argv[i]);
20912910Sgarrison             rdtext(fd);
21012910Sgarrison             fclose(fd);
21112910Sgarrison             }
21212910Sgarrison          }
21312910Sgarrison 
21412910Sgarrison    if (style) incfile( defstyle );
21512910Sgarrison    return(numfiles);
21612910Sgarrison 
21712910Sgarrison }
21812910Sgarrison 
219*17248Srrh newbibdir(name)
220*17248Srrh 	char *name;
221*17248Srrh {
222*17248Srrh 	strreplace(COMFILE, BMACLIB, name);
223*17248Srrh 	strreplace(DEFSTYLE, BMACLIB, name);
224*17248Srrh 	strcpy(BMACLIB, name);
225*17248Srrh 	wordstuff("BMACLIB", BMACLIB);
226*17248Srrh 	fprintf(tfd, ".ds l] %s\n", BMACLIB);
227*17248Srrh }
228*17248Srrh 
22912910Sgarrison /* incfile - read in an included file  */
23012910Sgarrison incfile(np)
23112910Sgarrison    char *np;
23212910Sgarrison {  char name[120];
23312910Sgarrison    FILE *fd;
23415061Sgarrison    char *p, line[LINELENGTH], dline[LINELENGTH], word[80], *tfgets();
23516244Srrh    int  i, getwrd();
23612910Sgarrison 
23715061Sgarrison    strcpy(bibfname, np);
23812910Sgarrison    fd = fopen(np, "r");
23912910Sgarrison    if (fd == NULL && *np != '/') {
24012910Sgarrison       strcpy(name, "bib.");
24112910Sgarrison       strcat(name, np);
24215061Sgarrison       strcpy(bibfname, name);
24312910Sgarrison       fd = fopen(name, "r");
24412910Sgarrison       }
24512910Sgarrison    if (fd == NULL && *np != '/') {
24612910Sgarrison       strcpy(name,BMACLIB);
24712910Sgarrison       strcat(name, "/bib.");
24812910Sgarrison       strcat(name, np);
24915061Sgarrison       strcpy(bibfname, name);
25012910Sgarrison       fd = fopen(name, "r");
25112910Sgarrison       }
25212910Sgarrison    if (fd == NULL) {
25315061Sgarrison       bibwarning("%s: can't open", np);
25415061Sgarrison       exit(1);
25512910Sgarrison       }
25612910Sgarrison 
25715061Sgarrison    /* now go off and process file */
25815061Sgarrison    biblineno = 1;
25915061Sgarrison    while (tfgets(line, LINELENGTH, fd) != NULL) {
26015061Sgarrison       biblineno++;
26112910Sgarrison       switch(line[0]) {
26212910Sgarrison 
26312910Sgarrison          case '#': break;
26412910Sgarrison 
26512961Sgarrison          case 'A': for (p = &line[1]; *p; p++)
26615061Sgarrison                       if (*p == 'A' || *p == '\0')
26712961Sgarrison                          abbrev = true;
26812961Sgarrison                       else if (*p == 'X')
26912961Sgarrison                          capsmcap = true;
27012961Sgarrison                       else if (*p == 'R') {
27112961Sgarrison                          if (*(p+1))
27212961Sgarrison                             numrev = atoi(p+1);
27312961Sgarrison                          else
27412961Sgarrison                             numrev = 1000;
27512961Sgarrison                          break;
27612961Sgarrison                          }
27712910Sgarrison                    break;
27812910Sgarrison 
27912910Sgarrison          case 'C': for (p = &line[1]; *p == ' '; p++) ;
28012910Sgarrison                    strcpy(citetemplate, p);
28112910Sgarrison                    break;
28212910Sgarrison 
28312910Sgarrison          case 'D': if ((i = getwrd(line, 1, word)) == 0)
28412910Sgarrison                       error("word expected in definition");
28515903Srrh 		   if (wordsearch(word))
28615903Srrh 			break;
28712910Sgarrison                    for (p = &line[i]; *p == ' '; p++) ;
28812910Sgarrison                    for (strcpy(dline, p); dline[strlen(dline)-1] == '\\'; ){
28912910Sgarrison                        dline[strlen(dline)-1] = '\n';
29015061Sgarrison                        if (tfgets(line, LINELENGTH, fd) == NULL) break;
29112910Sgarrison                        strcat(dline, line);
29212910Sgarrison                        }
29315903Srrh 		   wordstuff(word, dline);
29412910Sgarrison                    break;
29512910Sgarrison 
29612910Sgarrison          case 'E': for (p = &line[1]; *p; p++)
29712910Sgarrison                       if (*p == 'A')
29812910Sgarrison                          edabbrev = true;
29912910Sgarrison                       else if (*p == 'X')
30012910Sgarrison                          edcapsmcap = true;
30112910Sgarrison                       else if (*p == 'R') {
30212910Sgarrison                          if (*(p+1))
30312910Sgarrison                             ednumrev = atoi(p+1);
30412910Sgarrison                          else
30512910Sgarrison                             ednumrev = 1000;
30612910Sgarrison                          break;
30712910Sgarrison                          }
30812910Sgarrison                    break;
30912910Sgarrison 
31012910Sgarrison          case 'F': foot = true;
31112910Sgarrison                    hyphen = false;
31212910Sgarrison                    break;
31312910Sgarrison 
31412910Sgarrison          case 'I': for (p = &line[1]; *p == ' '; p++);
31512910Sgarrison                    expand(p);
31612910Sgarrison                    incfile(p);
31712910Sgarrison                    break;
31812910Sgarrison 
31912910Sgarrison          case 'H': hyphen = ordcite = true;
32012910Sgarrison                    break;
32112910Sgarrison 
32212910Sgarrison          case 'O': ordcite = true;
32312910Sgarrison                    break;
32412910Sgarrison 
32515061Sgarrison          case 'R': if (line[1] == 0)  /* this is now replaced by AR */
32612910Sgarrison                       numrev = 1000;
32712910Sgarrison                    else
32812910Sgarrison                       numrev = atoi(&line[1]);
32912910Sgarrison                    break;
33012910Sgarrison 
33112910Sgarrison          case 'S': sort = true;
33212910Sgarrison                    for (p = &line[1]; *p == ' '; p++) ;
33312910Sgarrison                    strcpy(sortstr, p);
33412910Sgarrison                    break;
33512910Sgarrison 
33612910Sgarrison          case 'T': for (p = &line[1]; *p == ' '; p++) ;
33712910Sgarrison                    strcpy(trailstr, p);
33812910Sgarrison                    break;
33912910Sgarrison 
34015061Sgarrison          case 'X': capsmcap = true;     /* this is now replace by AX */
34112910Sgarrison                    break;
34212910Sgarrison 
34312910Sgarrison          default:  fprintf(tfd,"%s\n",line);
34415061Sgarrison                    while (fgets(line, LINELENGTH, fd) != NULL)
34512910Sgarrison                       fputs(line, tfd);
34612910Sgarrison                    return;
34712910Sgarrison          }
34815061Sgarrison 
34915061Sgarrison    }
35015061Sgarrison    /* close up */
35115061Sgarrison    fclose(fd);
35212910Sgarrison }
35312910Sgarrison 
35415061Sgarrison /* bibwarning - print out a warning message */
35515903Srrh   /*VARARGS1*/
35615903Srrh   bibwarning(msg, a1, a2)
35715903Srrh   char *msg;
35815061Sgarrison {
35915061Sgarrison   fprintf(stderr,"`%s', line %d: ", bibfname, biblineno);
36015903Srrh   fprintf(stderr, msg, a1, a2);
361*17248Srrh   fprintf(stderr, "\n");
36215061Sgarrison }
36315061Sgarrison 
36415061Sgarrison /* error - report unrecoverable error message */
36515903Srrh   /*VARARGS1*/
36615903Srrh   error(str, a1, a2)
36715903Srrh   char *str;
36815061Sgarrison {
36915903Srrh   bibwarning(str, a1, a2);
37015903Srrh   /*
37115903Srrh    *	clean up temp files and exit
37215903Srrh    */
37315903Srrh   cleanup(1);
37415061Sgarrison }
37515061Sgarrison 
37615903Srrh #ifndef INCORE
37715061Sgarrison #ifdef READWRITE
37815061Sgarrison /*
37915061Sgarrison ** fixrfd( mode ) -- re-opens the rfd file to be read or write,
38015061Sgarrison **      depending on the mode.  Uses a static int to save the current mode
38115061Sgarrison **      and avoid unnecessary re-openings.
38215061Sgarrison */
38315061Sgarrison fixrfd( mode )
38415061Sgarrison register int mode;
38515061Sgarrison {
38615061Sgarrison 	static int cur_mode = WRITE;    /* rfd open for writing initially */
38715061Sgarrison 
38815061Sgarrison 	if (mode != cur_mode)
38915061Sgarrison 	{
39015061Sgarrison 		rfd = freopen(reffile, ((mode == READ)? "r" : "a"), rfd);
39115061Sgarrison 		cur_mode = mode;
39215061Sgarrison 		if (rfd == NULL)
39315903Srrh 		      error("Hell!  Couldn't re-open reference file %s",
39415903Srrh 			reffile);
39515061Sgarrison 	}
39615061Sgarrison }
39715061Sgarrison #endif
39815903Srrh #endif not INCORE
39915061Sgarrison 
40015061Sgarrison 
40115061Sgarrison /* tfgets - fgets which trims off newline */
40215061Sgarrison    char *tfgets(line, n, ptr)
40315061Sgarrison    char line[];
40415061Sgarrison    int  n;
40515061Sgarrison    FILE *ptr;
40615903Srrh {  reg char *p;
40715061Sgarrison 
40815061Sgarrison    p = fgets(line, n, ptr);
40915061Sgarrison    if (p == NULL)
41015061Sgarrison       return(NULL);
41115061Sgarrison    else
41215061Sgarrison       for (p = line; *p; p++)
41315061Sgarrison          if (*p == '\n')
41415061Sgarrison             *p = 0;
41515061Sgarrison    return(line);
41615061Sgarrison }
41715061Sgarrison 
41815061Sgarrison /* getwrd - place next word from in[i] into out */
41915061Sgarrison int getwrd(in, i, out)
42015903Srrh    reg char in[], out[];
42115903Srrh    reg int i;
42215061Sgarrison {  int j;
42315061Sgarrison 
42415061Sgarrison    j = 0;
42515061Sgarrison    while (in[i] == ' ' || in[i] == '\n' || in[i] == '\t')
42615061Sgarrison       i++;
42715061Sgarrison    if (in[i])
42815061Sgarrison       while (in[i] && in[i] != ' ' && in[i] != '\t' && in[i] != '\n')
42915061Sgarrison          out[j++] = in[i++];
43015061Sgarrison    else
43115061Sgarrison       i = 0;    /* signals end of in[i..]   */
43215061Sgarrison    out[j] = 0;
43315061Sgarrison    return (i);
43415061Sgarrison }
43515061Sgarrison 
43615061Sgarrison /* walloc - allocate enough space for a word */
43715061Sgarrison char *walloc(word)
43815061Sgarrison    char *word;
43915061Sgarrison {  char *i, *malloc();
44015061Sgarrison    i = malloc(1 + strlen(word));
44115061Sgarrison    if (i == NULL)
44215061Sgarrison       error("out of storage");
44315061Sgarrison    strcpy(i, word);
44415061Sgarrison    return(i);
44515061Sgarrison }
44615061Sgarrison 
44712910Sgarrison /* isword - see if character is legit word char */
44812910Sgarrison int iswordc(c)
44912910Sgarrison char c;
45012910Sgarrison {
45112910Sgarrison    if (isalnum(c) || c == '&' || c == '_')
45212910Sgarrison       return(true);
45312910Sgarrison    return(false);
45412910Sgarrison }
45512910Sgarrison    expand(line)
45612910Sgarrison    char *line;
45715903Srrh {  char line2[REFSIZE], word[LINELENGTH];
45815903Srrh    reg	struct wordinfo *wp;
45915903Srrh    reg	char *p, *q, *w;
46012910Sgarrison 
46115903Srrh 	q = line2;
46215903Srrh 	for (p = line; *p; /*VOID*/){
46315903Srrh 		if (isalnum(*p)) {
46415903Srrh 			for (w = word; *p && iswordc(*p); ) *w++ = *p++;
46515903Srrh 			*w = 0;
46615903Srrh 			if (wp = wordsearch(word)){
46715903Srrh 				strcpy(word, wp->wi_def);
46815903Srrh 				expand(word);
46915903Srrh 			}
47015903Srrh 			strcpy(q, word);
47115903Srrh 			q += strlen(q);
47215903Srrh 		} else {
47315903Srrh 			*q++ = *p++;
47415903Srrh 		}
47515903Srrh 	}
47615903Srrh 	*q = 0;
47715903Srrh 	strcpy(line, line2);
47812910Sgarrison }
47912910Sgarrison 
48015903Srrh /* wordstuff- save a word and its definition, building a hash table */
48115903Srrh    wordstuff(word, def)
48215903Srrh    char *word, *def;
48315903Srrh {
48415903Srrh    int i;
48515903Srrh    if (wordtop >= MAXDEFS)
48615903Srrh 	error("too many definitions, max of %d", MAXDEFS);
48715903Srrh    words[wordtop].wi_length = strlen(word);
48815903Srrh    words[wordtop].wi_word = word ? walloc(word) : 0;
48915903Srrh    words[wordtop].wi_def = def ? walloc(def) : 0;
49015903Srrh    i = strhash(word);
49115903Srrh    words[wordtop].wi_hp = wordhash[i];
49215903Srrh    wordhash[i] = &words[wordtop];
49315903Srrh    wordtop++;
49415903Srrh }
49515903Srrh    struct wordinfo *wordsearch(word)
49615903Srrh    char *word;
49715903Srrh {
49815903Srrh    reg int lg;
49915903Srrh    reg struct wordinfo *wp;
50015903Srrh    lg = strlen(word);
50115903Srrh    for (wp = wordhash[strhash(word)]; wp; wp = wp->wi_hp){
50215903Srrh 	if (wp->wi_length == lg && (strcmp(wp->wi_word, word) == 0)){
50315903Srrh 		return(wp);
50415903Srrh 	}
50515903Srrh    }
50615903Srrh    return(0);
50715903Srrh }
50815903Srrh 
50915903Srrh    int strhash(str)
51015903Srrh    reg char *str;
51115903Srrh {
51215903Srrh    reg int value = 0;
51315903Srrh    for (value = 0; *str; value <<= 2, value += *str++)/*VOID*/;
51415903Srrh    value %= HASHSIZE;
51515903Srrh    if (value < 0)
51615903Srrh 	value += HASHSIZE;
51715903Srrh    return(value);
51815903Srrh }
51915903Srrh 
52015061Sgarrison /* rdref - read text for an already cited reference */
52115903Srrh    rdref(p, ref)
52215903Srrh    struct refinfo *p;
52315061Sgarrison    char ref[REFSIZE];
52415061Sgarrison {
52515061Sgarrison    ref[0] = 0;
52615903Srrh #ifndef INCORE
52715061Sgarrison #ifdef READWRITE
52815061Sgarrison    fixrfd( READ );                      /* fix access mode of rfd, if nec. */
52915061Sgarrison #endif
53015903Srrh    fseek(rfd, p->ri_pos, 0);
53115903Srrh    fread(ref, p->ri_length, 1, rfd);
53215903Srrh #else INCORE
53315903Srrh    strcpy(ref, p->ri_ref);
53415903Srrh #endif INCORE
53515061Sgarrison }
53615061Sgarrison 
53715903Srrh /* wrref - write text for a new reference */
53815903Srrh    wrref(p, ref)
53915903Srrh    struct refinfo *p;
54015903Srrh    char ref[REFSIZE];
54115903Srrh {
54215903Srrh #ifndef INCORE
54315903Srrh #ifdef READWRITE
54415903Srrh     fixrfd( WRITE );                 /* fix access mode of rfd, if nec. */
54515903Srrh #else
54615903Srrh     fseek(rfd, p->ri_pos, 0);        /* go to end of rfd */
54715903Srrh #endif
54815903Srrh     fwrite(ref, p->ri_length, 1, rfd);
54915903Srrh #else INCORE
55015903Srrh    p->ri_ref = walloc(ref);
55115903Srrh #endif INCORE
55215903Srrh }
55315903Srrh 
55412910Sgarrison /* breakname - break a name into first and last name */
55512910Sgarrison    breakname(line, first, last)
55612910Sgarrison    char line[], first[], last[];
55715903Srrh {  reg char *t, *f, *q, *r, *p;
55812910Sgarrison 
55912910Sgarrison    for (t = line; *t != '\n'; t++);
56012910Sgarrison    for (t--; isspace(*t); t--);
56112910Sgarrison 
56212910Sgarrison    /* now strip off last name */
56312910Sgarrison    for (q = t; isspace(*q) == 0 || ((*q == ' ') & (*(q-1) == '\\')); q--)
56412910Sgarrison       if (q == line)
56512910Sgarrison          break;
56612910Sgarrison    f = q;
56715061Sgarrison    if (q != line) {
56812910Sgarrison       q++;
56915061Sgarrison       for (; isspace(*f); f--);
57015061Sgarrison       f++;
57115061Sgarrison       }
57212910Sgarrison 
57312910Sgarrison    /* first name is start to f, last name is q to t */
57412910Sgarrison 
57515061Sgarrison    for (r = first, p = line; p != f; )
57612910Sgarrison       *r++ = *p++;
57712910Sgarrison    *r = 0;
57812910Sgarrison    for (r = last, p = q, t++; q != t; )
57912910Sgarrison       *r++ = *q++;
58012910Sgarrison    *r = 0;
58115061Sgarrison 
58212910Sgarrison }
58312910Sgarrison 
58412910Sgarrison /* match - see if string1 is a substring of string2 (case independent)*/
58512910Sgarrison    int match(str1, str2)
58615903Srrh    reg char str1[], str2[];
58715903Srrh {  reg int  j, i;
58812910Sgarrison    char a, b;
58912910Sgarrison 
59012910Sgarrison    for (i = 0; str2[i]; i++) {
59112910Sgarrison       for (j = 0; str1[j]; j++) {
59212910Sgarrison          if (isupper(a = str2[i+j]))
59312910Sgarrison             a = (a - 'A') + 'a';
59412910Sgarrison          if (isupper(b = str1[j]))
59512910Sgarrison             b = (b - 'A') + 'a';
59612910Sgarrison          if (a != b)
59712910Sgarrison             break;
59812910Sgarrison          }
59912910Sgarrison       if (str1[j] == 0)
60012910Sgarrison          return(true);
60112910Sgarrison       }
60212910Sgarrison    return(false);
60312910Sgarrison }
60412910Sgarrison 
60512910Sgarrison /* scopy - append a copy of one string to another */
60612910Sgarrison    char *scopy(p, q)
60715903Srrh    reg char *p, *q;
60812910Sgarrison {
60912910Sgarrison    while (*p++ = *q++)
61012910Sgarrison       ;
61112910Sgarrison    return(--p);
61212910Sgarrison }
61312910Sgarrison 
61415061Sgarrison /* rcomp - reference comparison routine for qsort utility */
61515061Sgarrison    int rcomp(ap, bp)
61615903Srrh    struct refinfo *ap, *bp;
61715061Sgarrison {  char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD];
61815903Srrh    reg	char *p, *q;
61915903Srrh    char *getfield();
62015061Sgarrison    int  neg, res;
62115061Sgarrison    int  fields_found;
62215061Sgarrison 
62315903Srrh    rdref(ap, ref1);
62415903Srrh    rdref(bp, ref2);
62515061Sgarrison    for (p = sortstr; *p; p = q) {
62615061Sgarrison       if (*p == '-') {
62715061Sgarrison          p++;
62815061Sgarrison          neg = true;
62915061Sgarrison          }
63015061Sgarrison       else
63115061Sgarrison          neg = false;
63215061Sgarrison       q = getfield(p, field1, ref1);
63315061Sgarrison       fields_found = true;
63415061Sgarrison       if (q == 0) {
63515061Sgarrison 	 res = 1;
63615061Sgarrison 	 fields_found = false;
63715061Sgarrison       } else if (strcmp (field1, "") == 0) {	/* field not found */
63815061Sgarrison          if (*p == 'A') {
63915061Sgarrison             getfield("F", field1, ref1);
64015061Sgarrison 	    if (strcmp (field1, "") == 0) {
64115061Sgarrison                getfield("I", field1, ref1);
64215061Sgarrison 	       if (strcmp (field1, "") == 0) {
64315061Sgarrison 	          res = 1;
64415061Sgarrison 		  fields_found = false;
64515061Sgarrison 	       }
64615061Sgarrison 	    }
64715061Sgarrison 	 } else {
64815061Sgarrison 	    res = 1;
64915061Sgarrison 	    fields_found = false;
65015061Sgarrison 	 }
65115061Sgarrison       }
65215061Sgarrison 
65315061Sgarrison       if (getfield(p, field2, ref2) == 0) {
65415061Sgarrison 	 res = -1;
65515061Sgarrison 	 fields_found = false;
65615061Sgarrison       } else if (strcmp (field2, "") == 0) {	/* field not found */
65715061Sgarrison          if (*p == 'A') {
65815061Sgarrison             getfield("F", field2, ref2);
65915061Sgarrison 	    if (strcmp (field2, "") == 0) {
66015061Sgarrison                getfield("I", field2, ref2);
66115061Sgarrison 	       if (strcmp (field2, "") == 0) {
66215061Sgarrison 	          res = -1;
66315061Sgarrison 		  fields_found = false;
66415061Sgarrison 	       }
66515061Sgarrison 	    }
66615061Sgarrison 	 } else {
66715061Sgarrison 	    res = -1;
66815061Sgarrison 	    fields_found = false;
66915061Sgarrison 	 }
67015061Sgarrison       }
67115061Sgarrison       if (fields_found) {
67215061Sgarrison          if (*p == 'A') {
67315061Sgarrison             if (isupper(field1[0]))
67415061Sgarrison                field1[0] -= 'A' - 'a';
67515061Sgarrison             if (isupper(field2[0]))
67615061Sgarrison                field2[0] -= 'A' - 'a';
67715061Sgarrison             }
67815061Sgarrison          res = strcmp(field1, field2);
67915061Sgarrison          }
68015061Sgarrison       if (neg)
68115061Sgarrison          res = - res;
68215061Sgarrison       if (res != 0)
68315061Sgarrison          break;
68415061Sgarrison       }
68515061Sgarrison    if (res == 0)
68615061Sgarrison       if (ap < bp)
68715061Sgarrison          res = -1;
68815061Sgarrison       else
68915061Sgarrison          res = 1;
69015061Sgarrison    return(res);
69115061Sgarrison }
69215061Sgarrison 
69316244Srrh /* makecites - make standard citation strings, using citetemplate currently in effect */
69415903Srrh    makecites()
69515061Sgarrison {  char ref[REFSIZE], tempcite[100], *malloc();
69615903Srrh    reg int  i;
69715061Sgarrison 
69815903Srrh    for (i = 0; i < numrefs; i++) {
69915903Srrh       rdref(&refinfo[i], ref);
70015061Sgarrison       bldcite(tempcite, i, ref);
70116244Srrh       refinfo[i].ri_cite = malloc(2 + strlen(tempcite));
70215903Srrh       if (refinfo[i].ri_cite == NULL)
70315061Sgarrison          error("out of storage");
70415903Srrh       strcpy(refinfo[i].ri_cite, tempcite);
70515061Sgarrison       }
70615061Sgarrison }
70715061Sgarrison 
70815061Sgarrison /* bldcite - build a single citation string */
70915061Sgarrison    bldcite(cp, i, ref)
71015061Sgarrison    char *cp, ref[];
71115061Sgarrison    int  i;
71215903Srrh {  reg char *p, *q, *fp;
71315903Srrh    char c;
71415903Srrh    char field[REFSIZE];
71515890Srrh    char *getfield(), *aabet(), *aabetlast(), *astro();
71615061Sgarrison 
71715061Sgarrison    getfield("F", field, ref);
71815061Sgarrison    if (field[0] != 0)
71915061Sgarrison       for (p = field; *p; p++)
72015061Sgarrison          *cp++ = *p;
72115061Sgarrison    else {
72215061Sgarrison       p = citetemplate;
72315061Sgarrison       field[0] = 0;
72415061Sgarrison       while (c = *p++) {
72515061Sgarrison          if (isalpha(c)) {                      /* field name   */
72615061Sgarrison             q = getfield(p-1, field, ref);
72715061Sgarrison             if (q != 0) {
72815061Sgarrison                p = q;
72915061Sgarrison                for (fp = field; *fp; )
73015061Sgarrison                   *cp++ = *fp++;
73115061Sgarrison                }
73215061Sgarrison             }
73315061Sgarrison          else if (c == '1') {                   /* numeric  order */
73415061Sgarrison             sprintf(field,"%d",1 + i);
73515061Sgarrison             for (fp = field; *fp; )
73615061Sgarrison                *cp++ = *fp++;
73715061Sgarrison             }
73815061Sgarrison          else if (c == '2')                     /* alternate alphabetic */
73915061Sgarrison             cp = aabet(cp, ref);
74015061Sgarrison          else if (c == '3')                     /* Astrophysical Journal style*/
74115061Sgarrison             cp = astro(cp, ref);
74215890Srrh          else if (c == '9')                     /* Last name of Senior Author*/
74315890Srrh             cp = aabetlast(cp, ref);
74417246Srrh 	 else if (c == '0') {			/* print nothing */
74517246Srrh             for (fp = field; *fp; )
74617246Srrh                *cp++ = *fp++;
74717246Srrh             }
74815061Sgarrison /*       else if (c == '4')          here is how to add new styles */
74915061Sgarrison          else if (c == '{') {                   /* other information   */
75015061Sgarrison             while (*p != '}')
75115061Sgarrison                if (*p == 0)
75215061Sgarrison                   error("unexpected end of citation template");
75315061Sgarrison                else
75415061Sgarrison                   *cp++ = *p++;
75515061Sgarrison             p++;
75615061Sgarrison             }
75715061Sgarrison          else if (c == '<') {
75815061Sgarrison             while (*p != '>') {
75915061Sgarrison                if (*p == 0)
76015061Sgarrison                   error("unexpected end of citation template");
76115061Sgarrison                else
76215061Sgarrison                   *cp++ = *p++;
76315061Sgarrison                }
76415061Sgarrison             p++;
76515061Sgarrison             }
76615061Sgarrison          else if (c != '@')
76715061Sgarrison             *cp++ = c;
76815061Sgarrison          }
76915061Sgarrison       }
77015061Sgarrison    *cp++ = 0;
77115061Sgarrison }
77215061Sgarrison 
77315061Sgarrison /* alternate alphabetic citation style -
77415061Sgarrison         if 1 author - first three letters of last name
77515061Sgarrison         if 2 authors - first two letters of first, followed by first letter of
77615061Sgarrison                                 seond
77715061Sgarrison         if 3 or more authors - first letter of first three authors */
77815061Sgarrison    char *aabet(cp, ref)
77915061Sgarrison    char *cp, ref[];
78015903Srrh {  char field[REFSIZE], temp[100];
78115903Srrh    reg char *np, *fp;
78215061Sgarrison    int j, getname();
78315061Sgarrison 
78415061Sgarrison    if (getname(1, field, temp, ref)) {
78515061Sgarrison       np = cp;
78615061Sgarrison       fp = field;
78715061Sgarrison       for (j = 1; j <= 3; j++)
78815061Sgarrison          if (*fp != 0)
78915061Sgarrison             *cp++ = *fp++;
79015061Sgarrison       if (getname(2, field, temp, ref))
79115061Sgarrison          np[2] = field[0];
79215061Sgarrison       if (getname(3, field, temp, ref)) {
79315061Sgarrison          np[1] = np[2];
79415061Sgarrison          np[2] = field[0];
79515061Sgarrison          }
79615061Sgarrison       }
79715061Sgarrison return(cp);
79815061Sgarrison }
79915061Sgarrison 
80015890Srrh /* alternate alphabetic citation style -
80115890Srrh 	entire last name of senior author
80215890Srrh */
80315890Srrh    char *aabetlast(cp, ref)
80415890Srrh    char *cp, ref[];
80515890Srrh {  char field[REFSIZE], temp[100];
80615903Srrh    reg char	*fp;
80715890Srrh    int getname();
80815890Srrh 
80915890Srrh    if (getname(1, field, temp, ref)) {
81015890Srrh       for (fp = field; *fp; )
81115890Srrh          *cp++ = *fp++;
81215890Srrh    }
81315890Srrh    return(cp);
81415890Srrh }
81515890Srrh 
81615061Sgarrison /* Astrophysical Journal style
81715061Sgarrison         if 1 author - last name date
81815061Sgarrison         if 2 authors - last name and last name date
81915061Sgarrison         if 3 authors - last name, last name and last name date
82015061Sgarrison         if 4 or more authors - last name et al. date */
82115061Sgarrison    char *astro(cp, ref)
82215061Sgarrison    char *cp, ref[];
82315903Srrh {  char name1[100], name2[100], name3[100], temp[100];
82415903Srrh    reg char *fp;
82515061Sgarrison    int getname();
82615061Sgarrison 
82715061Sgarrison    if (getname(1, name1, temp, ref)) {
82815061Sgarrison       for (fp = name1; *fp; )
82915061Sgarrison          *cp++ = *fp++;
83015061Sgarrison       if (getname(4, name3, temp, ref)) {
83115061Sgarrison          for (fp = " et al."; *fp; )
83215061Sgarrison             *cp++ = *fp++;
83315061Sgarrison          }
83415061Sgarrison       else if (getname(2, name2, temp, ref)) {
83515061Sgarrison          if (getname(3, name3, temp, ref)) {
83615061Sgarrison             for (fp = "\\*(c]"; *fp; )
83715061Sgarrison                *cp++ = *fp++;
83815061Sgarrison             for (fp = name2; *fp; )
83915061Sgarrison                *cp++ = *fp++;
84015061Sgarrison             for (fp = "\\*(m]"; *fp; )
84115061Sgarrison                *cp++ = *fp++;
84215061Sgarrison             for (fp = name3; *fp; )
84315061Sgarrison                *cp++ = *fp++;
84415061Sgarrison             }
84515061Sgarrison          else {
84615061Sgarrison             for (fp = "\\*(n]"; *fp; )
84715061Sgarrison                *cp++ = *fp++;
84815061Sgarrison             for (fp = name2; *fp; )
84915061Sgarrison                *cp++ = *fp++;
85015061Sgarrison             }
85115061Sgarrison          }
85215061Sgarrison     }
85315061Sgarrison return(cp);
85415061Sgarrison }
85515061Sgarrison 
85615061Sgarrison /* getfield - get a single field from reference */
85715061Sgarrison    char *getfield(ptr, field, ref)
85815061Sgarrison    char *ptr, field[], ref[];
85915903Srrh {  reg	char *p, *q;
86015903Srrh    char	temp[100];
86115061Sgarrison    int  n, len, i, getname();
86215061Sgarrison 
86315061Sgarrison    field[0] = 0;
86415061Sgarrison    if (*ptr == 'A')
86515061Sgarrison       getname(1, field, temp, ref);
86615061Sgarrison    else
86715061Sgarrison       for (p = ref; *p; p++)
86815061Sgarrison          if (*p == '%' && *(p+1) == *ptr) {
86915061Sgarrison             for (p = p + 2; *p == ' '; p++)
87015061Sgarrison                ;
87115061Sgarrison             for (q = field; (*p != '\n') && (*p != '\0'); )
87215061Sgarrison                *q++ = *p++;
87315061Sgarrison             *q = 0;
87415061Sgarrison             break;
87515061Sgarrison             }
87615061Sgarrison    n = 0;
87715061Sgarrison    len = strlen(field);
87815061Sgarrison    if (*++ptr == '-') {
87915061Sgarrison       for (ptr++; isdigit(*ptr); ptr++)
88015061Sgarrison          n = 10 * n + (*ptr - '0');
88115061Sgarrison       if (n > len)
88215061Sgarrison          n = 0;
88315061Sgarrison       else
88415061Sgarrison          n = len - n;
88515061Sgarrison       for (i = 0; field[i] = field[i+n]; i++)
88615061Sgarrison          ;
88715061Sgarrison       }
88815061Sgarrison    else if (isdigit(*ptr)) {
88915061Sgarrison       for (; isdigit(*ptr); ptr++)
89015061Sgarrison          n = 10 * n + (*ptr - '0');
89115061Sgarrison       if (n > len)
89215061Sgarrison          n = len;
89315061Sgarrison       field[n] = 0;
89415061Sgarrison       }
89515061Sgarrison 
89615061Sgarrison    if (*ptr == 'u') {
89715061Sgarrison       ptr++;
89815061Sgarrison       for (p = field; *p; p++)
89915061Sgarrison          if (islower(*p))
90015061Sgarrison             *p = (*p - 'a') + 'A';
90115061Sgarrison       }
90215061Sgarrison    else if (*ptr == 'l') {
90315061Sgarrison       ptr++;
90415061Sgarrison       for (p = field; *p; p++)
90515061Sgarrison          if (isupper(*p))
90615061Sgarrison             *p = (*p - 'A') + 'a';
90715061Sgarrison       }
90815061Sgarrison    return(ptr);
90915061Sgarrison }
91015061Sgarrison 
91115061Sgarrison /* getname - get the nth name field from reference, breaking into
91215061Sgarrison              first and last names */
91315061Sgarrison    int getname(n, last, first, ref)
91415061Sgarrison    int  n;
91515061Sgarrison    char last[], first[], ref[];
91615903Srrh {  reg char *p;
91715061Sgarrison    int  m;
91815061Sgarrison 
91915061Sgarrison    m = n;
92015061Sgarrison    for (p = ref; *p; p++)
92115061Sgarrison       if (*p == '%' & *(p+1) == 'A') {
92215061Sgarrison          n--;
92315061Sgarrison          if (n == 0) {
92415061Sgarrison             for (p = p + 2; *p == ' '; p++) ;
92515061Sgarrison             breakname(p, first, last) ;
92615061Sgarrison             return(true);
92715061Sgarrison             }
92815061Sgarrison          }
92915061Sgarrison 
93015061Sgarrison    if (n == m)          /* no authors, try editors */
93115061Sgarrison       for (p = ref; *p; p++)
93215061Sgarrison          if (*p == '%' & *(p+1) == 'E') {
93315061Sgarrison             n--;
93415061Sgarrison             if (n == 0) {
93515061Sgarrison                for (p = p + 2; *p == ' '; p++) ;
93615061Sgarrison                breakname(p, first, last) ;
93715061Sgarrison                return(true);
93815061Sgarrison                }
93915061Sgarrison             }
94015061Sgarrison 
94115061Sgarrison    if (n == m) {        /* no editors, either, try institution */
94215061Sgarrison       first[0] = last[0] = '\0';
94315061Sgarrison       getfield("I", last, ref);
94415061Sgarrison       if (last[0] != '\0')
94515061Sgarrison          return(true);
94615061Sgarrison       }
94715061Sgarrison 
94815061Sgarrison    return(false);
94915061Sgarrison }
95015061Sgarrison 
95115061Sgarrison /* disambiguate - compare adjacent citation strings, and if equal, add
95215061Sgarrison                   single character disambiguators */
95315061Sgarrison    disambiguate()
95415903Srrh {  reg int i, j;
95516244Srrh 	char adstr;
95615061Sgarrison 
95715061Sgarrison    for (i = 0; i < numrefs; i = j) {
95815061Sgarrison       j = i + 1;
95915903Srrh       if (strcmp(refinfo[i].ri_cite, refinfo[j].ri_cite)==0) {
96016244Srrh          adstr = 'a';
96115903Srrh          for(j = i+1; strcmp(refinfo[i].ri_cite,refinfo[j].ri_cite) == 0; j++) {
96216244Srrh             adstr = 'a' + (j-i);
96315061Sgarrison             if (j == numrefs)
96415061Sgarrison                break;
96516244Srrh 	    refinfo[j].ri_disambig[0] = adstr;
96615061Sgarrison             }
96716244Srrh 	 refinfo[i].ri_disambig[0] = 'a';
96815061Sgarrison          }
96915061Sgarrison      }
97016244Srrh   for (i = 0; i < numrefs; i++){
97116244Srrh 	strcat(refinfo[i].ri_cite, refinfo[i].ri_disambig);
97216244Srrh   }
97315061Sgarrison }
97415061Sgarrison 
97515061Sgarrison 
97612910Sgarrison /* bldname - build a name field
97712910Sgarrison              doing abbreviations, reversals, and caps/small caps
97812910Sgarrison */
97912910Sgarrison    bldname(first, last, name, reverse)
98012910Sgarrison    char *first, *last, name[];
98112910Sgarrison    int reverse;
98212910Sgarrison {
98315903Srrh    char newfirst[120], newlast[120];
98415903Srrh    reg char *p, *q, *f, *l;
98515903Srrh    char *scopy();
98612910Sgarrison    int  flag;
98712910Sgarrison 
98812910Sgarrison    if (abbrev) {
98912910Sgarrison       p = first;
99012910Sgarrison       q = newfirst;
99112910Sgarrison       flag = false;
99212910Sgarrison       while (*p) {
99312910Sgarrison          while (*p == ' ')
99412910Sgarrison             p++;
99512910Sgarrison          if (*p == 0)
99612910Sgarrison             break;
99712910Sgarrison          if (isupper(*p)) {
99815061Sgarrison             if (flag)           /* between initial gap */
99912910Sgarrison                q = scopy(q, "\\*(a]");
100012910Sgarrison             flag = true;
100112910Sgarrison             *q++ = *p;
100215061Sgarrison             q = scopy(q, "\\*(p]");
100312910Sgarrison             }
100412910Sgarrison          if (*++p == '.')
100512910Sgarrison             p++;
100612910Sgarrison          else while (*p != 0 && ! isspace(*p))
100712910Sgarrison             p++;
100812910Sgarrison          }
100912910Sgarrison       *q = 0;
101012910Sgarrison       f = newfirst;
101112910Sgarrison       }
101212910Sgarrison    else
101312910Sgarrison       f = first;
101412910Sgarrison 
101512910Sgarrison    if (capsmcap) {
101612910Sgarrison       p = last;
101712910Sgarrison       q = newlast;
101812910Sgarrison       flag = 0;  /* 1 - printing cap, 2 - printing small */
101912910Sgarrison       while (*p)
102012910Sgarrison          if (islower(*p)) {
102112910Sgarrison             if (flag != 2)
102212910Sgarrison                q = scopy(q, "\\s-2");
102312910Sgarrison             flag = 2;
102412910Sgarrison             *q++ = (*p++ - 'a') + 'A';
102512910Sgarrison             }
102612910Sgarrison          else {
102712910Sgarrison             if (flag == 2)
102812910Sgarrison                q = scopy(q,"\\s+2");
102912910Sgarrison             flag = 1;
103012910Sgarrison             *q++ = *p++;
103112910Sgarrison             }
103212910Sgarrison       if (flag == 2)
103312910Sgarrison          q = scopy(q, "\\s+2");
103412910Sgarrison       *q = 0;
103512910Sgarrison       l = newlast;
103612910Sgarrison       }
103712910Sgarrison    else
103812910Sgarrison       l = last;
103912910Sgarrison 
104015061Sgarrison    if (f[0] == 0)
104115061Sgarrison       sprintf(name, "%s\n", l);
104215061Sgarrison    else if (reverse)
104315061Sgarrison       sprintf(name, "%s\\*(b]%s\n", l, f);
104412910Sgarrison    else
104512910Sgarrison       sprintf(name, "%s %s\n", f, l);
104612910Sgarrison }
104712910Sgarrison 
104812910Sgarrison /* prtauth - print author or editor field */
104912910Sgarrison    prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev)
105012910Sgarrison    char c, *line;
105112910Sgarrison    int  num, max, abbrev, capsmcap, numrev;
105212910Sgarrison    FILE *ofd;
105312910Sgarrison {  char first[LINELENGTH], last[LINELENGTH];
105412910Sgarrison 
105512910Sgarrison    if (num <= numrev || abbrev || capsmcap) {
105612910Sgarrison       breakname(line, first, last);
105712910Sgarrison       bldname(first, last, line, num <= numrev);
105812910Sgarrison       }
105912910Sgarrison    if (num == 1)
106012910Sgarrison       fprintf(ofd,".ds [%c %s", c, line);
106112910Sgarrison    else if (num < max)
106212910Sgarrison       fprintf(ofd,".as [%c \\*(c]%s", c, line);
106312910Sgarrison    else if (max == 2)
106412910Sgarrison       fprintf(ofd,".as [%c \\*(n]%s", c, line);
106512910Sgarrison    else
106612910Sgarrison       fprintf(ofd,".as [%c \\*(m]%s", c, line);
106712910Sgarrison    if (num == max && index(trailstr, c))
106812910Sgarrison       fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
106912910Sgarrison }
107012910Sgarrison 
107112910Sgarrison /* doline - actually print out a line of reference information */
107212910Sgarrison    doline(c, line, numauths, maxauths, numeds, maxeds, ofd)
107312910Sgarrison    char c, *line;
107412910Sgarrison    int numauths, maxauths, numeds, maxeds;
107512910Sgarrison    FILE *ofd;
107612910Sgarrison {
107712910Sgarrison 
107812910Sgarrison    switch(c) {
107912910Sgarrison       case 'A':
108012910Sgarrison           prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev);
108112910Sgarrison           break;
108212910Sgarrison 
108312910Sgarrison        case 'E':
108412910Sgarrison           prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, ednumrev);
108512910Sgarrison           if (numeds == maxeds)
108612910Sgarrison              fprintf(ofd,".nr [E %d\n", maxeds);
108712910Sgarrison           break;
108812910Sgarrison 
108912910Sgarrison        case 'P':
109012910Sgarrison           if (index(line, '-'))
109112910Sgarrison              fprintf(ofd,".nr [P 1\n");
109212910Sgarrison           else
109312910Sgarrison              fprintf(ofd,".nr [P 0\n");
109412910Sgarrison           fprintf(ofd,".ds [P %s",line);
109512910Sgarrison           if (index(trailstr, 'P'))
109612910Sgarrison              fprintf(ofd,".ds ]P %c\n",line[strlen(line)-2]);
109712910Sgarrison           break;
109812910Sgarrison 
109912910Sgarrison        case 'F':
110012910Sgarrison        case 'K': break;
110112910Sgarrison 
110212910Sgarrison        default:
110312910Sgarrison           fprintf(ofd,".ds [%c %s", c, line);
110412910Sgarrison           if (index(trailstr, c))
110512910Sgarrison              fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
110612910Sgarrison           }
110712910Sgarrison }
110812910Sgarrison 
110915061Sgarrison /* dumpref - dump reference number i */
111015061Sgarrison    dumpref(i, ofd)
111115061Sgarrison    int i;
111215061Sgarrison    FILE *ofd;
111315903Srrh {  char ref[REFSIZE], line[REFSIZE];
111415903Srrh    reg char *p, *q;
111515903Srrh    char *from;
111615061Sgarrison    int numauths, maxauths, numeds, maxeds;
111715061Sgarrison 
111815903Srrh    rdref(&refinfo[i], ref);
111915061Sgarrison    maxauths = maxeds = 0;
112015061Sgarrison    numauths = numeds = 0;
112115061Sgarrison    for (p = ref; *p; p++)
112215061Sgarrison       if (*p == '%')
112315061Sgarrison          if (*(p+1) == 'A') maxauths++;
112415061Sgarrison          else if (*(p+1) == 'E') maxeds++;
112515061Sgarrison    fprintf(ofd, ".[-\n");
112615903Srrh    fprintf(ofd, ".ds [F %s\n", refinfo[i].ri_cite);
112715903Srrh #ifndef INCORE
112815903Srrh    fseek(rfd, (long)refinfo[i].ri_pos, 0);
112915061Sgarrison    while (fgets(line, REFSIZE, rfd) != NULL) {
113015903Srrh #else INCORE
113115903Srrh    for (q = line, from = refinfo[i].ri_ref; *from; /*VOID*/) { /*} */
113215903Srrh 	if (*from == '\n'){
113315903Srrh 		*q++ = '\n';
113415903Srrh 		*q = 0;
113515903Srrh 		q = line;
113615903Srrh 		from++;
113715903Srrh 	} else {
113815903Srrh 		*q++ = *from++;
113915903Srrh 		continue;
114015903Srrh 	}
114115903Srrh #endif INCORE
114215903Srrh 	switch(line[0]){
114315903Srrh 	case 0:
114415903Srrh 		goto doneref;
114515903Srrh 	case '.':
114615903Srrh 		fprintf(ofd, "%s", line);
114715903Srrh 		break;
114815903Srrh 	case '%':
114915903Srrh 		switch(line[1]){
115015903Srrh 		case 'A':	numauths++;	break;
115115903Srrh 		case 'E':	numeds++;	break;
115215903Srrh 		}
115315903Srrh 		for (p = &line[2]; *p == ' '; p++) /*VOID*/;
115415903Srrh 		doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd);
115515903Srrh 	}
115615903Srrh    }
115715903Srrh    doneref:;
115815061Sgarrison    fprintf(ofd,".][\n");
115915061Sgarrison }
1160