xref: /csrg-svn/contrib/bib/src/bibargs.c (revision 31947)
113110Srrh #ifndef lint
2*31947Sbostic static char sccsid[] = "@(#)bibargs.c	2.11	07/27/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];
729*31947Sbostic    char *getfield(), *aabet(), *aabetlast(),
730*31947Sbostic         *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*/
756*31947Sbostic             cp = multfull(cp, ref, 3);
757*31947Sbostic          else if (c == '4')                     /* Computing Surveys style*/
758*31947Sbostic             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 
861*31947Sbostic /*
862*31947Sbostic   Multiple full authors last names (1, 2 or 3 full names).
863*31947Sbostic 
864*31947Sbostic   If maxauthors<3
86515061Sgarrison         if 1 author - last name date
86615061Sgarrison         if 2 authors - last name and last name date
867*31947Sbostic         if 3 or more authors - last name et al. date
868*31947Sbostic   If maxauthors>=3
869*31947Sbostic         if 1 author - last name date
870*31947Sbostic         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 */
873*31947Sbostic    char *multfull(cp, ref, maxauthors)
87415061Sgarrison    char *cp, ref[];
875*31947Sbostic    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*31947Sbostic       if ((maxauthors >= 3) && (getname(4, name3, temp, ref))) {
884*31947Sbostic          for (fp = " \\*(e]"; *fp; )
88515061Sgarrison             *cp++ = *fp++;
88615061Sgarrison          }
88715061Sgarrison       else if (getname(2, name2, temp, ref)) {
88815061Sgarrison          if (getname(3, name3, temp, ref)) {
88915061Sgarrison             for (fp = "\\*(c]"; *fp; )
89015061Sgarrison                *cp++ = *fp++;
89115061Sgarrison             for (fp = name2; *fp; )
89215061Sgarrison                *cp++ = *fp++;
89315061Sgarrison             for (fp = "\\*(m]"; *fp; )
89415061Sgarrison                *cp++ = *fp++;
89515061Sgarrison             for (fp = name3; *fp; )
89615061Sgarrison                *cp++ = *fp++;
89715061Sgarrison             }
89815061Sgarrison          else {
89915061Sgarrison             for (fp = "\\*(n]"; *fp; )
90015061Sgarrison                *cp++ = *fp++;
90115061Sgarrison             for (fp = name2; *fp; )
90215061Sgarrison                *cp++ = *fp++;
90315061Sgarrison             }
90415061Sgarrison          }
90515061Sgarrison     }
90615061Sgarrison return(cp);
90715061Sgarrison }
90815061Sgarrison 
90915061Sgarrison /* getfield - get a single field from reference */
91015061Sgarrison    char *getfield(ptr, field, ref)
91115061Sgarrison    char *ptr, field[], ref[];
91215903Srrh {  reg	char *p, *q;
91315903Srrh    char	temp[100];
91415061Sgarrison    int  n, len, i, getname();
91515061Sgarrison 
91615061Sgarrison    field[0] = 0;
91715061Sgarrison    if (*ptr == 'A')
91815061Sgarrison       getname(1, field, temp, ref);
91915061Sgarrison    else
92015061Sgarrison       for (p = ref; *p; p++)
92115061Sgarrison          if (*p == '%' && *(p+1) == *ptr) {
92215061Sgarrison             for (p = p + 2; *p == ' '; p++)
92315061Sgarrison                ;
92415061Sgarrison             for (q = field; (*p != '\n') && (*p != '\0'); )
92515061Sgarrison                *q++ = *p++;
92615061Sgarrison             *q = 0;
92715061Sgarrison             break;
92815061Sgarrison             }
92915061Sgarrison    n = 0;
93015061Sgarrison    len = strlen(field);
93115061Sgarrison    if (*++ptr == '-') {
93215061Sgarrison       for (ptr++; isdigit(*ptr); ptr++)
93315061Sgarrison          n = 10 * n + (*ptr - '0');
93415061Sgarrison       if (n > len)
93515061Sgarrison          n = 0;
93615061Sgarrison       else
93715061Sgarrison          n = len - n;
93815061Sgarrison       for (i = 0; field[i] = field[i+n]; i++)
93915061Sgarrison          ;
94015061Sgarrison       }
94115061Sgarrison    else if (isdigit(*ptr)) {
94215061Sgarrison       for (; isdigit(*ptr); ptr++)
94315061Sgarrison          n = 10 * n + (*ptr - '0');
94415061Sgarrison       if (n > len)
94515061Sgarrison          n = len;
94615061Sgarrison       field[n] = 0;
94715061Sgarrison       }
94815061Sgarrison 
94915061Sgarrison    if (*ptr == 'u') {
95015061Sgarrison       ptr++;
95115061Sgarrison       for (p = field; *p; p++)
95215061Sgarrison          if (islower(*p))
95315061Sgarrison             *p = (*p - 'a') + 'A';
95415061Sgarrison       }
95515061Sgarrison    else if (*ptr == 'l') {
95615061Sgarrison       ptr++;
95715061Sgarrison       for (p = field; *p; p++)
95815061Sgarrison          if (isupper(*p))
95915061Sgarrison             *p = (*p - 'A') + 'a';
96015061Sgarrison       }
96115061Sgarrison    return(ptr);
96215061Sgarrison }
96315061Sgarrison 
96415061Sgarrison /* getname - get the nth name field from reference, breaking into
96515061Sgarrison              first and last names */
96615061Sgarrison    int getname(n, last, first, ref)
96715061Sgarrison    int  n;
96815061Sgarrison    char last[], first[], ref[];
96915903Srrh {  reg char *p;
97015061Sgarrison    int  m;
97115061Sgarrison 
97215061Sgarrison    m = n;
97315061Sgarrison    for (p = ref; *p; p++)
97415061Sgarrison       if (*p == '%' & *(p+1) == 'A') {
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 authors, try editors */
98415061Sgarrison       for (p = ref; *p; p++)
98515061Sgarrison          if (*p == '%' & *(p+1) == 'E') {
98615061Sgarrison             n--;
98715061Sgarrison             if (n == 0) {
98815061Sgarrison                for (p = p + 2; *p == ' '; p++) ;
98915061Sgarrison                breakname(p, first, last) ;
99015061Sgarrison                return(true);
99115061Sgarrison                }
99215061Sgarrison             }
99315061Sgarrison 
99415061Sgarrison    if (n == m) {        /* no editors, either, try institution */
99515061Sgarrison       first[0] = last[0] = '\0';
99615061Sgarrison       getfield("I", last, ref);
99715061Sgarrison       if (last[0] != '\0')
99815061Sgarrison          return(true);
99915061Sgarrison       }
100015061Sgarrison 
100115061Sgarrison    return(false);
100215061Sgarrison }
100315061Sgarrison 
100415061Sgarrison /* disambiguate - compare adjacent citation strings, and if equal, add
100515061Sgarrison                   single character disambiguators */
100615061Sgarrison    disambiguate()
100715903Srrh {  reg int i, j;
100816244Srrh 	char adstr;
100915061Sgarrison 
101023492Sgarrison    for (i = 0; i < numrefs-1; i = j) {
101115061Sgarrison       j = i + 1;
101215903Srrh       if (strcmp(refinfo[i].ri_cite, refinfo[j].ri_cite)==0) {
101316244Srrh          adstr = 'a';
101423492Sgarrison          for(j = i+1;
101523492Sgarrison 	     j<numrefs && strcmp(refinfo[i].ri_cite,refinfo[j].ri_cite) == 0;
101623492Sgarrison 	     j++) {
101716244Srrh             adstr = 'a' + (j-i);
101816244Srrh 	    refinfo[j].ri_disambig[0] = adstr;
101915061Sgarrison             }
102016244Srrh 	 refinfo[i].ri_disambig[0] = 'a';
102115061Sgarrison          }
102215061Sgarrison      }
102316244Srrh   for (i = 0; i < numrefs; i++){
102416244Srrh 	strcat(refinfo[i].ri_cite, refinfo[i].ri_disambig);
102516244Srrh   }
102615061Sgarrison }
102715061Sgarrison 
102815061Sgarrison 
102912910Sgarrison /* bldname - build a name field
103012910Sgarrison              doing abbreviations, reversals, and caps/small caps
103112910Sgarrison */
103212910Sgarrison    bldname(first, last, name, reverse)
103312910Sgarrison    char *first, *last, name[];
103412910Sgarrison    int reverse;
103512910Sgarrison {
103615903Srrh    char newfirst[120], newlast[120];
103715903Srrh    reg char *p, *q, *f, *l;
103815903Srrh    char *scopy();
103912910Sgarrison    int  flag;
104012910Sgarrison 
104112910Sgarrison    if (abbrev) {
104212910Sgarrison       p = first;
104312910Sgarrison       q = newfirst;
104412910Sgarrison       flag = false;
104512910Sgarrison       while (*p) {
104612910Sgarrison          while (*p == ' ')
104712910Sgarrison             p++;
104812910Sgarrison          if (*p == 0)
104912910Sgarrison             break;
105012910Sgarrison          if (isupper(*p)) {
105115061Sgarrison             if (flag)           /* between initial gap */
105212910Sgarrison                q = scopy(q, "\\*(a]");
105312910Sgarrison             flag = true;
105412910Sgarrison             *q++ = *p;
105515061Sgarrison             q = scopy(q, "\\*(p]");
105612910Sgarrison             }
105712910Sgarrison          if (*++p == '.')
105812910Sgarrison             p++;
105912910Sgarrison          else while (*p != 0 && ! isspace(*p))
106012910Sgarrison             p++;
106112910Sgarrison          }
106212910Sgarrison       *q = 0;
106312910Sgarrison       f = newfirst;
106412910Sgarrison       }
106512910Sgarrison    else
106612910Sgarrison       f = first;
106712910Sgarrison 
106812910Sgarrison    if (capsmcap) {
106912910Sgarrison       p = last;
107012910Sgarrison       q = newlast;
107112910Sgarrison       flag = 0;  /* 1 - printing cap, 2 - printing small */
107212910Sgarrison       while (*p)
107312910Sgarrison          if (islower(*p)) {
107412910Sgarrison             if (flag != 2)
107512910Sgarrison                q = scopy(q, "\\s-2");
107612910Sgarrison             flag = 2;
107712910Sgarrison             *q++ = (*p++ - 'a') + 'A';
107812910Sgarrison             }
107912910Sgarrison          else {
108012910Sgarrison             if (flag == 2)
108112910Sgarrison                q = scopy(q,"\\s+2");
108212910Sgarrison             flag = 1;
108312910Sgarrison             *q++ = *p++;
108412910Sgarrison             }
108512910Sgarrison       if (flag == 2)
108612910Sgarrison          q = scopy(q, "\\s+2");
108712910Sgarrison       *q = 0;
108812910Sgarrison       l = newlast;
108912910Sgarrison       }
109012910Sgarrison    else
109112910Sgarrison       l = last;
109212910Sgarrison 
109315061Sgarrison    if (f[0] == 0)
109415061Sgarrison       sprintf(name, "%s\n", l);
109515061Sgarrison    else if (reverse)
109615061Sgarrison       sprintf(name, "%s\\*(b]%s\n", l, f);
109712910Sgarrison    else
109812910Sgarrison       sprintf(name, "%s %s\n", f, l);
109912910Sgarrison }
110012910Sgarrison 
110112910Sgarrison /* prtauth - print author or editor field */
110212910Sgarrison    prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev)
110312910Sgarrison    char c, *line;
110412910Sgarrison    int  num, max, abbrev, capsmcap, numrev;
110512910Sgarrison    FILE *ofd;
110612910Sgarrison {  char first[LINELENGTH], last[LINELENGTH];
110712910Sgarrison 
110812910Sgarrison    if (num <= numrev || abbrev || capsmcap) {
110912910Sgarrison       breakname(line, first, last);
111012910Sgarrison       bldname(first, last, line, num <= numrev);
111112910Sgarrison       }
111212910Sgarrison    if (num == 1)
111312910Sgarrison       fprintf(ofd,".ds [%c %s", c, line);
111412910Sgarrison    else if (num < max)
111512910Sgarrison       fprintf(ofd,".as [%c \\*(c]%s", c, line);
111612910Sgarrison    else if (max == 2)
111712910Sgarrison       fprintf(ofd,".as [%c \\*(n]%s", c, line);
111812910Sgarrison    else
111912910Sgarrison       fprintf(ofd,".as [%c \\*(m]%s", c, line);
112012910Sgarrison    if (num == max && index(trailstr, c))
112112910Sgarrison       fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
112212910Sgarrison }
112312910Sgarrison 
112412910Sgarrison /* doline - actually print out a line of reference information */
112512910Sgarrison    doline(c, line, numauths, maxauths, numeds, maxeds, ofd)
112612910Sgarrison    char c, *line;
112712910Sgarrison    int numauths, maxauths, numeds, maxeds;
112812910Sgarrison    FILE *ofd;
112912910Sgarrison {
113012910Sgarrison 
113112910Sgarrison    switch(c) {
113212910Sgarrison       case 'A':
113312910Sgarrison           prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev);
113412910Sgarrison           break;
113512910Sgarrison 
113612910Sgarrison        case 'E':
113712910Sgarrison           prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, ednumrev);
113812910Sgarrison           if (numeds == maxeds)
113912910Sgarrison              fprintf(ofd,".nr [E %d\n", maxeds);
114012910Sgarrison           break;
114112910Sgarrison 
114212910Sgarrison        case 'P':
114312910Sgarrison           if (index(line, '-'))
114412910Sgarrison              fprintf(ofd,".nr [P 1\n");
114512910Sgarrison           else
114612910Sgarrison              fprintf(ofd,".nr [P 0\n");
114712910Sgarrison           fprintf(ofd,".ds [P %s",line);
114812910Sgarrison           if (index(trailstr, 'P'))
114912910Sgarrison              fprintf(ofd,".ds ]P %c\n",line[strlen(line)-2]);
115012910Sgarrison           break;
115112910Sgarrison 
115212910Sgarrison        case 'F':
115312910Sgarrison        case 'K': break;
115412910Sgarrison 
115512910Sgarrison        default:
115612910Sgarrison           fprintf(ofd,".ds [%c %s", c, line);
115712910Sgarrison           if (index(trailstr, c))
115812910Sgarrison              fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]);
115912910Sgarrison           }
116012910Sgarrison }
116112910Sgarrison 
116215061Sgarrison /* dumpref - dump reference number i */
116315061Sgarrison    dumpref(i, ofd)
116415061Sgarrison    int i;
116515061Sgarrison    FILE *ofd;
116615903Srrh {  char ref[REFSIZE], line[REFSIZE];
116715903Srrh    reg char *p, *q;
116815903Srrh    char *from;
116915061Sgarrison    int numauths, maxauths, numeds, maxeds;
117015061Sgarrison 
1171*31947Sbostic    if ( i < 0 ) ref[0] = 0; /* ref not found */
1172*31947Sbostic    else {
1173*31947Sbostic 	   rdref(&refinfo[i], ref);
1174*31947Sbostic 	   maxauths = maxeds = 0;
1175*31947Sbostic 	   numauths = numeds = 0;
1176*31947Sbostic 	   for (p = ref; *p; p++)
1177*31947Sbostic 	      if (*p == '%')
1178*31947Sbostic 	         if (*(p+1) == 'A') maxauths++;
1179*31947Sbostic 	         else if (*(p+1) == 'E') maxeds++;
1180*31947Sbostic 	   fprintf(ofd, ".[-\n");
1181*31947Sbostic 	   fprintf(ofd, ".ds [F %s\n", refinfo[i].ri_cite);
118215903Srrh #ifndef INCORE
1183*31947Sbostic 	   fseek(rfd, (long)refinfo[i].ri_pos, 0);
1184*31947Sbostic 	   while (fgets(line, REFSIZE, rfd) != NULL) {
118515903Srrh #else INCORE
1186*31947Sbostic 	   for (q = line, from = refinfo[i].ri_ref; *from; /*VOID*/) { /*} */
1187*31947Sbostic 		if (*from == '\n'){
1188*31947Sbostic 			*q++ = '\n';
1189*31947Sbostic 			*q = 0;
1190*31947Sbostic 			q = line;
1191*31947Sbostic 			from++;
1192*31947Sbostic 		} else {
1193*31947Sbostic 			*q++ = *from++;
1194*31947Sbostic 			continue;
1195*31947Sbostic 		}
119615903Srrh #endif INCORE
1197*31947Sbostic 		switch(line[0]){
1198*31947Sbostic 		case 0:
1199*31947Sbostic 			goto doneref;
1200*31947Sbostic 		case '.':
1201*31947Sbostic 			fprintf(ofd, "%s", line);
1202*31947Sbostic 			break;
1203*31947Sbostic 		case '%':
1204*31947Sbostic 			switch(line[1]){
1205*31947Sbostic 			case 'A':	numauths++;	break;
1206*31947Sbostic 			case 'E':	numeds++;	break;
1207*31947Sbostic 			}
1208*31947Sbostic 			for (p = &line[2]; *p == ' '; p++) /*VOID*/;
1209*31947Sbostic 			doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd);
121015903Srrh 		}
1211*31947Sbostic 	   }
1212*31947Sbostic 	   doneref:;
1213*31947Sbostic 	   fprintf(ofd,".][\n");
121415903Srrh    }
121515061Sgarrison }
1216