xref: /csrg-svn/contrib/bib/src/bibargs.c (revision 23492)
113110Srrh #ifndef lint
2*23492Sgarrison static char sccsid[] = "@(#)bibargs.c	2.9	06/11/85";
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              */
3423485Sgarrison    int	max_klen     = 6;	/* max size of key			     */
3512910Sgarrison    int  sort         = false;   /* sort references ? (default no)            */
3612910Sgarrison    int  foot         = false;   /* footnoted references ? (default endnotes) */
3717246Srrh    int  doacite      = true;    /* place citations ? */
3812910Sgarrison    int  hyphen       = false;   /* hypenate contiguous references            */
3912910Sgarrison    int  ordcite      = true;    /* order multiple citations                  */
4012910Sgarrison    char sortstr[80]  = "1";     /* sorting template                          */
4112910Sgarrison    char trailstr[80] = "";      /* trailing characters to output             */
4212910Sgarrison    char pfile[120];             /* private file name                         */
4312910Sgarrison    int  personal = false;       /* personal file given ? (default no)        */
4412910Sgarrison    char citetemplate[80] = "1"; /* citation template                         */
4515903Srrh    struct wordinfo words[MAXDEFS];     /* defined words */
4615903Srrh    struct wordinfo *wordhash[HASHSIZE];
4715903Srrh    struct wordinfo *wordsearch();
4815903Srrh    int  wordtop = 0;           /* number of defined words         */
4912910Sgarrison 
5012910Sgarrison /* where output goes */
5112910Sgarrison    extern FILE *tfd;
5215061Sgarrison /* reference file information */
5315903Srrh    extern struct refinfo refinfo[];
5415061Sgarrison    extern char reffile[];
5515903Srrh #ifndef INCORE
5615061Sgarrison    extern FILE *rfd;
5715903Srrh #endif not INCORE
5815061Sgarrison    extern int numrefs;
5912910Sgarrison 
6012910Sgarrison /* doargs - read command argument line for both bib and listrefs
6112910Sgarrison             set switch values
6212910Sgarrison             call rdtext on file arguments, after dumping
6312910Sgarrison             default style file if no alternative style is given
6412910Sgarrison */
6512910Sgarrison    int doargs(argc, argv, defstyle)
6612910Sgarrison    int argc;
6712910Sgarrison    char **argv, defstyle[];
6812910Sgarrison {  int numfiles, i, style;
6912910Sgarrison    char *p, *q, *walloc();
7012910Sgarrison    FILE *fd;
7112910Sgarrison 
7212910Sgarrison    numfiles = 0;
7312910Sgarrison    style = true;
7417248Srrh    newbibdir(BMACLIB);
7512910Sgarrison 
7612910Sgarrison    for (i = 1; i < argc; i++)
7712910Sgarrison       if (argv[i][0] == '-')
7812910Sgarrison          switch(argv[i][1]) {
7917248Srrh 			case 'd':
8017248Srrh 				if (argv[i][2])
8117248Srrh 					p = &argv[i][2];
8217248Srrh 				else {  /* take next arg */
8317248Srrh 					i++;
8417248Srrh 					p = argv[i];
8517248Srrh 			}
8617248Srrh 			newbibdir(p);
8715061Sgarrison             case 'a':  for (p = &argv[i][2]; *p; p++)
8815061Sgarrison                           if (*p == 'a' || *p == 0)
8912961Sgarrison                              abbrev = true;
9012961Sgarrison                            else if (*p == 'x')
9112961Sgarrison                              capsmcap = true;
9212961Sgarrison                            else if (*p == 'r') {
9312961Sgarrison                              if (*(p+1))
9412961Sgarrison                                 numrev = atoi(p+1);
9512961Sgarrison                               else
9612961Sgarrison                                 numrev = 1000;
9712961Sgarrison                               break;
9812961Sgarrison                               }
9912910Sgarrison                        break;
10012910Sgarrison 
10112910Sgarrison             case 'c':  if (argv[i][2] == 0)
10215903Srrh                           error("citation string expected for 'c'");
10312910Sgarrison                        else
10412910Sgarrison                           for (p = citetemplate,q = &argv[i][2]; *p++ = *q++; );
10512910Sgarrison                        break;
10612910Sgarrison 
10712910Sgarrison             case 'e':  for (p = &argv[i][2]; *p; p++)
10812910Sgarrison                           if (*p == 'a')
10912910Sgarrison                              edabbrev = true;
11012910Sgarrison                            else if (*p == 'x')
11112910Sgarrison                              edcapsmcap = true;
11212910Sgarrison                            else if (*p == 'r') {
11312910Sgarrison                              if (*(p+1))
11412910Sgarrison                                 ednumrev = atoi(p+1);
11512910Sgarrison                               else
11612910Sgarrison                                 ednumrev = 1000;
11712910Sgarrison                               break;
11812910Sgarrison                               }
11912910Sgarrison                        break;
12012910Sgarrison 
12123485Sgarrison 	    case 'l':  if (argv[i][2]){
12223485Sgarrison                           max_klen  = atoi(&argv[i][2]);
12323485Sgarrison 			  if (max_klen > REFSIZE)
12423485Sgarrison 			      error("too long key size");
12523485Sgarrison 		       } else {
12623485Sgarrison 			  error("-l needs a numeric value");
12723485Sgarrison 		       }
12823485Sgarrison 		       break;
12923485Sgarrison 
13017246Srrh             case 'v':  doacite = false;
13117246Srrh 			/*FALLTHROUGH*/
13212910Sgarrison             case 'f':  foot = true;
13312910Sgarrison                        hyphen = false;
13412910Sgarrison                        break;
13512910Sgarrison 
13612910Sgarrison             case 'h':  hyphen = ordcite = true;
13712910Sgarrison                        break;
13812910Sgarrison 
13912910Sgarrison             case 'n':  for (p = &argv[i][2]; *p; p++)
14012910Sgarrison                           if (*p == 'a')
14112910Sgarrison                              abbrev = false;
14217246Srrh                           else if (*p == 'v')
14317246Srrh                              doacite = true;
14412910Sgarrison                           else if (*p == 'f')
14512910Sgarrison                              foot = false;
14612910Sgarrison                           else if (*p == 'h')
14712910Sgarrison                              hyphen = false;
14812910Sgarrison                           else if (*p == 'o')
14912910Sgarrison                              ordcite = false;
15012910Sgarrison                           else if (*p == 'r')
15112910Sgarrison                              numrev = 0;
15212910Sgarrison                           else if (*p == 's')
15312910Sgarrison                              sort = false;
15412910Sgarrison                           else if (*p == 'x')
15512910Sgarrison                              capsmcap = false;
15612910Sgarrison                        break;
15712910Sgarrison 
15812910Sgarrison             case 'o':  ordcite = true;
15912910Sgarrison                        break;
16012910Sgarrison 
16112910Sgarrison             case 'p':  if (argv[i][2])
16212910Sgarrison                           p = &argv[i][2];
16312910Sgarrison                        else {  /* take next arg */
16412910Sgarrison                           i++;
16512910Sgarrison                           p = argv[i];
16612910Sgarrison                           }
16712910Sgarrison                        strcpy(pfile, p);
16812910Sgarrison                        personal = true;
16912910Sgarrison                        break;
17012910Sgarrison 
17115061Sgarrison             case 'r':  if (argv[i][2] == 0)  /* this is now replaced by -ar */
17212910Sgarrison                           numrev = 1000;
17312910Sgarrison                        else
17412910Sgarrison                           numrev = atoi(&argv[i][2]);
17512910Sgarrison                        break;
17612910Sgarrison 
17712910Sgarrison             case 's':  sort = true;
17812910Sgarrison                        if (argv[i][2])
17912910Sgarrison                           for (p = sortstr,q = &argv[i][2]; *p++ = *q++; );
18012910Sgarrison                        break;
18112910Sgarrison 
18215061Sgarrison             case 't':  style = false;           /* fall through */
18315061Sgarrison             case 'i':  if (argv[i][2])
18412910Sgarrison                           p = &argv[i][2];
18512910Sgarrison                        else { /* take next arg */
18612910Sgarrison                           i++;
18712910Sgarrison                           p = argv[i];
18812910Sgarrison                           }
18912910Sgarrison                        incfile(p);
19012910Sgarrison                        break;
19112910Sgarrison 
19215061Sgarrison             case 'x':  capsmcap = true; /* this is now replaced by -ax */
19312910Sgarrison                        break;
19412910Sgarrison 
19512910Sgarrison             case 0:    if (style) {  /* no style command given, take default */
19612910Sgarrison                           style = false;
19712910Sgarrison                           incfile( defstyle );
19812910Sgarrison                           }
19915061Sgarrison                        strcpy(bibfname,"<stdin>");
20012910Sgarrison                        rdtext(stdin);
20112910Sgarrison                        numfiles++;
20212910Sgarrison                        break;
20312910Sgarrison 
20412910Sgarrison             default:   fputs(argv[i], stderr);
20515903Srrh                        error("'%c' invalid switch", argv[i][1]);
20612910Sgarrison             }
20712910Sgarrison       else { /* file name */
20812910Sgarrison          numfiles++;
20912910Sgarrison          if (style) {
21012910Sgarrison             style = false;
21112910Sgarrison             incfile( defstyle );
21212910Sgarrison             }
21312910Sgarrison          fd = fopen(argv[i], "r");
21412910Sgarrison          if (fd == NULL) {
21515903Srrh             error("can't open file %s", argv[i]);
21612910Sgarrison             }
21712910Sgarrison          else {
21815061Sgarrison             strcpy(bibfname, argv[i]);
21912910Sgarrison             rdtext(fd);
22012910Sgarrison             fclose(fd);
22112910Sgarrison             }
22212910Sgarrison          }
22312910Sgarrison 
22412910Sgarrison    if (style) incfile( defstyle );
22512910Sgarrison    return(numfiles);
22612910Sgarrison 
22712910Sgarrison }
22812910Sgarrison 
22917248Srrh newbibdir(name)
23017248Srrh 	char *name;
23117248Srrh {
23217248Srrh 	strreplace(COMFILE, BMACLIB, name);
23317248Srrh 	strreplace(DEFSTYLE, BMACLIB, name);
23417248Srrh 	strcpy(BMACLIB, name);
23517248Srrh 	wordstuff("BMACLIB", BMACLIB);
23617248Srrh 	fprintf(tfd, ".ds l] %s\n", BMACLIB);
23717248Srrh }
23817248Srrh 
23912910Sgarrison /* incfile - read in an included file  */
24012910Sgarrison incfile(np)
24112910Sgarrison    char *np;
24212910Sgarrison {  char name[120];
24312910Sgarrison    FILE *fd;
24415061Sgarrison    char *p, line[LINELENGTH], dline[LINELENGTH], word[80], *tfgets();
24516244Srrh    int  i, getwrd();
24612910Sgarrison 
24715061Sgarrison    strcpy(bibfname, np);
24812910Sgarrison    fd = fopen(np, "r");
24912910Sgarrison    if (fd == NULL && *np != '/') {
25012910Sgarrison       strcpy(name, "bib.");
25112910Sgarrison       strcat(name, np);
25215061Sgarrison       strcpy(bibfname, name);
25312910Sgarrison       fd = fopen(name, "r");
25412910Sgarrison       }
25512910Sgarrison    if (fd == NULL && *np != '/') {
25612910Sgarrison       strcpy(name,BMACLIB);
25712910Sgarrison       strcat(name, "/bib.");
25812910Sgarrison       strcat(name, np);
25915061Sgarrison       strcpy(bibfname, name);
26012910Sgarrison       fd = fopen(name, "r");
26112910Sgarrison       }
26212910Sgarrison    if (fd == NULL) {
26315061Sgarrison       bibwarning("%s: can't open", np);
26415061Sgarrison       exit(1);
26512910Sgarrison       }
26612910Sgarrison 
26715061Sgarrison    /* now go off and process file */
26815061Sgarrison    biblineno = 1;
26915061Sgarrison    while (tfgets(line, LINELENGTH, fd) != NULL) {
27015061Sgarrison       biblineno++;
27112910Sgarrison       switch(line[0]) {
27212910Sgarrison 
27312910Sgarrison          case '#': break;
27412910Sgarrison 
27512961Sgarrison          case 'A': for (p = &line[1]; *p; p++)
27615061Sgarrison                       if (*p == 'A' || *p == '\0')
27712961Sgarrison                          abbrev = true;
27812961Sgarrison                       else if (*p == 'X')
27912961Sgarrison                          capsmcap = true;
28012961Sgarrison                       else if (*p == 'R') {
28112961Sgarrison                          if (*(p+1))
28212961Sgarrison                             numrev = atoi(p+1);
28312961Sgarrison                          else
28412961Sgarrison                             numrev = 1000;
28512961Sgarrison                          break;
28612961Sgarrison                          }
28712910Sgarrison                    break;
28812910Sgarrison 
28912910Sgarrison          case 'C': for (p = &line[1]; *p == ' '; p++) ;
29012910Sgarrison                    strcpy(citetemplate, p);
29112910Sgarrison                    break;
29212910Sgarrison 
29312910Sgarrison          case 'D': if ((i = getwrd(line, 1, word)) == 0)
29412910Sgarrison                       error("word expected in definition");
295*23492Sgarrison 		   if (wordsearch(word)) { /* already there-toss rest of def.*/
296*23492Sgarrison 			while(line[strlen(line)-1] == '\\' ) {
297*23492Sgarrison                             if (tfgets(line, LINELENGTH, fd) == NULL) break;
298*23492Sgarrison 			}
29915903Srrh 			break;
300*23492Sgarrison 		   }
30112910Sgarrison                    for (p = &line[i]; *p == ' '; p++) ;
30212910Sgarrison                    for (strcpy(dline, p); dline[strlen(dline)-1] == '\\'; ){
30312910Sgarrison                        dline[strlen(dline)-1] = '\n';
30415061Sgarrison                        if (tfgets(line, LINELENGTH, fd) == NULL) break;
30512910Sgarrison                        strcat(dline, line);
30612910Sgarrison                        }
30715903Srrh 		   wordstuff(word, dline);
30812910Sgarrison                    break;
30912910Sgarrison 
31012910Sgarrison          case 'E': for (p = &line[1]; *p; p++)
31112910Sgarrison                       if (*p == 'A')
31212910Sgarrison                          edabbrev = true;
31312910Sgarrison                       else if (*p == 'X')
31412910Sgarrison                          edcapsmcap = true;
31512910Sgarrison                       else if (*p == 'R') {
31612910Sgarrison                          if (*(p+1))
31712910Sgarrison                             ednumrev = atoi(p+1);
31812910Sgarrison                          else
31912910Sgarrison                             ednumrev = 1000;
32012910Sgarrison                          break;
32112910Sgarrison                          }
32212910Sgarrison                    break;
32312910Sgarrison 
32412910Sgarrison          case 'F': foot = true;
32512910Sgarrison                    hyphen = false;
32612910Sgarrison                    break;
32712910Sgarrison 
32812910Sgarrison          case 'I': for (p = &line[1]; *p == ' '; p++);
32912910Sgarrison                    expand(p);
33012910Sgarrison                    incfile(p);
33112910Sgarrison                    break;
33212910Sgarrison 
33312910Sgarrison          case 'H': hyphen = ordcite = true;
33412910Sgarrison                    break;
33512910Sgarrison 
33612910Sgarrison          case 'O': ordcite = true;
33712910Sgarrison                    break;
33812910Sgarrison 
33915061Sgarrison          case 'R': if (line[1] == 0)  /* this is now replaced by AR */
34012910Sgarrison                       numrev = 1000;
34112910Sgarrison                    else
34212910Sgarrison                       numrev = atoi(&line[1]);
34312910Sgarrison                    break;
34412910Sgarrison 
34512910Sgarrison          case 'S': sort = true;
34612910Sgarrison                    for (p = &line[1]; *p == ' '; p++) ;
34712910Sgarrison                    strcpy(sortstr, p);
34812910Sgarrison                    break;
34912910Sgarrison 
35012910Sgarrison          case 'T': for (p = &line[1]; *p == ' '; p++) ;
35112910Sgarrison                    strcpy(trailstr, p);
35212910Sgarrison                    break;
35312910Sgarrison 
35415061Sgarrison          case 'X': capsmcap = true;     /* this is now replace by AX */
35512910Sgarrison                    break;
35612910Sgarrison 
35712910Sgarrison          default:  fprintf(tfd,"%s\n",line);
35815061Sgarrison                    while (fgets(line, LINELENGTH, fd) != NULL)
35912910Sgarrison                       fputs(line, tfd);
36012910Sgarrison                    return;
36112910Sgarrison          }
36215061Sgarrison 
36315061Sgarrison    }
36415061Sgarrison    /* close up */
36515061Sgarrison    fclose(fd);
36612910Sgarrison }
36712910Sgarrison 
36815061Sgarrison /* bibwarning - print out a warning message */
36915903Srrh   /*VARARGS1*/
37015903Srrh   bibwarning(msg, a1, a2)
37115903Srrh   char *msg;
37215061Sgarrison {
37315061Sgarrison   fprintf(stderr,"`%s', line %d: ", bibfname, biblineno);
37415903Srrh   fprintf(stderr, msg, a1, a2);
37517248Srrh   fprintf(stderr, "\n");
37615061Sgarrison }
37715061Sgarrison 
37815061Sgarrison /* error - report unrecoverable error message */
37915903Srrh   /*VARARGS1*/
38015903Srrh   error(str, a1, a2)
38115903Srrh   char *str;
38215061Sgarrison {
38315903Srrh   bibwarning(str, a1, a2);
38415903Srrh   /*
38515903Srrh    *	clean up temp files and exit
38615903Srrh    */
38715903Srrh   cleanup(1);
38815061Sgarrison }
38915061Sgarrison 
39015903Srrh #ifndef INCORE
39115061Sgarrison #ifdef READWRITE
39215061Sgarrison /*
39315061Sgarrison ** fixrfd( mode ) -- re-opens the rfd file to be read or write,
39415061Sgarrison **      depending on the mode.  Uses a static int to save the current mode
39515061Sgarrison **      and avoid unnecessary re-openings.
39615061Sgarrison */
39715061Sgarrison fixrfd( mode )
39815061Sgarrison register int mode;
39915061Sgarrison {
40015061Sgarrison 	static int cur_mode = WRITE;    /* rfd open for writing initially */
40115061Sgarrison 
40215061Sgarrison 	if (mode != cur_mode)
40315061Sgarrison 	{
40415061Sgarrison 		rfd = freopen(reffile, ((mode == READ)? "r" : "a"), rfd);
40515061Sgarrison 		cur_mode = mode;
40615061Sgarrison 		if (rfd == NULL)
40715903Srrh 		      error("Hell!  Couldn't re-open reference file %s",
40815903Srrh 			reffile);
40915061Sgarrison 	}
41015061Sgarrison }
41115061Sgarrison #endif
41215903Srrh #endif not INCORE
41315061Sgarrison 
41415061Sgarrison 
41515061Sgarrison /* tfgets - fgets which trims off newline */
41615061Sgarrison    char *tfgets(line, n, ptr)
41715061Sgarrison    char line[];
41815061Sgarrison    int  n;
41915061Sgarrison    FILE *ptr;
42015903Srrh {  reg char *p;
42115061Sgarrison 
42215061Sgarrison    p = fgets(line, n, ptr);
42315061Sgarrison    if (p == NULL)
42415061Sgarrison       return(NULL);
42515061Sgarrison    else
42615061Sgarrison       for (p = line; *p; p++)
42715061Sgarrison          if (*p == '\n')
42815061Sgarrison             *p = 0;
42915061Sgarrison    return(line);
43015061Sgarrison }
43115061Sgarrison 
43215061Sgarrison /* getwrd - place next word from in[i] into out */
43315061Sgarrison int getwrd(in, i, out)
43415903Srrh    reg char in[], out[];
43515903Srrh    reg int i;
43615061Sgarrison {  int j;
43715061Sgarrison 
43815061Sgarrison    j = 0;
43915061Sgarrison    while (in[i] == ' ' || in[i] == '\n' || in[i] == '\t')
44015061Sgarrison       i++;
44115061Sgarrison    if (in[i])
44215061Sgarrison       while (in[i] && in[i] != ' ' && in[i] != '\t' && in[i] != '\n')
44315061Sgarrison          out[j++] = in[i++];
44415061Sgarrison    else
44515061Sgarrison       i = 0;    /* signals end of in[i..]   */
44615061Sgarrison    out[j] = 0;
44715061Sgarrison    return (i);
44815061Sgarrison }
44915061Sgarrison 
45015061Sgarrison /* walloc - allocate enough space for a word */
45115061Sgarrison char *walloc(word)
45215061Sgarrison    char *word;
45315061Sgarrison {  char *i, *malloc();
45415061Sgarrison    i = malloc(1 + strlen(word));
45515061Sgarrison    if (i == NULL)
45615061Sgarrison       error("out of storage");
45715061Sgarrison    strcpy(i, word);
45815061Sgarrison    return(i);
45915061Sgarrison }
46015061Sgarrison 
46112910Sgarrison /* isword - see if character is legit word char */
46212910Sgarrison int iswordc(c)
46312910Sgarrison char c;
46412910Sgarrison {
46512910Sgarrison    if (isalnum(c) || c == '&' || c == '_')
46612910Sgarrison       return(true);
46712910Sgarrison    return(false);
46812910Sgarrison }
46912910Sgarrison    expand(line)
47012910Sgarrison    char *line;
47115903Srrh {  char line2[REFSIZE], word[LINELENGTH];
47215903Srrh    reg	struct wordinfo *wp;
47315903Srrh    reg	char *p, *q, *w;
47412910Sgarrison 
47515903Srrh 	q = line2;
47615903Srrh 	for (p = line; *p; /*VOID*/){
47715903Srrh 		if (isalnum(*p)) {
47815903Srrh 			for (w = word; *p && iswordc(*p); ) *w++ = *p++;
47915903Srrh 			*w = 0;
48015903Srrh 			if (wp = wordsearch(word)){
48115903Srrh 				strcpy(word, wp->wi_def);
48215903Srrh 				expand(word);
48315903Srrh 			}
48415903Srrh 			strcpy(q, word);
48515903Srrh 			q += strlen(q);
48615903Srrh 		} else {
48715903Srrh 			*q++ = *p++;
48815903Srrh 		}
48915903Srrh 	}
49015903Srrh 	*q = 0;
49115903Srrh 	strcpy(line, line2);
49212910Sgarrison }
49312910Sgarrison 
49415903Srrh /* wordstuff- save a word and its definition, building a hash table */
49515903Srrh    wordstuff(word, def)
49615903Srrh    char *word, *def;
49715903Srrh {
49815903Srrh    int i;
49915903Srrh    if (wordtop >= MAXDEFS)
50015903Srrh 	error("too many definitions, max of %d", MAXDEFS);
50115903Srrh    words[wordtop].wi_length = strlen(word);
50215903Srrh    words[wordtop].wi_word = word ? walloc(word) : 0;
50315903Srrh    words[wordtop].wi_def = def ? walloc(def) : 0;
50415903Srrh    i = strhash(word);
50515903Srrh    words[wordtop].wi_hp = wordhash[i];
50615903Srrh    wordhash[i] = &words[wordtop];
50715903Srrh    wordtop++;
50815903Srrh }
50915903Srrh    struct wordinfo *wordsearch(word)
51015903Srrh    char *word;
51115903Srrh {
51215903Srrh    reg int lg;
51315903Srrh    reg struct wordinfo *wp;
51415903Srrh    lg = strlen(word);
51515903Srrh    for (wp = wordhash[strhash(word)]; wp; wp = wp->wi_hp){
51615903Srrh 	if (wp->wi_length == lg && (strcmp(wp->wi_word, word) == 0)){
51715903Srrh 		return(wp);
51815903Srrh 	}
51915903Srrh    }
52015903Srrh    return(0);
52115903Srrh }
52215903Srrh 
52315903Srrh    int strhash(str)
52415903Srrh    reg char *str;
52515903Srrh {
52615903Srrh    reg int value = 0;
52715903Srrh    for (value = 0; *str; value <<= 2, value += *str++)/*VOID*/;
52815903Srrh    value %= HASHSIZE;
52915903Srrh    if (value < 0)
53015903Srrh 	value += HASHSIZE;
53115903Srrh    return(value);
53215903Srrh }
53315903Srrh 
53415061Sgarrison /* rdref - read text for an already cited reference */
53515903Srrh    rdref(p, ref)
53615903Srrh    struct refinfo *p;
53715061Sgarrison    char ref[REFSIZE];
53815061Sgarrison {
53915061Sgarrison    ref[0] = 0;
54015903Srrh #ifndef INCORE
54115061Sgarrison #ifdef READWRITE
54215061Sgarrison    fixrfd( READ );                      /* fix access mode of rfd, if nec. */
54315061Sgarrison #endif
54415903Srrh    fseek(rfd, p->ri_pos, 0);
54515903Srrh    fread(ref, p->ri_length, 1, rfd);
54615903Srrh #else INCORE
54715903Srrh    strcpy(ref, p->ri_ref);
54815903Srrh #endif INCORE
54915061Sgarrison }
55015061Sgarrison 
55115903Srrh /* wrref - write text for a new reference */
55215903Srrh    wrref(p, ref)
55315903Srrh    struct refinfo *p;
55415903Srrh    char ref[REFSIZE];
55515903Srrh {
55615903Srrh #ifndef INCORE
55715903Srrh #ifdef READWRITE
55815903Srrh     fixrfd( WRITE );                 /* fix access mode of rfd, if nec. */
55915903Srrh #else
56015903Srrh     fseek(rfd, p->ri_pos, 0);        /* go to end of rfd */
56115903Srrh #endif
56215903Srrh     fwrite(ref, p->ri_length, 1, rfd);
56315903Srrh #else INCORE
56415903Srrh    p->ri_ref = walloc(ref);
56515903Srrh #endif INCORE
56615903Srrh }
56715903Srrh 
56812910Sgarrison /* breakname - break a name into first and last name */
56912910Sgarrison    breakname(line, first, last)
57012910Sgarrison    char line[], first[], last[];
57115903Srrh {  reg char *t, *f, *q, *r, *p;
57212910Sgarrison 
57312910Sgarrison    for (t = line; *t != '\n'; t++);
57412910Sgarrison    for (t--; isspace(*t); t--);
57512910Sgarrison 
57612910Sgarrison    /* now strip off last name */
57712910Sgarrison    for (q = t; isspace(*q) == 0 || ((*q == ' ') & (*(q-1) == '\\')); q--)
57812910Sgarrison       if (q == line)
57912910Sgarrison          break;
58012910Sgarrison    f = q;
58115061Sgarrison    if (q != line) {
58212910Sgarrison       q++;
58315061Sgarrison       for (; isspace(*f); f--);
58415061Sgarrison       f++;
58515061Sgarrison       }
58612910Sgarrison 
58712910Sgarrison    /* first name is start to f, last name is q to t */
58812910Sgarrison 
58915061Sgarrison    for (r = first, p = line; p != f; )
59012910Sgarrison       *r++ = *p++;
59112910Sgarrison    *r = 0;
59212910Sgarrison    for (r = last, p = q, t++; q != t; )
59312910Sgarrison       *r++ = *q++;
59412910Sgarrison    *r = 0;
59515061Sgarrison 
59612910Sgarrison }
59712910Sgarrison 
59812910Sgarrison /* match - see if string1 is a substring of string2 (case independent)*/
59912910Sgarrison    int match(str1, str2)
60015903Srrh    reg char str1[], str2[];
60115903Srrh {  reg int  j, i;
60212910Sgarrison    char a, b;
60312910Sgarrison 
60412910Sgarrison    for (i = 0; str2[i]; i++) {
60512910Sgarrison       for (j = 0; str1[j]; j++) {
60612910Sgarrison          if (isupper(a = str2[i+j]))
60712910Sgarrison             a = (a - 'A') + 'a';
60812910Sgarrison          if (isupper(b = str1[j]))
60912910Sgarrison             b = (b - 'A') + 'a';
61012910Sgarrison          if (a != b)
61112910Sgarrison             break;
61212910Sgarrison          }
61312910Sgarrison       if (str1[j] == 0)
61412910Sgarrison          return(true);
61512910Sgarrison       }
61612910Sgarrison    return(false);
61712910Sgarrison }
61812910Sgarrison 
61912910Sgarrison /* scopy - append a copy of one string to another */
62012910Sgarrison    char *scopy(p, q)
62115903Srrh    reg char *p, *q;
62212910Sgarrison {
62312910Sgarrison    while (*p++ = *q++)
62412910Sgarrison       ;
62512910Sgarrison    return(--p);
62612910Sgarrison }
62712910Sgarrison 
62815061Sgarrison /* rcomp - reference comparison routine for qsort utility */
62915061Sgarrison    int rcomp(ap, bp)
63015903Srrh    struct refinfo *ap, *bp;
63115061Sgarrison {  char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD];
63215903Srrh    reg	char *p, *q;
63315903Srrh    char *getfield();
63415061Sgarrison    int  neg, res;
63515061Sgarrison    int  fields_found;
63615061Sgarrison 
63715903Srrh    rdref(ap, ref1);
63815903Srrh    rdref(bp, ref2);
63915061Sgarrison    for (p = sortstr; *p; p = q) {
64015061Sgarrison       if (*p == '-') {
64115061Sgarrison          p++;
64215061Sgarrison          neg = true;
64315061Sgarrison          }
64415061Sgarrison       else
64515061Sgarrison          neg = false;
64615061Sgarrison       q = getfield(p, field1, ref1);
64715061Sgarrison       fields_found = true;
64815061Sgarrison       if (q == 0) {
64915061Sgarrison 	 res = 1;
65015061Sgarrison 	 fields_found = false;
65115061Sgarrison       } else if (strcmp (field1, "") == 0) {	/* field not found */
65215061Sgarrison          if (*p == 'A') {
65315061Sgarrison             getfield("F", field1, ref1);
65415061Sgarrison 	    if (strcmp (field1, "") == 0) {
65515061Sgarrison                getfield("I", field1, ref1);
65615061Sgarrison 	       if (strcmp (field1, "") == 0) {
65715061Sgarrison 	          res = 1;
65815061Sgarrison 		  fields_found = false;
65915061Sgarrison 	       }
66015061Sgarrison 	    }
66115061Sgarrison 	 } else {
66215061Sgarrison 	    res = 1;
66315061Sgarrison 	    fields_found = false;
66415061Sgarrison 	 }
66515061Sgarrison       }
66615061Sgarrison 
66715061Sgarrison       if (getfield(p, field2, ref2) == 0) {
66815061Sgarrison 	 res = -1;
66915061Sgarrison 	 fields_found = false;
67015061Sgarrison       } else if (strcmp (field2, "") == 0) {	/* field not found */
67115061Sgarrison          if (*p == 'A') {
67215061Sgarrison             getfield("F", field2, ref2);
67315061Sgarrison 	    if (strcmp (field2, "") == 0) {
67415061Sgarrison                getfield("I", field2, ref2);
67515061Sgarrison 	       if (strcmp (field2, "") == 0) {
67615061Sgarrison 	          res = -1;
67715061Sgarrison 		  fields_found = false;
67815061Sgarrison 	       }
67915061Sgarrison 	    }
68015061Sgarrison 	 } else {
68115061Sgarrison 	    res = -1;
68215061Sgarrison 	    fields_found = false;
68315061Sgarrison 	 }
68415061Sgarrison       }
68515061Sgarrison       if (fields_found) {
68615061Sgarrison          if (*p == 'A') {
68715061Sgarrison             if (isupper(field1[0]))
68815061Sgarrison                field1[0] -= 'A' - 'a';
68915061Sgarrison             if (isupper(field2[0]))
69015061Sgarrison                field2[0] -= 'A' - 'a';
69115061Sgarrison             }
69215061Sgarrison          res = strcmp(field1, field2);
69315061Sgarrison          }
69415061Sgarrison       if (neg)
69515061Sgarrison          res = - res;
69615061Sgarrison       if (res != 0)
69715061Sgarrison          break;
69815061Sgarrison       }
69915061Sgarrison    if (res == 0)
70015061Sgarrison       if (ap < bp)
70115061Sgarrison          res = -1;
70215061Sgarrison       else
70315061Sgarrison          res = 1;
70415061Sgarrison    return(res);
70515061Sgarrison }
70615061Sgarrison 
70716244Srrh /* makecites - make standard citation strings, using citetemplate currently in effect */
70815903Srrh    makecites()
70915061Sgarrison {  char ref[REFSIZE], tempcite[100], *malloc();
71015903Srrh    reg int  i;
71115061Sgarrison 
71215903Srrh    for (i = 0; i < numrefs; i++) {
71315903Srrh       rdref(&refinfo[i], ref);
71415061Sgarrison       bldcite(tempcite, i, ref);
71516244Srrh       refinfo[i].ri_cite = malloc(2 + strlen(tempcite));
71615903Srrh       if (refinfo[i].ri_cite == NULL)
71715061Sgarrison          error("out of storage");
71815903Srrh       strcpy(refinfo[i].ri_cite, tempcite);
71915061Sgarrison       }
72015061Sgarrison }
72115061Sgarrison 
72215061Sgarrison /* bldcite - build a single citation string */
72315061Sgarrison    bldcite(cp, i, ref)
72415061Sgarrison    char *cp, ref[];
72515061Sgarrison    int  i;
72615903Srrh {  reg char *p, *q, *fp;
72715903Srrh    char c;
72815903Srrh    char field[REFSIZE];
72923485Sgarrison    char *getfield(), *aabet(), *aabetlast(), *fullaabet(), *astro();
73015061Sgarrison 
73115061Sgarrison    getfield("F", field, ref);
73215061Sgarrison    if (field[0] != 0)
73315061Sgarrison       for (p = field; *p; p++)
73415061Sgarrison          *cp++ = *p;
73515061Sgarrison    else {
73615061Sgarrison       p = citetemplate;
73715061Sgarrison       field[0] = 0;
73815061Sgarrison       while (c = *p++) {
73915061Sgarrison          if (isalpha(c)) {                      /* field name   */
74015061Sgarrison             q = getfield(p-1, field, ref);
74115061Sgarrison             if (q != 0) {
74215061Sgarrison                p = q;
74315061Sgarrison                for (fp = field; *fp; )
74415061Sgarrison                   *cp++ = *fp++;
74515061Sgarrison                }
74615061Sgarrison             }
74715061Sgarrison          else if (c == '1') {                   /* numeric  order */
74815061Sgarrison             sprintf(field,"%d",1 + i);
74915061Sgarrison             for (fp = field; *fp; )
75015061Sgarrison                *cp++ = *fp++;
75115061Sgarrison             }
75215061Sgarrison          else if (c == '2')                     /* alternate alphabetic */
75315061Sgarrison             cp = aabet(cp, ref);
75415061Sgarrison          else if (c == '3')                     /* Astrophysical Journal style*/
75515061Sgarrison             cp = astro(cp, ref);
75623485Sgarrison 	 else if (c == '8')			/* Full alphabetic */
75723485Sgarrison 	    cp = fullaabet(cp, ref);
75815890Srrh          else if (c == '9')                     /* Last name of Senior Author*/
75915890Srrh             cp = aabetlast(cp, ref);
76017246Srrh 	 else if (c == '0') {			/* print nothing */
76117246Srrh             for (fp = field; *fp; )
76217246Srrh                *cp++ = *fp++;
76317246Srrh             }
76415061Sgarrison /*       else if (c == '4')          here is how to add new styles */
76515061Sgarrison          else if (c == '{') {                   /* other information   */
76615061Sgarrison             while (*p != '}')
76715061Sgarrison                if (*p == 0)
76815061Sgarrison                   error("unexpected end of citation template");
76915061Sgarrison                else
77015061Sgarrison                   *cp++ = *p++;
77115061Sgarrison             p++;
77215061Sgarrison             }
77315061Sgarrison          else if (c == '<') {
77415061Sgarrison             while (*p != '>') {
77515061Sgarrison                if (*p == 0)
77615061Sgarrison                   error("unexpected end of citation template");
77715061Sgarrison                else
77815061Sgarrison                   *cp++ = *p++;
77915061Sgarrison                }
78015061Sgarrison             p++;
78115061Sgarrison             }
78215061Sgarrison          else if (c != '@')
78315061Sgarrison             *cp++ = c;
78415061Sgarrison          }
78515061Sgarrison       }
78615061Sgarrison    *cp++ = 0;
78715061Sgarrison }
78815061Sgarrison 
78915061Sgarrison /* alternate alphabetic citation style -
79015061Sgarrison         if 1 author - first three letters of last name
79115061Sgarrison         if 2 authors - first two letters of first, followed by first letter of
79215061Sgarrison                                 seond
79315061Sgarrison         if 3 or more authors - first letter of first three authors */
79415061Sgarrison    char *aabet(cp, ref)
79515061Sgarrison    char *cp, ref[];
79615903Srrh {  char field[REFSIZE], temp[100];
79715903Srrh    reg char *np, *fp;
79815061Sgarrison    int j, getname();
79915061Sgarrison 
80015061Sgarrison    if (getname(1, field, temp, ref)) {
80115061Sgarrison       np = cp;
80215061Sgarrison       fp = field;
80315061Sgarrison       for (j = 1; j <= 3; j++)
80415061Sgarrison          if (*fp != 0)
80515061Sgarrison             *cp++ = *fp++;
80615061Sgarrison       if (getname(2, field, temp, ref))
80715061Sgarrison          np[2] = field[0];
80815061Sgarrison       if (getname(3, field, temp, ref)) {
80915061Sgarrison          np[1] = np[2];
81015061Sgarrison          np[2] = field[0];
81115061Sgarrison          }
81215061Sgarrison       }
81315061Sgarrison return(cp);
81415061Sgarrison }
81515061Sgarrison 
81615890Srrh /* alternate alphabetic citation style -
81723485Sgarrison 	first two characters of last names of all authors
81823485Sgarrison 	up to max_klen characters.
81923485Sgarrison */
82023485Sgarrison    char *fullaabet(cp, ref)
82123485Sgarrison    char *cp, ref[];
82223485Sgarrison {  char field[REFSIZE], temp[100];
82323485Sgarrison    reg char	*fp;
82423485Sgarrison    char	*lastcp;
82523485Sgarrison    int getname();
82623485Sgarrison    int i;
82723485Sgarrison 
82823485Sgarrison    lastcp = cp + max_klen;
82923485Sgarrison    for (i= 1; getname(i, field, temp, ref); i++) {
83023485Sgarrison       for (fp = field; *fp && (fp < &(field[3])); )
83123485Sgarrison 	 if (cp > lastcp)
83223485Sgarrison 	     break;
83323485Sgarrison          else if (isalpha(*fp))
83423485Sgarrison 	     *cp++ = *fp++;
83523485Sgarrison 	 else
83623485Sgarrison 	     fp++;
83723485Sgarrison    }
83823485Sgarrison    return(cp);
83923485Sgarrison }
84023485Sgarrison 
84123485Sgarrison 
84223485Sgarrison /* alternate alphabetic citation style -
84315890Srrh 	entire last name of senior author
84415890Srrh */
84515890Srrh    char *aabetlast(cp, ref)
84615890Srrh    char *cp, ref[];
84715890Srrh {  char field[REFSIZE], temp[100];
84815903Srrh    reg char	*fp;
84915890Srrh    int getname();
85015890Srrh 
85115890Srrh    if (getname(1, field, temp, ref)) {
85215890Srrh       for (fp = field; *fp; )
85315890Srrh          *cp++ = *fp++;
85415890Srrh    }
85515890Srrh    return(cp);
85615890Srrh }
85715890Srrh 
85815061Sgarrison /* Astrophysical Journal style
85915061Sgarrison         if 1 author - last name date
86015061Sgarrison         if 2 authors - last name and last name date
86115061Sgarrison         if 3 authors - last name, last name and last name date
86215061Sgarrison         if 4 or more authors - last name et al. date */
86315061Sgarrison    char *astro(cp, ref)
86415061Sgarrison    char *cp, ref[];
86515903Srrh {  char name1[100], name2[100], name3[100], temp[100];
86615903Srrh    reg char *fp;
86715061Sgarrison    int getname();
86815061Sgarrison 
86915061Sgarrison    if (getname(1, name1, temp, ref)) {
87015061Sgarrison       for (fp = name1; *fp; )
87115061Sgarrison          *cp++ = *fp++;
87215061Sgarrison       if (getname(4, name3, temp, ref)) {
87315061Sgarrison          for (fp = " et al."; *fp; )
87415061Sgarrison             *cp++ = *fp++;
87515061Sgarrison          }
87615061Sgarrison       else if (getname(2, name2, temp, ref)) {
87715061Sgarrison          if (getname(3, name3, temp, ref)) {
87815061Sgarrison             for (fp = "\\*(c]"; *fp; )
87915061Sgarrison                *cp++ = *fp++;
88015061Sgarrison             for (fp = name2; *fp; )
88115061Sgarrison                *cp++ = *fp++;
88215061Sgarrison             for (fp = "\\*(m]"; *fp; )
88315061Sgarrison                *cp++ = *fp++;
88415061Sgarrison             for (fp = name3; *fp; )
88515061Sgarrison                *cp++ = *fp++;
88615061Sgarrison             }
88715061Sgarrison          else {
88815061Sgarrison             for (fp = "\\*(n]"; *fp; )
88915061Sgarrison                *cp++ = *fp++;
89015061Sgarrison             for (fp = name2; *fp; )
89115061Sgarrison                *cp++ = *fp++;
89215061Sgarrison             }
89315061Sgarrison          }
89415061Sgarrison     }
89515061Sgarrison return(cp);
89615061Sgarrison }
89715061Sgarrison 
89815061Sgarrison /* getfield - get a single field from reference */
89915061Sgarrison    char *getfield(ptr, field, ref)
90015061Sgarrison    char *ptr, field[], ref[];
90115903Srrh {  reg	char *p, *q;
90215903Srrh    char	temp[100];
90315061Sgarrison    int  n, len, i, getname();
90415061Sgarrison 
90515061Sgarrison    field[0] = 0;
90615061Sgarrison    if (*ptr == 'A')
90715061Sgarrison       getname(1, field, temp, ref);
90815061Sgarrison    else
90915061Sgarrison       for (p = ref; *p; p++)
91015061Sgarrison          if (*p == '%' && *(p+1) == *ptr) {
91115061Sgarrison             for (p = p + 2; *p == ' '; p++)
91215061Sgarrison                ;
91315061Sgarrison             for (q = field; (*p != '\n') && (*p != '\0'); )
91415061Sgarrison                *q++ = *p++;
91515061Sgarrison             *q = 0;
91615061Sgarrison             break;
91715061Sgarrison             }
91815061Sgarrison    n = 0;
91915061Sgarrison    len = strlen(field);
92015061Sgarrison    if (*++ptr == '-') {
92115061Sgarrison       for (ptr++; isdigit(*ptr); ptr++)
92215061Sgarrison          n = 10 * n + (*ptr - '0');
92315061Sgarrison       if (n > len)
92415061Sgarrison          n = 0;
92515061Sgarrison       else
92615061Sgarrison          n = len - n;
92715061Sgarrison       for (i = 0; field[i] = field[i+n]; i++)
92815061Sgarrison          ;
92915061Sgarrison       }
93015061Sgarrison    else if (isdigit(*ptr)) {
93115061Sgarrison       for (; isdigit(*ptr); ptr++)
93215061Sgarrison          n = 10 * n + (*ptr - '0');
93315061Sgarrison       if (n > len)
93415061Sgarrison          n = len;
93515061Sgarrison       field[n] = 0;
93615061Sgarrison       }
93715061Sgarrison 
93815061Sgarrison    if (*ptr == 'u') {
93915061Sgarrison       ptr++;
94015061Sgarrison       for (p = field; *p; p++)
94115061Sgarrison          if (islower(*p))
94215061Sgarrison             *p = (*p - 'a') + 'A';
94315061Sgarrison       }
94415061Sgarrison    else if (*ptr == 'l') {
94515061Sgarrison       ptr++;
94615061Sgarrison       for (p = field; *p; p++)
94715061Sgarrison          if (isupper(*p))
94815061Sgarrison             *p = (*p - 'A') + 'a';
94915061Sgarrison       }
95015061Sgarrison    return(ptr);
95115061Sgarrison }
95215061Sgarrison 
95315061Sgarrison /* getname - get the nth name field from reference, breaking into
95415061Sgarrison              first and last names */
95515061Sgarrison    int getname(n, last, first, ref)
95615061Sgarrison    int  n;
95715061Sgarrison    char last[], first[], ref[];
95815903Srrh {  reg char *p;
95915061Sgarrison    int  m;
96015061Sgarrison 
96115061Sgarrison    m = n;
96215061Sgarrison    for (p = ref; *p; p++)
96315061Sgarrison       if (*p == '%' & *(p+1) == 'A') {
96415061Sgarrison          n--;
96515061Sgarrison          if (n == 0) {
96615061Sgarrison             for (p = p + 2; *p == ' '; p++) ;
96715061Sgarrison             breakname(p, first, last) ;
96815061Sgarrison             return(true);
96915061Sgarrison             }
97015061Sgarrison          }
97115061Sgarrison 
97215061Sgarrison    if (n == m)          /* no authors, try editors */
97315061Sgarrison       for (p = ref; *p; p++)
97415061Sgarrison          if (*p == '%' & *(p+1) == 'E') {
97515061Sgarrison             n--;
97615061Sgarrison             if (n == 0) {
97715061Sgarrison                for (p = p + 2; *p == ' '; p++) ;
97815061Sgarrison                breakname(p, first, last) ;
97915061Sgarrison                return(true);
98015061Sgarrison                }
98115061Sgarrison             }
98215061Sgarrison 
98315061Sgarrison    if (n == m) {        /* no editors, either, try institution */
98415061Sgarrison       first[0] = last[0] = '\0';
98515061Sgarrison       getfield("I", last, ref);
98615061Sgarrison       if (last[0] != '\0')
98715061Sgarrison          return(true);
98815061Sgarrison       }
98915061Sgarrison 
99015061Sgarrison    return(false);
99115061Sgarrison }
99215061Sgarrison 
99315061Sgarrison /* disambiguate - compare adjacent citation strings, and if equal, add
99415061Sgarrison                   single character disambiguators */
99515061Sgarrison    disambiguate()
99615903Srrh {  reg int i, j;
99716244Srrh 	char adstr;
99815061Sgarrison 
999*23492Sgarrison    for (i = 0; i < numrefs-1; i = j) {
100015061Sgarrison       j = i + 1;
100115903Srrh       if (strcmp(refinfo[i].ri_cite, refinfo[j].ri_cite)==0) {
100216244Srrh          adstr = 'a';
1003*23492Sgarrison          for(j = i+1;
1004*23492Sgarrison 	     j<numrefs && strcmp(refinfo[i].ri_cite,refinfo[j].ri_cite) == 0;
1005*23492Sgarrison 	     j++) {
100616244Srrh             adstr = 'a' + (j-i);
100716244Srrh 	    refinfo[j].ri_disambig[0] = adstr;
100815061Sgarrison             }
100916244Srrh 	 refinfo[i].ri_disambig[0] = 'a';
101015061Sgarrison          }
101115061Sgarrison      }
101216244Srrh   for (i = 0; i < numrefs; i++){
101316244Srrh 	strcat(refinfo[i].ri_cite, refinfo[i].ri_disambig);
101416244Srrh   }
101515061Sgarrison }
101615061Sgarrison 
101715061Sgarrison 
101812910Sgarrison /* bldname - build a name field
101912910Sgarrison              doing abbreviations, reversals, and caps/small caps
102012910Sgarrison */
102112910Sgarrison    bldname(first, last, name, reverse)
102212910Sgarrison    char *first, *last, name[];
102312910Sgarrison    int reverse;
102412910Sgarrison {
102515903Srrh    char newfirst[120], newlast[120];
102615903Srrh    reg char *p, *q, *f, *l;
102715903Srrh    char *scopy();
102812910Sgarrison    int  flag;
102912910Sgarrison 
103012910Sgarrison    if (abbrev) {
103112910Sgarrison       p = first;
103212910Sgarrison       q = newfirst;
103312910Sgarrison       flag = false;
103412910Sgarrison       while (*p) {
103512910Sgarrison          while (*p == ' ')
103612910Sgarrison             p++;
103712910Sgarrison          if (*p == 0)
103812910Sgarrison             break;
103912910Sgarrison          if (isupper(*p)) {
104015061Sgarrison             if (flag)           /* between initial gap */
104112910Sgarrison                q = scopy(q, "\\*(a]");
104212910Sgarrison             flag = true;
104312910Sgarrison             *q++ = *p;
104415061Sgarrison             q = scopy(q, "\\*(p]");
104512910Sgarrison             }
104612910Sgarrison          if (*++p == '.')
104712910Sgarrison             p++;
104812910Sgarrison          else while (*p != 0 && ! isspace(*p))
104912910Sgarrison             p++;
105012910Sgarrison          }
105112910Sgarrison       *q = 0;
105212910Sgarrison       f = newfirst;
105312910Sgarrison       }
105412910Sgarrison    else
105512910Sgarrison       f = first;
105612910Sgarrison 
105712910Sgarrison    if (capsmcap) {
105812910Sgarrison       p = last;
105912910Sgarrison       q = newlast;
106012910Sgarrison       flag = 0;  /* 1 - printing cap, 2 - printing small */
106112910Sgarrison       while (*p)
106212910Sgarrison          if (islower(*p)) {
106312910Sgarrison             if (flag != 2)
106412910Sgarrison                q = scopy(q, "\\s-2");
106512910Sgarrison             flag = 2;
106612910Sgarrison             *q++ = (*p++ - 'a') + 'A';
106712910Sgarrison             }
106812910Sgarrison          else {
106912910Sgarrison             if (flag == 2)
107012910Sgarrison                q = scopy(q,"\\s+2");
107112910Sgarrison             flag = 1;
107212910Sgarrison             *q++ = *p++;
107312910Sgarrison             }
107412910Sgarrison       if (flag == 2)
107512910Sgarrison          q = scopy(q, "\\s+2");
107612910Sgarrison       *q = 0;
107712910Sgarrison       l = newlast;
107812910Sgarrison       }
107912910Sgarrison    else
108012910Sgarrison       l = last;
108112910Sgarrison 
108215061Sgarrison    if (f[0] == 0)
108315061Sgarrison       sprintf(name, "%s\n", l);
108415061Sgarrison    else if (reverse)
108515061Sgarrison       sprintf(name, "%s\\*(b]%s\n", l, f);
108612910Sgarrison    else
108712910Sgarrison       sprintf(name, "%s %s\n", f, l);
108812910Sgarrison }
108912910Sgarrison 
109012910Sgarrison /* prtauth - print author or editor field */
109112910Sgarrison    prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev)
109212910Sgarrison    char c, *line;
109312910Sgarrison    int  num, max, abbrev, capsmcap, numrev;
109412910Sgarrison    FILE *ofd;
109512910Sgarrison {  char first[LINELENGTH], last[LINELENGTH];
109612910Sgarrison 
109712910Sgarrison    if (num <= numrev || abbrev || capsmcap) {
109812910Sgarrison       breakname(line, first, last);
109912910Sgarrison       bldname(first, last, line, num <= numrev);
110012910Sgarrison       }
110112910Sgarrison    if (num == 1)
110212910Sgarrison       fprintf(ofd,".ds [%c %s", c, line);
110312910Sgarrison    else if (num < max)
110412910Sgarrison       fprintf(ofd,".as [%c \\*(c]%s", c, line);
110512910Sgarrison    else if (max == 2)
110612910Sgarrison       fprintf(ofd,".as [%c \\*(n]%s", c, line);
110712910Sgarrison    else
110812910Sgarrison       fprintf(ofd,".as [%c \\*(m]%s", c, line);
110912910Sgarrison    if (num == max && index(trailstr, c))
111012910Sgarrison       fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
111112910Sgarrison }
111212910Sgarrison 
111312910Sgarrison /* doline - actually print out a line of reference information */
111412910Sgarrison    doline(c, line, numauths, maxauths, numeds, maxeds, ofd)
111512910Sgarrison    char c, *line;
111612910Sgarrison    int numauths, maxauths, numeds, maxeds;
111712910Sgarrison    FILE *ofd;
111812910Sgarrison {
111912910Sgarrison 
112012910Sgarrison    switch(c) {
112112910Sgarrison       case 'A':
112212910Sgarrison           prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev);
112312910Sgarrison           break;
112412910Sgarrison 
112512910Sgarrison        case 'E':
112612910Sgarrison           prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, ednumrev);
112712910Sgarrison           if (numeds == maxeds)
112812910Sgarrison              fprintf(ofd,".nr [E %d\n", maxeds);
112912910Sgarrison           break;
113012910Sgarrison 
113112910Sgarrison        case 'P':
113212910Sgarrison           if (index(line, '-'))
113312910Sgarrison              fprintf(ofd,".nr [P 1\n");
113412910Sgarrison           else
113512910Sgarrison              fprintf(ofd,".nr [P 0\n");
113612910Sgarrison           fprintf(ofd,".ds [P %s",line);
113712910Sgarrison           if (index(trailstr, 'P'))
113812910Sgarrison              fprintf(ofd,".ds ]P %c\n",line[strlen(line)-2]);
113912910Sgarrison           break;
114012910Sgarrison 
114112910Sgarrison        case 'F':
114212910Sgarrison        case 'K': break;
114312910Sgarrison 
114412910Sgarrison        default:
114512910Sgarrison           fprintf(ofd,".ds [%c %s", c, line);
114612910Sgarrison           if (index(trailstr, c))
114712910Sgarrison              fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
114812910Sgarrison           }
114912910Sgarrison }
115012910Sgarrison 
115115061Sgarrison /* dumpref - dump reference number i */
115215061Sgarrison    dumpref(i, ofd)
115315061Sgarrison    int i;
115415061Sgarrison    FILE *ofd;
115515903Srrh {  char ref[REFSIZE], line[REFSIZE];
115615903Srrh    reg char *p, *q;
115715903Srrh    char *from;
115815061Sgarrison    int numauths, maxauths, numeds, maxeds;
115915061Sgarrison 
116015903Srrh    rdref(&refinfo[i], ref);
116115061Sgarrison    maxauths = maxeds = 0;
116215061Sgarrison    numauths = numeds = 0;
116315061Sgarrison    for (p = ref; *p; p++)
116415061Sgarrison       if (*p == '%')
116515061Sgarrison          if (*(p+1) == 'A') maxauths++;
116615061Sgarrison          else if (*(p+1) == 'E') maxeds++;
116715061Sgarrison    fprintf(ofd, ".[-\n");
116815903Srrh    fprintf(ofd, ".ds [F %s\n", refinfo[i].ri_cite);
116915903Srrh #ifndef INCORE
117015903Srrh    fseek(rfd, (long)refinfo[i].ri_pos, 0);
117115061Sgarrison    while (fgets(line, REFSIZE, rfd) != NULL) {
117215903Srrh #else INCORE
117315903Srrh    for (q = line, from = refinfo[i].ri_ref; *from; /*VOID*/) { /*} */
117415903Srrh 	if (*from == '\n'){
117515903Srrh 		*q++ = '\n';
117615903Srrh 		*q = 0;
117715903Srrh 		q = line;
117815903Srrh 		from++;
117915903Srrh 	} else {
118015903Srrh 		*q++ = *from++;
118115903Srrh 		continue;
118215903Srrh 	}
118315903Srrh #endif INCORE
118415903Srrh 	switch(line[0]){
118515903Srrh 	case 0:
118615903Srrh 		goto doneref;
118715903Srrh 	case '.':
118815903Srrh 		fprintf(ofd, "%s", line);
118915903Srrh 		break;
119015903Srrh 	case '%':
119115903Srrh 		switch(line[1]){
119215903Srrh 		case 'A':	numauths++;	break;
119315903Srrh 		case 'E':	numeds++;	break;
119415903Srrh 		}
119515903Srrh 		for (p = &line[2]; *p == ' '; p++) /*VOID*/;
119615903Srrh 		doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd);
119715903Srrh 	}
119815903Srrh    }
119915903Srrh    doneref:;
120015061Sgarrison    fprintf(ofd,".][\n");
120115061Sgarrison }
1202