xref: /csrg-svn/contrib/bib/src/bibargs.c (revision 32623)
113110Srrh #ifndef lint
2*32623Sgarrison static char sccsid[] = "@(#)bibargs.c	2.12	11/16/87";
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             */
4225528Sgarrison    char pfile[400];             /* 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");
29523492Sgarrison 		   if (wordsearch(word)) { /* already there-toss rest of def.*/
29623492Sgarrison 			while(line[strlen(line)-1] == '\\' ) {
29723492Sgarrison                             if (tfgets(line, LINELENGTH, fd) == NULL) break;
29823492Sgarrison 			}
29915903Srrh 			break;
30023492Sgarrison 		   }
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];
72931947Sbostic    char *getfield(), *aabet(), *aabetlast(),
73031947Sbostic         *fullaabet(), *multfull();
73115061Sgarrison 
73215061Sgarrison    getfield("F", field, ref);
73315061Sgarrison    if (field[0] != 0)
73415061Sgarrison       for (p = field; *p; p++)
73515061Sgarrison          *cp++ = *p;
73615061Sgarrison    else {
73715061Sgarrison       p = citetemplate;
73815061Sgarrison       field[0] = 0;
73915061Sgarrison       while (c = *p++) {
74015061Sgarrison          if (isalpha(c)) {                      /* field name   */
74115061Sgarrison             q = getfield(p-1, field, ref);
74215061Sgarrison             if (q != 0) {
74315061Sgarrison                p = q;
74415061Sgarrison                for (fp = field; *fp; )
74515061Sgarrison                   *cp++ = *fp++;
74615061Sgarrison                }
74715061Sgarrison             }
74815061Sgarrison          else if (c == '1') {                   /* numeric  order */
74915061Sgarrison             sprintf(field,"%d",1 + i);
75015061Sgarrison             for (fp = field; *fp; )
75115061Sgarrison                *cp++ = *fp++;
75215061Sgarrison             }
75315061Sgarrison          else if (c == '2')                     /* alternate alphabetic */
75415061Sgarrison             cp = aabet(cp, ref);
75515061Sgarrison          else if (c == '3')                     /* Astrophysical Journal style*/
75631947Sbostic             cp = multfull(cp, ref, 3);
75731947Sbostic          else if (c == '4')                     /* Computing Surveys style*/
75831947Sbostic             cp = multfull(cp, ref, 2);
75923485Sgarrison 	 else if (c == '8')			/* Full alphabetic */
76023485Sgarrison 	    cp = fullaabet(cp, ref);
76115890Srrh          else if (c == '9')                     /* Last name of Senior Author*/
76215890Srrh             cp = aabetlast(cp, ref);
76317246Srrh 	 else if (c == '0') {			/* print nothing */
76417246Srrh             for (fp = field; *fp; )
76517246Srrh                *cp++ = *fp++;
76617246Srrh             }
76715061Sgarrison /*       else if (c == '4')          here is how to add new styles */
76815061Sgarrison          else if (c == '{') {                   /* other information   */
76915061Sgarrison             while (*p != '}')
77015061Sgarrison                if (*p == 0)
77115061Sgarrison                   error("unexpected end of citation template");
77215061Sgarrison                else
77315061Sgarrison                   *cp++ = *p++;
77415061Sgarrison             p++;
77515061Sgarrison             }
77615061Sgarrison          else if (c == '<') {
77715061Sgarrison             while (*p != '>') {
77815061Sgarrison                if (*p == 0)
77915061Sgarrison                   error("unexpected end of citation template");
78015061Sgarrison                else
78115061Sgarrison                   *cp++ = *p++;
78215061Sgarrison                }
78315061Sgarrison             p++;
78415061Sgarrison             }
78515061Sgarrison          else if (c != '@')
78615061Sgarrison             *cp++ = c;
78715061Sgarrison          }
78815061Sgarrison       }
78915061Sgarrison    *cp++ = 0;
79015061Sgarrison }
79115061Sgarrison 
79215061Sgarrison /* alternate alphabetic citation style -
79315061Sgarrison         if 1 author - first three letters of last name
79415061Sgarrison         if 2 authors - first two letters of first, followed by first letter of
79515061Sgarrison                                 seond
79615061Sgarrison         if 3 or more authors - first letter of first three authors */
79715061Sgarrison    char *aabet(cp, ref)
79815061Sgarrison    char *cp, ref[];
79915903Srrh {  char field[REFSIZE], temp[100];
80015903Srrh    reg char *np, *fp;
80115061Sgarrison    int j, getname();
80215061Sgarrison 
80315061Sgarrison    if (getname(1, field, temp, ref)) {
80415061Sgarrison       np = cp;
80515061Sgarrison       fp = field;
80615061Sgarrison       for (j = 1; j <= 3; j++)
80715061Sgarrison          if (*fp != 0)
80815061Sgarrison             *cp++ = *fp++;
80915061Sgarrison       if (getname(2, field, temp, ref))
81015061Sgarrison          np[2] = field[0];
81115061Sgarrison       if (getname(3, field, temp, ref)) {
81215061Sgarrison          np[1] = np[2];
81315061Sgarrison          np[2] = field[0];
81415061Sgarrison          }
81515061Sgarrison       }
81615061Sgarrison return(cp);
81715061Sgarrison }
81815061Sgarrison 
81915890Srrh /* alternate alphabetic citation style -
82023485Sgarrison 	first two characters of last names of all authors
82123485Sgarrison 	up to max_klen characters.
82223485Sgarrison */
82323485Sgarrison    char *fullaabet(cp, ref)
82423485Sgarrison    char *cp, ref[];
82523485Sgarrison {  char field[REFSIZE], temp[100];
82623485Sgarrison    reg char	*fp;
82723485Sgarrison    char	*lastcp;
82823485Sgarrison    int getname();
82923485Sgarrison    int i;
83023485Sgarrison 
83123485Sgarrison    lastcp = cp + max_klen;
83223485Sgarrison    for (i= 1; getname(i, field, temp, ref); i++) {
83323485Sgarrison       for (fp = field; *fp && (fp < &(field[3])); )
83423485Sgarrison 	 if (cp > lastcp)
83523485Sgarrison 	     break;
83623485Sgarrison          else if (isalpha(*fp))
83723485Sgarrison 	     *cp++ = *fp++;
83823485Sgarrison 	 else
83923485Sgarrison 	     fp++;
84023485Sgarrison    }
84123485Sgarrison    return(cp);
84223485Sgarrison }
84323485Sgarrison 
84423485Sgarrison 
84523485Sgarrison /* alternate alphabetic citation style -
84615890Srrh 	entire last name of senior author
84715890Srrh */
84815890Srrh    char *aabetlast(cp, ref)
84915890Srrh    char *cp, ref[];
85015890Srrh {  char field[REFSIZE], temp[100];
85115903Srrh    reg char	*fp;
85215890Srrh    int getname();
85315890Srrh 
85415890Srrh    if (getname(1, field, temp, ref)) {
85515890Srrh       for (fp = field; *fp; )
85615890Srrh          *cp++ = *fp++;
85715890Srrh    }
85815890Srrh    return(cp);
85915890Srrh }
86015890Srrh 
86131947Sbostic /*
86231947Sbostic   Multiple full authors last names (1, 2 or 3 full names).
86331947Sbostic 
86431947Sbostic   If maxauthors<3
86515061Sgarrison         if 1 author - last name date
86615061Sgarrison         if 2 authors - last name and last name date
86731947Sbostic         if 3 or more authors - last name et al. date
86831947Sbostic   If maxauthors>=3
86931947Sbostic         if 1 author - last name date
87031947Sbostic         if 2 authors - last name and last name date
87115061Sgarrison         if 3 authors - last name, last name and last name date
87215061Sgarrison         if 4 or more authors - last name et al. date */
87331947Sbostic    char *multfull(cp, ref, maxauthors)
87415061Sgarrison    char *cp, ref[];
87531947Sbostic    int maxauthors;
87615903Srrh {  char name1[100], name2[100], name3[100], temp[100];
87715903Srrh    reg char *fp;
87815061Sgarrison    int getname();
87915061Sgarrison 
88015061Sgarrison    if (getname(1, name1, temp, ref)) {
88115061Sgarrison       for (fp = name1; *fp; )
88215061Sgarrison          *cp++ = *fp++;
883*32623Sgarrison       if (((maxauthors >= 3) && (getname(4, name3, temp, ref)))
884*32623Sgarrison 	  || ((maxauthors < 3) && (getname(3, name3, temp, ref)))) {
88531947Sbostic          for (fp = " \\*(e]"; *fp; )
88615061Sgarrison             *cp++ = *fp++;
88715061Sgarrison          }
88815061Sgarrison       else if (getname(2, name2, temp, ref)) {
88915061Sgarrison          if (getname(3, name3, temp, ref)) {
89015061Sgarrison             for (fp = "\\*(c]"; *fp; )
89115061Sgarrison                *cp++ = *fp++;
89215061Sgarrison             for (fp = name2; *fp; )
89315061Sgarrison                *cp++ = *fp++;
89415061Sgarrison             for (fp = "\\*(m]"; *fp; )
89515061Sgarrison                *cp++ = *fp++;
89615061Sgarrison             for (fp = name3; *fp; )
89715061Sgarrison                *cp++ = *fp++;
89815061Sgarrison             }
89915061Sgarrison          else {
90015061Sgarrison             for (fp = "\\*(n]"; *fp; )
90115061Sgarrison                *cp++ = *fp++;
90215061Sgarrison             for (fp = name2; *fp; )
90315061Sgarrison                *cp++ = *fp++;
90415061Sgarrison             }
90515061Sgarrison          }
90615061Sgarrison     }
90715061Sgarrison return(cp);
90815061Sgarrison }
90915061Sgarrison 
91015061Sgarrison /* getfield - get a single field from reference */
91115061Sgarrison    char *getfield(ptr, field, ref)
91215061Sgarrison    char *ptr, field[], ref[];
91315903Srrh {  reg	char *p, *q;
91415903Srrh    char	temp[100];
91515061Sgarrison    int  n, len, i, getname();
91615061Sgarrison 
91715061Sgarrison    field[0] = 0;
91815061Sgarrison    if (*ptr == 'A')
91915061Sgarrison       getname(1, field, temp, ref);
92015061Sgarrison    else
92115061Sgarrison       for (p = ref; *p; p++)
92215061Sgarrison          if (*p == '%' && *(p+1) == *ptr) {
92315061Sgarrison             for (p = p + 2; *p == ' '; p++)
92415061Sgarrison                ;
92515061Sgarrison             for (q = field; (*p != '\n') && (*p != '\0'); )
92615061Sgarrison                *q++ = *p++;
92715061Sgarrison             *q = 0;
92815061Sgarrison             break;
92915061Sgarrison             }
93015061Sgarrison    n = 0;
93115061Sgarrison    len = strlen(field);
93215061Sgarrison    if (*++ptr == '-') {
93315061Sgarrison       for (ptr++; isdigit(*ptr); ptr++)
93415061Sgarrison          n = 10 * n + (*ptr - '0');
93515061Sgarrison       if (n > len)
93615061Sgarrison          n = 0;
93715061Sgarrison       else
93815061Sgarrison          n = len - n;
93915061Sgarrison       for (i = 0; field[i] = field[i+n]; i++)
94015061Sgarrison          ;
94115061Sgarrison       }
94215061Sgarrison    else if (isdigit(*ptr)) {
94315061Sgarrison       for (; isdigit(*ptr); ptr++)
94415061Sgarrison          n = 10 * n + (*ptr - '0');
94515061Sgarrison       if (n > len)
94615061Sgarrison          n = len;
94715061Sgarrison       field[n] = 0;
94815061Sgarrison       }
94915061Sgarrison 
95015061Sgarrison    if (*ptr == 'u') {
95115061Sgarrison       ptr++;
95215061Sgarrison       for (p = field; *p; p++)
95315061Sgarrison          if (islower(*p))
95415061Sgarrison             *p = (*p - 'a') + 'A';
95515061Sgarrison       }
95615061Sgarrison    else if (*ptr == 'l') {
95715061Sgarrison       ptr++;
95815061Sgarrison       for (p = field; *p; p++)
95915061Sgarrison          if (isupper(*p))
96015061Sgarrison             *p = (*p - 'A') + 'a';
96115061Sgarrison       }
96215061Sgarrison    return(ptr);
96315061Sgarrison }
96415061Sgarrison 
96515061Sgarrison /* getname - get the nth name field from reference, breaking into
96615061Sgarrison              first and last names */
96715061Sgarrison    int getname(n, last, first, ref)
96815061Sgarrison    int  n;
96915061Sgarrison    char last[], first[], ref[];
97015903Srrh {  reg char *p;
97115061Sgarrison    int  m;
97215061Sgarrison 
97315061Sgarrison    m = n;
97415061Sgarrison    for (p = ref; *p; p++)
97515061Sgarrison       if (*p == '%' & *(p+1) == 'A') {
97615061Sgarrison          n--;
97715061Sgarrison          if (n == 0) {
97815061Sgarrison             for (p = p + 2; *p == ' '; p++) ;
97915061Sgarrison             breakname(p, first, last) ;
98015061Sgarrison             return(true);
98115061Sgarrison             }
98215061Sgarrison          }
98315061Sgarrison 
98415061Sgarrison    if (n == m)          /* no authors, try editors */
98515061Sgarrison       for (p = ref; *p; p++)
98615061Sgarrison          if (*p == '%' & *(p+1) == 'E') {
98715061Sgarrison             n--;
98815061Sgarrison             if (n == 0) {
98915061Sgarrison                for (p = p + 2; *p == ' '; p++) ;
99015061Sgarrison                breakname(p, first, last) ;
99115061Sgarrison                return(true);
99215061Sgarrison                }
99315061Sgarrison             }
99415061Sgarrison 
99515061Sgarrison    if (n == m) {        /* no editors, either, try institution */
99615061Sgarrison       first[0] = last[0] = '\0';
99715061Sgarrison       getfield("I", last, ref);
99815061Sgarrison       if (last[0] != '\0')
99915061Sgarrison          return(true);
100015061Sgarrison       }
100115061Sgarrison 
100215061Sgarrison    return(false);
100315061Sgarrison }
100415061Sgarrison 
100515061Sgarrison /* disambiguate - compare adjacent citation strings, and if equal, add
100615061Sgarrison                   single character disambiguators */
100715061Sgarrison    disambiguate()
100815903Srrh {  reg int i, j;
100916244Srrh 	char adstr;
101015061Sgarrison 
101123492Sgarrison    for (i = 0; i < numrefs-1; i = j) {
101215061Sgarrison       j = i + 1;
101315903Srrh       if (strcmp(refinfo[i].ri_cite, refinfo[j].ri_cite)==0) {
101416244Srrh          adstr = 'a';
101523492Sgarrison          for(j = i+1;
101623492Sgarrison 	     j<numrefs && strcmp(refinfo[i].ri_cite,refinfo[j].ri_cite) == 0;
101723492Sgarrison 	     j++) {
101816244Srrh             adstr = 'a' + (j-i);
101916244Srrh 	    refinfo[j].ri_disambig[0] = adstr;
102015061Sgarrison             }
102116244Srrh 	 refinfo[i].ri_disambig[0] = 'a';
102215061Sgarrison          }
102315061Sgarrison      }
102416244Srrh   for (i = 0; i < numrefs; i++){
102516244Srrh 	strcat(refinfo[i].ri_cite, refinfo[i].ri_disambig);
102616244Srrh   }
102715061Sgarrison }
102815061Sgarrison 
102915061Sgarrison 
103012910Sgarrison /* bldname - build a name field
103112910Sgarrison              doing abbreviations, reversals, and caps/small caps
103212910Sgarrison */
103312910Sgarrison    bldname(first, last, name, reverse)
103412910Sgarrison    char *first, *last, name[];
103512910Sgarrison    int reverse;
103612910Sgarrison {
103715903Srrh    char newfirst[120], newlast[120];
103815903Srrh    reg char *p, *q, *f, *l;
103915903Srrh    char *scopy();
104012910Sgarrison    int  flag;
104112910Sgarrison 
104212910Sgarrison    if (abbrev) {
104312910Sgarrison       p = first;
104412910Sgarrison       q = newfirst;
104512910Sgarrison       flag = false;
104612910Sgarrison       while (*p) {
104712910Sgarrison          while (*p == ' ')
104812910Sgarrison             p++;
104912910Sgarrison          if (*p == 0)
105012910Sgarrison             break;
105112910Sgarrison          if (isupper(*p)) {
105215061Sgarrison             if (flag)           /* between initial gap */
105312910Sgarrison                q = scopy(q, "\\*(a]");
105412910Sgarrison             flag = true;
105512910Sgarrison             *q++ = *p;
105615061Sgarrison             q = scopy(q, "\\*(p]");
105712910Sgarrison             }
105812910Sgarrison          if (*++p == '.')
105912910Sgarrison             p++;
106012910Sgarrison          else while (*p != 0 && ! isspace(*p))
106112910Sgarrison             p++;
106212910Sgarrison          }
106312910Sgarrison       *q = 0;
106412910Sgarrison       f = newfirst;
106512910Sgarrison       }
106612910Sgarrison    else
106712910Sgarrison       f = first;
106812910Sgarrison 
106912910Sgarrison    if (capsmcap) {
107012910Sgarrison       p = last;
107112910Sgarrison       q = newlast;
107212910Sgarrison       flag = 0;  /* 1 - printing cap, 2 - printing small */
107312910Sgarrison       while (*p)
107412910Sgarrison          if (islower(*p)) {
107512910Sgarrison             if (flag != 2)
107612910Sgarrison                q = scopy(q, "\\s-2");
107712910Sgarrison             flag = 2;
107812910Sgarrison             *q++ = (*p++ - 'a') + 'A';
107912910Sgarrison             }
108012910Sgarrison          else {
108112910Sgarrison             if (flag == 2)
108212910Sgarrison                q = scopy(q,"\\s+2");
108312910Sgarrison             flag = 1;
108412910Sgarrison             *q++ = *p++;
108512910Sgarrison             }
108612910Sgarrison       if (flag == 2)
108712910Sgarrison          q = scopy(q, "\\s+2");
108812910Sgarrison       *q = 0;
108912910Sgarrison       l = newlast;
109012910Sgarrison       }
109112910Sgarrison    else
109212910Sgarrison       l = last;
109312910Sgarrison 
109415061Sgarrison    if (f[0] == 0)
109515061Sgarrison       sprintf(name, "%s\n", l);
109615061Sgarrison    else if (reverse)
109715061Sgarrison       sprintf(name, "%s\\*(b]%s\n", l, f);
109812910Sgarrison    else
109912910Sgarrison       sprintf(name, "%s %s\n", f, l);
110012910Sgarrison }
110112910Sgarrison 
110212910Sgarrison /* prtauth - print author or editor field */
110312910Sgarrison    prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev)
110412910Sgarrison    char c, *line;
110512910Sgarrison    int  num, max, abbrev, capsmcap, numrev;
110612910Sgarrison    FILE *ofd;
110712910Sgarrison {  char first[LINELENGTH], last[LINELENGTH];
110812910Sgarrison 
110912910Sgarrison    if (num <= numrev || abbrev || capsmcap) {
111012910Sgarrison       breakname(line, first, last);
111112910Sgarrison       bldname(first, last, line, num <= numrev);
111212910Sgarrison       }
111312910Sgarrison    if (num == 1)
111412910Sgarrison       fprintf(ofd,".ds [%c %s", c, line);
111512910Sgarrison    else if (num < max)
111612910Sgarrison       fprintf(ofd,".as [%c \\*(c]%s", c, line);
111712910Sgarrison    else if (max == 2)
111812910Sgarrison       fprintf(ofd,".as [%c \\*(n]%s", c, line);
111912910Sgarrison    else
112012910Sgarrison       fprintf(ofd,".as [%c \\*(m]%s", c, line);
112112910Sgarrison    if (num == max && index(trailstr, c))
112212910Sgarrison       fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
112312910Sgarrison }
112412910Sgarrison 
112512910Sgarrison /* doline - actually print out a line of reference information */
112612910Sgarrison    doline(c, line, numauths, maxauths, numeds, maxeds, ofd)
112712910Sgarrison    char c, *line;
112812910Sgarrison    int numauths, maxauths, numeds, maxeds;
112912910Sgarrison    FILE *ofd;
113012910Sgarrison {
113112910Sgarrison 
113212910Sgarrison    switch(c) {
113312910Sgarrison       case 'A':
113412910Sgarrison           prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev);
113512910Sgarrison           break;
113612910Sgarrison 
113712910Sgarrison        case 'E':
113812910Sgarrison           prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, ednumrev);
113912910Sgarrison           if (numeds == maxeds)
114012910Sgarrison              fprintf(ofd,".nr [E %d\n", maxeds);
114112910Sgarrison           break;
114212910Sgarrison 
114312910Sgarrison        case 'P':
114412910Sgarrison           if (index(line, '-'))
114512910Sgarrison              fprintf(ofd,".nr [P 1\n");
114612910Sgarrison           else
114712910Sgarrison              fprintf(ofd,".nr [P 0\n");
114812910Sgarrison           fprintf(ofd,".ds [P %s",line);
114912910Sgarrison           if (index(trailstr, 'P'))
115012910Sgarrison              fprintf(ofd,".ds ]P %c\n",line[strlen(line)-2]);
115112910Sgarrison           break;
115212910Sgarrison 
115312910Sgarrison        case 'F':
115412910Sgarrison        case 'K': break;
115512910Sgarrison 
115612910Sgarrison        default:
115712910Sgarrison           fprintf(ofd,".ds [%c %s", c, line);
115812910Sgarrison           if (index(trailstr, c))
115912910Sgarrison              fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
116012910Sgarrison           }
116112910Sgarrison }
116212910Sgarrison 
116315061Sgarrison /* dumpref - dump reference number i */
116415061Sgarrison    dumpref(i, ofd)
116515061Sgarrison    int i;
116615061Sgarrison    FILE *ofd;
116715903Srrh {  char ref[REFSIZE], line[REFSIZE];
116815903Srrh    reg char *p, *q;
116915903Srrh    char *from;
117015061Sgarrison    int numauths, maxauths, numeds, maxeds;
117115061Sgarrison 
117231947Sbostic    if ( i < 0 ) ref[0] = 0; /* ref not found */
117331947Sbostic    else {
117431947Sbostic 	   rdref(&refinfo[i], ref);
117531947Sbostic 	   maxauths = maxeds = 0;
117631947Sbostic 	   numauths = numeds = 0;
117731947Sbostic 	   for (p = ref; *p; p++)
117831947Sbostic 	      if (*p == '%')
117931947Sbostic 	         if (*(p+1) == 'A') maxauths++;
118031947Sbostic 	         else if (*(p+1) == 'E') maxeds++;
118131947Sbostic 	   fprintf(ofd, ".[-\n");
118231947Sbostic 	   fprintf(ofd, ".ds [F %s\n", refinfo[i].ri_cite);
118315903Srrh #ifndef INCORE
118431947Sbostic 	   fseek(rfd, (long)refinfo[i].ri_pos, 0);
118531947Sbostic 	   while (fgets(line, REFSIZE, rfd) != NULL) {
118615903Srrh #else INCORE
118731947Sbostic 	   for (q = line, from = refinfo[i].ri_ref; *from; /*VOID*/) { /*} */
118831947Sbostic 		if (*from == '\n'){
118931947Sbostic 			*q++ = '\n';
119031947Sbostic 			*q = 0;
119131947Sbostic 			q = line;
119231947Sbostic 			from++;
119331947Sbostic 		} else {
119431947Sbostic 			*q++ = *from++;
119531947Sbostic 			continue;
119631947Sbostic 		}
119715903Srrh #endif INCORE
119831947Sbostic 		switch(line[0]){
119931947Sbostic 		case 0:
120031947Sbostic 			goto doneref;
120131947Sbostic 		case '.':
120231947Sbostic 			fprintf(ofd, "%s", line);
120331947Sbostic 			break;
120431947Sbostic 		case '%':
120531947Sbostic 			switch(line[1]){
120631947Sbostic 			case 'A':	numauths++;	break;
120731947Sbostic 			case 'E':	numeds++;	break;
120831947Sbostic 			}
120931947Sbostic 			for (p = &line[2]; *p == ' '; p++) /*VOID*/;
121031947Sbostic 			doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd);
121115903Srrh 		}
121231947Sbostic 	   }
121331947Sbostic 	   doneref:;
121431947Sbostic 	   fprintf(ofd,".][\n");
121515903Srrh    }
121615061Sgarrison }
1217