113110Srrh #ifndef lint 2*15890Srrh static char sccsid[] = "@(#)bibargs.c 2.3 01/24/84"; 313110Srrh #endif not lint 415061Sgarrison /* 515061Sgarrison Authored by: Tim Budd, University of Arizona, 1983. 615061Sgarrison version 7/4/83 713110Srrh 815061Sgarrison Various modifications suggested by: 915061Sgarrison David Cherveny - Duke University Medical Center 1015061Sgarrison Phil Garrison - UC Berkeley 1115061Sgarrison M. J. Hawley - Yale University 1215061Sgarrison 1315061Sgarrison 1415061Sgarrison 1515061Sgarrison 1612910Sgarrison read argument strings for bib and listrefs 1712910Sgarrison do name formatting, printing lines, other actions common to both 1812910Sgarrison */ 1912910Sgarrison # include <stdio.h> 2012910Sgarrison # include <ctype.h> 2112910Sgarrison # include "bib.h" 2212910Sgarrison # define LINELENGTH 1024 2312910Sgarrison # define MAXDEFS 500 /* maximum number of defined words */ 2412910Sgarrison 2512910Sgarrison /* global variables */ 2615061Sgarrison char bibfname[120]; /* file name currently being read */ 2715061Sgarrison int biblineno; /* line number currently being referenced */ 2812910Sgarrison int abbrev = false; /* automatically abbreviate names */ 2912910Sgarrison int capsmcap = false; /* print names in caps small caps (CACM form)*/ 3012910Sgarrison int numrev = 0; /* number of authors names to reverse */ 3112910Sgarrison int edabbrev = false; /* abbreviate editors names ? */ 3212910Sgarrison int edcapsmcap = false; /* print editors in cap small caps */ 3312910Sgarrison int ednumrev = 0; /* number of editors to reverse */ 3412910Sgarrison int sort = false; /* sort references ? (default no) */ 3512910Sgarrison int foot = false; /* footnoted references ? (default endnotes) */ 3612910Sgarrison int hyphen = false; /* hypenate contiguous references */ 3712910Sgarrison int ordcite = true; /* order multiple citations */ 3812910Sgarrison char sortstr[80] = "1"; /* sorting template */ 3912910Sgarrison char trailstr[80] = ""; /* trailing characters to output */ 4012910Sgarrison char pfile[120]; /* private file name */ 4112910Sgarrison int personal = false; /* personal file given ? (default no) */ 4212910Sgarrison char citetemplate[80] = "1"; /* citation template */ 4312910Sgarrison char *words[MAXDEFS]; /* defined words */ 4412910Sgarrison char *defs[MAXDEFS]; /* defined word definitions */ 4512910Sgarrison int wordtop = -1; /* top of defined words array */ 4612910Sgarrison 4712910Sgarrison /* where output goes */ 4812910Sgarrison extern FILE *tfd; 4915061Sgarrison /* reference file information */ 5015061Sgarrison extern long int refspos[]; 5115061Sgarrison extern char reffile[]; 5215061Sgarrison extern FILE *rfd; 5315061Sgarrison extern char *citestr[]; 5415061Sgarrison extern int numrefs; 5512910Sgarrison 5612910Sgarrison /* doargs - read command argument line for both bib and listrefs 5712910Sgarrison set switch values 5812910Sgarrison call rdtext on file arguments, after dumping 5912910Sgarrison default style file if no alternative style is given 6012910Sgarrison */ 6112910Sgarrison int doargs(argc, argv, defstyle) 6212910Sgarrison int argc; 6312910Sgarrison char **argv, defstyle[]; 6412910Sgarrison { int numfiles, i, style; 6512910Sgarrison char *p, *q, *walloc(); 6612910Sgarrison FILE *fd; 6712910Sgarrison 6812910Sgarrison numfiles = 0; 6912910Sgarrison style = true; 7012910Sgarrison words[0] = walloc("BMACLIB"); 7112910Sgarrison defs[0] = walloc(BMACLIB); 7212910Sgarrison wordtop++; 7312910Sgarrison fputs(".ds l] ",tfd); 7412910Sgarrison fputs(BMACLIB, tfd); 7512910Sgarrison fputs("\n", tfd); 7612910Sgarrison 7712910Sgarrison for (i = 1; i < argc; i++) 7812910Sgarrison if (argv[i][0] == '-') 7912910Sgarrison switch(argv[i][1]) { 8012910Sgarrison 8115061Sgarrison case 'a': for (p = &argv[i][2]; *p; p++) 8215061Sgarrison if (*p == 'a' || *p == 0) 8312961Sgarrison abbrev = true; 8412961Sgarrison else if (*p == 'x') 8512961Sgarrison capsmcap = true; 8612961Sgarrison else if (*p == 'r') { 8712961Sgarrison if (*(p+1)) 8812961Sgarrison numrev = atoi(p+1); 8912961Sgarrison else 9012961Sgarrison numrev = 1000; 9112961Sgarrison break; 9212961Sgarrison } 9312910Sgarrison break; 9412910Sgarrison 9512910Sgarrison case 'c': if (argv[i][2] == 0) 9612910Sgarrison error("citation string expected"); 9712910Sgarrison else 9812910Sgarrison for (p = citetemplate,q = &argv[i][2]; *p++ = *q++; ); 9912910Sgarrison break; 10012910Sgarrison 10112910Sgarrison case 'e': for (p = &argv[i][2]; *p; p++) 10212910Sgarrison if (*p == 'a') 10312910Sgarrison edabbrev = true; 10412910Sgarrison else if (*p == 'x') 10512910Sgarrison edcapsmcap = true; 10612910Sgarrison else if (*p == 'r') { 10712910Sgarrison if (*(p+1)) 10812910Sgarrison ednumrev = atoi(p+1); 10912910Sgarrison else 11012910Sgarrison ednumrev = 1000; 11112910Sgarrison break; 11212910Sgarrison } 11312910Sgarrison break; 11412910Sgarrison 11512910Sgarrison case 'f': foot = true; 11612910Sgarrison hyphen = false; 11712910Sgarrison break; 11812910Sgarrison 11912910Sgarrison case 'h': hyphen = ordcite = true; 12012910Sgarrison break; 12112910Sgarrison 12212910Sgarrison case 'n': for (p = &argv[i][2]; *p; p++) 12312910Sgarrison if (*p == 'a') 12412910Sgarrison abbrev = false; 12512910Sgarrison else if (*p == 'f') 12612910Sgarrison foot = false; 12712910Sgarrison else if (*p == 'h') 12812910Sgarrison hyphen = false; 12912910Sgarrison else if (*p == 'o') 13012910Sgarrison ordcite = false; 13112910Sgarrison else if (*p == 'r') 13212910Sgarrison numrev = 0; 13312910Sgarrison else if (*p == 's') 13412910Sgarrison sort = false; 13512910Sgarrison else if (*p == 'x') 13612910Sgarrison capsmcap = false; 13712910Sgarrison break; 13812910Sgarrison 13912910Sgarrison case 'o': ordcite = true; 14012910Sgarrison break; 14112910Sgarrison 14212910Sgarrison case 'p': if (argv[i][2]) 14312910Sgarrison p = &argv[i][2]; 14412910Sgarrison else { /* take next arg */ 14512910Sgarrison i++; 14612910Sgarrison p = argv[i]; 14712910Sgarrison } 14812910Sgarrison strcpy(pfile, p); 14912910Sgarrison personal = true; 15012910Sgarrison break; 15112910Sgarrison 15215061Sgarrison case 'r': if (argv[i][2] == 0) /* this is now replaced by -ar */ 15312910Sgarrison numrev = 1000; 15412910Sgarrison else 15512910Sgarrison numrev = atoi(&argv[i][2]); 15612910Sgarrison break; 15712910Sgarrison 15812910Sgarrison case 's': sort = true; 15912910Sgarrison if (argv[i][2]) 16012910Sgarrison for (p = sortstr,q = &argv[i][2]; *p++ = *q++; ); 16112910Sgarrison break; 16212910Sgarrison 16315061Sgarrison case 't': style = false; /* fall through */ 16415061Sgarrison case 'i': if (argv[i][2]) 16512910Sgarrison p = &argv[i][2]; 16612910Sgarrison else { /* take next arg */ 16712910Sgarrison i++; 16812910Sgarrison p = argv[i]; 16912910Sgarrison } 17012910Sgarrison incfile(p); 17112910Sgarrison break; 17212910Sgarrison 17315061Sgarrison case 'x': capsmcap = true; /* this is now replaced by -ax */ 17412910Sgarrison break; 17512910Sgarrison 17612910Sgarrison case 0: if (style) { /* no style command given, take default */ 17712910Sgarrison style = false; 17812910Sgarrison incfile( defstyle ); 17912910Sgarrison } 18015061Sgarrison strcpy(bibfname,"<stdin>"); 18112910Sgarrison rdtext(stdin); 18212910Sgarrison numfiles++; 18312910Sgarrison break; 18412910Sgarrison 18512910Sgarrison default: fputs(argv[i], stderr); 18612910Sgarrison error(": invalid switch"); 18712910Sgarrison } 18812910Sgarrison else { /* file name */ 18912910Sgarrison numfiles++; 19012910Sgarrison if (style) { 19112910Sgarrison style = false; 19212910Sgarrison incfile( defstyle ); 19312910Sgarrison } 19412910Sgarrison fd = fopen(argv[i], "r"); 19512910Sgarrison if (fd == NULL) { 19612910Sgarrison fputs(argv[i], stderr); 19712910Sgarrison error(": can't open"); 19812910Sgarrison } 19912910Sgarrison else { 20015061Sgarrison strcpy(bibfname, argv[i]); 20112910Sgarrison rdtext(fd); 20212910Sgarrison fclose(fd); 20312910Sgarrison } 20412910Sgarrison } 20512910Sgarrison 20612910Sgarrison if (style) incfile( defstyle ); 20712910Sgarrison return(numfiles); 20812910Sgarrison 20912910Sgarrison } 21012910Sgarrison 21112910Sgarrison /* incfile - read in an included file */ 21212910Sgarrison incfile(np) 21312910Sgarrison char *np; 21412910Sgarrison { char name[120]; 21512910Sgarrison FILE *fd; 21615061Sgarrison char *p, line[LINELENGTH], dline[LINELENGTH], word[80], *tfgets(); 21715061Sgarrison int i, j, getwrd(); 21812910Sgarrison 21915061Sgarrison strcpy(bibfname, np); 22012910Sgarrison fd = fopen(np, "r"); 22112910Sgarrison if (fd == NULL && *np != '/') { 22212910Sgarrison strcpy(name, "bib."); 22312910Sgarrison strcat(name, np); 22415061Sgarrison strcpy(bibfname, name); 22512910Sgarrison fd = fopen(name, "r"); 22612910Sgarrison } 22712910Sgarrison if (fd == NULL && *np != '/') { 22812910Sgarrison strcpy(name,BMACLIB); 22912910Sgarrison strcat(name, "/bib."); 23012910Sgarrison strcat(name, np); 23115061Sgarrison strcpy(bibfname, name); 23212910Sgarrison fd = fopen(name, "r"); 23312910Sgarrison } 23412910Sgarrison if (fd == NULL) { 23515061Sgarrison bibwarning("%s: can't open", np); 23615061Sgarrison exit(1); 23712910Sgarrison } 23812910Sgarrison 23915061Sgarrison /* now go off and process file */ 24015061Sgarrison biblineno = 1; 24115061Sgarrison while (tfgets(line, LINELENGTH, fd) != NULL) { 24215061Sgarrison biblineno++; 24312910Sgarrison switch(line[0]) { 24412910Sgarrison 24512910Sgarrison case '#': break; 24612910Sgarrison 24712961Sgarrison case 'A': for (p = &line[1]; *p; p++) 24815061Sgarrison if (*p == 'A' || *p == '\0') 24912961Sgarrison abbrev = true; 25012961Sgarrison else if (*p == 'X') 25112961Sgarrison capsmcap = true; 25212961Sgarrison else if (*p == 'R') { 25312961Sgarrison if (*(p+1)) 25412961Sgarrison numrev = atoi(p+1); 25512961Sgarrison else 25612961Sgarrison numrev = 1000; 25712961Sgarrison break; 25812961Sgarrison } 25912910Sgarrison break; 26012910Sgarrison 26112910Sgarrison case 'C': for (p = &line[1]; *p == ' '; p++) ; 26212910Sgarrison strcpy(citetemplate, p); 26312910Sgarrison break; 26412910Sgarrison 26512910Sgarrison case 'D': if ((i = getwrd(line, 1, word)) == 0) 26612910Sgarrison error("word expected in definition"); 26712910Sgarrison for (j = 0; j <= wordtop; j++) 26812910Sgarrison if (strcmp(word, words[j]) == 0) 26912910Sgarrison break; 27012910Sgarrison if (j > wordtop) { 27112910Sgarrison if ((j = ++wordtop) > MAXDEFS) 27212910Sgarrison error("too many defintions"); 27312910Sgarrison words[wordtop] = walloc(word); 27412910Sgarrison } 27512910Sgarrison for (p = &line[i]; *p == ' '; p++) ; 27612910Sgarrison for (strcpy(dline, p); dline[strlen(dline)-1] == '\\'; ){ 27712910Sgarrison dline[strlen(dline)-1] = '\n'; 27815061Sgarrison if (tfgets(line, LINELENGTH, fd) == NULL) break; 27912910Sgarrison strcat(dline, line); 28012910Sgarrison } 28112910Sgarrison defs[j] = walloc(dline); 28212910Sgarrison break; 28312910Sgarrison 28412910Sgarrison case 'E': for (p = &line[1]; *p; p++) 28512910Sgarrison if (*p == 'A') 28612910Sgarrison edabbrev = true; 28712910Sgarrison else if (*p == 'X') 28812910Sgarrison edcapsmcap = true; 28912910Sgarrison else if (*p == 'R') { 29012910Sgarrison if (*(p+1)) 29112910Sgarrison ednumrev = atoi(p+1); 29212910Sgarrison else 29312910Sgarrison ednumrev = 1000; 29412910Sgarrison break; 29512910Sgarrison } 29612910Sgarrison break; 29712910Sgarrison 29812910Sgarrison case 'F': foot = true; 29912910Sgarrison hyphen = false; 30012910Sgarrison break; 30112910Sgarrison 30212910Sgarrison case 'I': for (p = &line[1]; *p == ' '; p++); 30312910Sgarrison expand(p); 30412910Sgarrison incfile(p); 30512910Sgarrison break; 30612910Sgarrison 30712910Sgarrison case 'H': hyphen = ordcite = true; 30812910Sgarrison break; 30912910Sgarrison 31012910Sgarrison case 'O': ordcite = true; 31112910Sgarrison break; 31212910Sgarrison 31315061Sgarrison case 'R': if (line[1] == 0) /* this is now replaced by AR */ 31412910Sgarrison numrev = 1000; 31512910Sgarrison else 31612910Sgarrison numrev = atoi(&line[1]); 31712910Sgarrison break; 31812910Sgarrison 31912910Sgarrison case 'S': sort = true; 32012910Sgarrison for (p = &line[1]; *p == ' '; p++) ; 32112910Sgarrison strcpy(sortstr, p); 32212910Sgarrison break; 32312910Sgarrison 32412910Sgarrison case 'T': for (p = &line[1]; *p == ' '; p++) ; 32512910Sgarrison strcpy(trailstr, p); 32612910Sgarrison break; 32712910Sgarrison 32815061Sgarrison case 'X': capsmcap = true; /* this is now replace by AX */ 32912910Sgarrison break; 33012910Sgarrison 33112910Sgarrison default: fprintf(tfd,"%s\n",line); 33215061Sgarrison while (fgets(line, LINELENGTH, fd) != NULL) 33312910Sgarrison fputs(line, tfd); 33412910Sgarrison return; 33512910Sgarrison } 33615061Sgarrison 33715061Sgarrison } 33815061Sgarrison /* close up */ 33915061Sgarrison fclose(fd); 34012910Sgarrison } 34112910Sgarrison 34215061Sgarrison /* bibwarning - print out a warning message */ 34315061Sgarrison bibwarning(msg, arg) 34415061Sgarrison char *msg, *arg; 34515061Sgarrison { 34615061Sgarrison fprintf(stderr,"`%s', line %d: ", bibfname, biblineno); 34715061Sgarrison fprintf(stderr, msg, arg); 34815061Sgarrison } 34915061Sgarrison 35015061Sgarrison /* error - report unrecoverable error message */ 35115061Sgarrison error(str) 35215061Sgarrison char str[]; 35315061Sgarrison { 35415061Sgarrison bibwarning("%s\n", str); 35515061Sgarrison exit(1); 35615061Sgarrison } 35715061Sgarrison 35815061Sgarrison #ifdef READWRITE 35915061Sgarrison /* 36015061Sgarrison ** fixrfd( mode ) -- re-opens the rfd file to be read or write, 36115061Sgarrison ** depending on the mode. Uses a static int to save the current mode 36215061Sgarrison ** and avoid unnecessary re-openings. 36315061Sgarrison */ 36415061Sgarrison fixrfd( mode ) 36515061Sgarrison register int mode; 36615061Sgarrison { 36715061Sgarrison static int cur_mode = WRITE; /* rfd open for writing initially */ 36815061Sgarrison 36915061Sgarrison if (mode != cur_mode) 37015061Sgarrison { 37115061Sgarrison rfd = freopen(reffile, ((mode == READ)? "r" : "a"), rfd); 37215061Sgarrison cur_mode = mode; 37315061Sgarrison if (rfd == NULL) 37415061Sgarrison error("Hell! Couldn't re-open reference file"); 37515061Sgarrison } 37615061Sgarrison } 37715061Sgarrison #endif 37815061Sgarrison 37915061Sgarrison 38015061Sgarrison /* tfgets - fgets which trims off newline */ 38115061Sgarrison char *tfgets(line, n, ptr) 38215061Sgarrison char line[]; 38315061Sgarrison int n; 38415061Sgarrison FILE *ptr; 38515061Sgarrison { char *p; 38615061Sgarrison 38715061Sgarrison p = fgets(line, n, ptr); 38815061Sgarrison if (p == NULL) 38915061Sgarrison return(NULL); 39015061Sgarrison else 39115061Sgarrison for (p = line; *p; p++) 39215061Sgarrison if (*p == '\n') 39315061Sgarrison *p = 0; 39415061Sgarrison return(line); 39515061Sgarrison } 39615061Sgarrison 39715061Sgarrison /* getwrd - place next word from in[i] into out */ 39815061Sgarrison int getwrd(in, i, out) 39915061Sgarrison char in[], out[]; 40015061Sgarrison int i; 40115061Sgarrison { int j; 40215061Sgarrison 40315061Sgarrison j = 0; 40415061Sgarrison while (in[i] == ' ' || in[i] == '\n' || in[i] == '\t') 40515061Sgarrison i++; 40615061Sgarrison if (in[i]) 40715061Sgarrison while (in[i] && in[i] != ' ' && in[i] != '\t' && in[i] != '\n') 40815061Sgarrison out[j++] = in[i++]; 40915061Sgarrison else 41015061Sgarrison i = 0; /* signals end of in[i..] */ 41115061Sgarrison out[j] = 0; 41215061Sgarrison return (i); 41315061Sgarrison } 41415061Sgarrison 41515061Sgarrison /* walloc - allocate enough space for a word */ 41615061Sgarrison char *walloc(word) 41715061Sgarrison char *word; 41815061Sgarrison { char *i, *malloc(); 41915061Sgarrison i = malloc(1 + strlen(word)); 42015061Sgarrison if (i == NULL) 42115061Sgarrison error("out of storage"); 42215061Sgarrison strcpy(i, word); 42315061Sgarrison return(i); 42415061Sgarrison } 42515061Sgarrison 42612910Sgarrison /* isword - see if character is legit word char */ 42712910Sgarrison int iswordc(c) 42812910Sgarrison char c; 42912910Sgarrison { 43012910Sgarrison if (isalnum(c) || c == '&' || c == '_') 43112910Sgarrison return(true); 43212910Sgarrison return(false); 43312910Sgarrison } 43412910Sgarrison 43512910Sgarrison /* expand - expand reference, replacing defined words */ 43612910Sgarrison expand(line) 43712910Sgarrison char *line; 43812910Sgarrison { char line2[REFSIZE], word[LINELENGTH], *p, *q, *w; 43912910Sgarrison int replaced, i; 44012910Sgarrison 44112910Sgarrison replaced = true; 44212910Sgarrison while (replaced) { 44312910Sgarrison replaced = false; 44412910Sgarrison p = line; 44512910Sgarrison q = line2; 44612910Sgarrison while (*p) { 44712910Sgarrison if (isalnum(*p)) { 44812910Sgarrison for (w = word; *p && iswordc(*p); ) 44912910Sgarrison *w++ = *p++; 45012910Sgarrison *w = 0; 45112910Sgarrison for (i = 0; i <= wordtop; i++) 45212910Sgarrison if (strcmp(word, words[i]) == 0) { 45312910Sgarrison strcpy(word, defs[i]); 45412910Sgarrison replaced = true; 45512910Sgarrison break; 45612910Sgarrison } 45712910Sgarrison for (w = word; *w; ) 45812910Sgarrison *q++ = *w++; 45912910Sgarrison } 46012910Sgarrison else 46112910Sgarrison *q++ = *p++; 46212910Sgarrison } 46312910Sgarrison *q = 0; 46412910Sgarrison p = line; 46512910Sgarrison q = line2; 46612910Sgarrison while (*p++ = *q++); 46712910Sgarrison } 46812910Sgarrison } 46912910Sgarrison 47015061Sgarrison /* rdref - read text for an already cited reference */ 47115061Sgarrison rdref(i, ref) 47215061Sgarrison long int i; 47315061Sgarrison char ref[REFSIZE]; 47415061Sgarrison { 47515061Sgarrison ref[0] = 0; 47615061Sgarrison #ifdef READWRITE 47715061Sgarrison fixrfd( READ ); /* fix access mode of rfd, if nec. */ 47815061Sgarrison #endif 47915061Sgarrison fseek(rfd, i, 0); 48015061Sgarrison fread(ref, 1, REFSIZE, rfd); 48115061Sgarrison } 48215061Sgarrison 48312910Sgarrison /* breakname - break a name into first and last name */ 48412910Sgarrison breakname(line, first, last) 48512910Sgarrison char line[], first[], last[]; 48612910Sgarrison { char *p, *q, *r, *t, *f; 48712910Sgarrison 48812910Sgarrison for (t = line; *t != '\n'; t++); 48912910Sgarrison for (t--; isspace(*t); t--); 49012910Sgarrison 49112910Sgarrison /* now strip off last name */ 49212910Sgarrison for (q = t; isspace(*q) == 0 || ((*q == ' ') & (*(q-1) == '\\')); q--) 49312910Sgarrison if (q == line) 49412910Sgarrison break; 49512910Sgarrison f = q; 49615061Sgarrison if (q != line) { 49712910Sgarrison q++; 49815061Sgarrison for (; isspace(*f); f--); 49915061Sgarrison f++; 50015061Sgarrison } 50112910Sgarrison 50212910Sgarrison /* first name is start to f, last name is q to t */ 50312910Sgarrison 50415061Sgarrison for (r = first, p = line; p != f; ) 50512910Sgarrison *r++ = *p++; 50612910Sgarrison *r = 0; 50712910Sgarrison for (r = last, p = q, t++; q != t; ) 50812910Sgarrison *r++ = *q++; 50912910Sgarrison *r = 0; 51015061Sgarrison 51112910Sgarrison } 51212910Sgarrison 51312910Sgarrison /* match - see if string1 is a substring of string2 (case independent)*/ 51412910Sgarrison int match(str1, str2) 51512910Sgarrison char str1[], str2[]; 51612910Sgarrison { int i, j; 51712910Sgarrison char a, b; 51812910Sgarrison 51912910Sgarrison for (i = 0; str2[i]; i++) { 52012910Sgarrison for (j = 0; str1[j]; j++) { 52112910Sgarrison if (isupper(a = str2[i+j])) 52212910Sgarrison a = (a - 'A') + 'a'; 52312910Sgarrison if (isupper(b = str1[j])) 52412910Sgarrison b = (b - 'A') + 'a'; 52512910Sgarrison if (a != b) 52612910Sgarrison break; 52712910Sgarrison } 52812910Sgarrison if (str1[j] == 0) 52912910Sgarrison return(true); 53012910Sgarrison } 53112910Sgarrison return(false); 53212910Sgarrison } 53312910Sgarrison 53412910Sgarrison /* scopy - append a copy of one string to another */ 53512910Sgarrison char *scopy(p, q) 53612910Sgarrison char *p, *q; 53712910Sgarrison { 53812910Sgarrison while (*p++ = *q++) 53912910Sgarrison ; 54012910Sgarrison return(--p); 54112910Sgarrison } 54212910Sgarrison 54315061Sgarrison /* rcomp - reference comparison routine for qsort utility */ 54415061Sgarrison int rcomp(ap, bp) 54515061Sgarrison long int *ap, *bp; 54615061Sgarrison { char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD]; 54715061Sgarrison char *p, *q, *getfield(); 54815061Sgarrison int neg, res; 54915061Sgarrison int fields_found; 55015061Sgarrison 55115061Sgarrison rdref(*ap, ref1); 55215061Sgarrison rdref(*bp, ref2); 55315061Sgarrison for (p = sortstr; *p; p = q) { 55415061Sgarrison if (*p == '-') { 55515061Sgarrison p++; 55615061Sgarrison neg = true; 55715061Sgarrison } 55815061Sgarrison else 55915061Sgarrison neg = false; 56015061Sgarrison q = getfield(p, field1, ref1); 56115061Sgarrison fields_found = true; 56215061Sgarrison if (q == 0) { 56315061Sgarrison res = 1; 56415061Sgarrison fields_found = false; 56515061Sgarrison } else if (strcmp (field1, "") == 0) { /* field not found */ 56615061Sgarrison if (*p == 'A') { 56715061Sgarrison getfield("F", field1, ref1); 56815061Sgarrison if (strcmp (field1, "") == 0) { 56915061Sgarrison getfield("I", field1, ref1); 57015061Sgarrison if (strcmp (field1, "") == 0) { 57115061Sgarrison res = 1; 57215061Sgarrison fields_found = false; 57315061Sgarrison } 57415061Sgarrison } 57515061Sgarrison } else { 57615061Sgarrison res = 1; 57715061Sgarrison fields_found = false; 57815061Sgarrison } 57915061Sgarrison } 58015061Sgarrison 58115061Sgarrison if (getfield(p, field2, ref2) == 0) { 58215061Sgarrison res = -1; 58315061Sgarrison fields_found = false; 58415061Sgarrison } else if (strcmp (field2, "") == 0) { /* field not found */ 58515061Sgarrison if (*p == 'A') { 58615061Sgarrison getfield("F", field2, ref2); 58715061Sgarrison if (strcmp (field2, "") == 0) { 58815061Sgarrison getfield("I", field2, ref2); 58915061Sgarrison if (strcmp (field2, "") == 0) { 59015061Sgarrison res = -1; 59115061Sgarrison fields_found = false; 59215061Sgarrison } 59315061Sgarrison } 59415061Sgarrison } else { 59515061Sgarrison res = -1; 59615061Sgarrison fields_found = false; 59715061Sgarrison } 59815061Sgarrison } 59915061Sgarrison if (fields_found) { 60015061Sgarrison if (*p == 'A') { 60115061Sgarrison if (isupper(field1[0])) 60215061Sgarrison field1[0] -= 'A' - 'a'; 60315061Sgarrison if (isupper(field2[0])) 60415061Sgarrison field2[0] -= 'A' - 'a'; 60515061Sgarrison } 60615061Sgarrison res = strcmp(field1, field2); 60715061Sgarrison } 60815061Sgarrison if (neg) 60915061Sgarrison res = - res; 61015061Sgarrison if (res != 0) 61115061Sgarrison break; 61215061Sgarrison } 61315061Sgarrison if (res == 0) 61415061Sgarrison if (ap < bp) 61515061Sgarrison res = -1; 61615061Sgarrison else 61715061Sgarrison res = 1; 61815061Sgarrison return(res); 61915061Sgarrison } 62015061Sgarrison 62115061Sgarrison /* makecites - make citation strings */ 62215061Sgarrison makecites(citestr) 62315061Sgarrison char *citestr[]; 62415061Sgarrison { char ref[REFSIZE], tempcite[100], *malloc(); 62515061Sgarrison int i; 62615061Sgarrison 62715061Sgarrison for (i = 0; i <= numrefs; i++) { 62815061Sgarrison rdref(refspos[i], ref); 62915061Sgarrison bldcite(tempcite, i, ref); 63015061Sgarrison citestr[i] = malloc(2 + strlen(tempcite)); /* leave room for disambig */ 63115061Sgarrison if (citestr[i] == NULL) 63215061Sgarrison error("out of storage"); 63315061Sgarrison strcpy(citestr[i], tempcite); 63415061Sgarrison } 63515061Sgarrison } 63615061Sgarrison 63715061Sgarrison /* bldcite - build a single citation string */ 63815061Sgarrison bldcite(cp, i, ref) 63915061Sgarrison char *cp, ref[]; 64015061Sgarrison int i; 641*15890Srrh { char *p, *q, c, *fp, field[REFSIZE]; 642*15890Srrh char *getfield(), *aabet(), *aabetlast(), *astro(); 64315061Sgarrison 64415061Sgarrison getfield("F", field, ref); 64515061Sgarrison if (field[0] != 0) 64615061Sgarrison for (p = field; *p; p++) 64715061Sgarrison *cp++ = *p; 64815061Sgarrison else { 64915061Sgarrison p = citetemplate; 65015061Sgarrison field[0] = 0; 65115061Sgarrison while (c = *p++) { 65215061Sgarrison if (isalpha(c)) { /* field name */ 65315061Sgarrison q = getfield(p-1, field, ref); 65415061Sgarrison if (q != 0) { 65515061Sgarrison p = q; 65615061Sgarrison for (fp = field; *fp; ) 65715061Sgarrison *cp++ = *fp++; 65815061Sgarrison } 65915061Sgarrison } 66015061Sgarrison else if (c == '1') { /* numeric order */ 66115061Sgarrison sprintf(field,"%d",1 + i); 66215061Sgarrison for (fp = field; *fp; ) 66315061Sgarrison *cp++ = *fp++; 66415061Sgarrison } 66515061Sgarrison else if (c == '2') /* alternate alphabetic */ 66615061Sgarrison cp = aabet(cp, ref); 66715061Sgarrison else if (c == '3') /* Astrophysical Journal style*/ 66815061Sgarrison cp = astro(cp, ref); 669*15890Srrh else if (c == '9') /* Last name of Senior Author*/ 670*15890Srrh cp = aabetlast(cp, ref); 67115061Sgarrison /* else if (c == '4') here is how to add new styles */ 67215061Sgarrison else if (c == '{') { /* other information */ 67315061Sgarrison while (*p != '}') 67415061Sgarrison if (*p == 0) 67515061Sgarrison error("unexpected end of citation template"); 67615061Sgarrison else 67715061Sgarrison *cp++ = *p++; 67815061Sgarrison p++; 67915061Sgarrison } 68015061Sgarrison else if (c == '<') { 68115061Sgarrison while (*p != '>') { 68215061Sgarrison if (*p == 0) 68315061Sgarrison error("unexpected end of citation template"); 68415061Sgarrison else 68515061Sgarrison *cp++ = *p++; 68615061Sgarrison } 68715061Sgarrison p++; 68815061Sgarrison } 68915061Sgarrison else if (c != '@') 69015061Sgarrison *cp++ = c; 69115061Sgarrison } 69215061Sgarrison } 69315061Sgarrison *cp++ = 0; 69415061Sgarrison } 69515061Sgarrison 69615061Sgarrison /* alternate alphabetic citation style - 69715061Sgarrison if 1 author - first three letters of last name 69815061Sgarrison if 2 authors - first two letters of first, followed by first letter of 69915061Sgarrison seond 70015061Sgarrison if 3 or more authors - first letter of first three authors */ 70115061Sgarrison char *aabet(cp, ref) 70215061Sgarrison char *cp, ref[]; 70315061Sgarrison { char field[REFSIZE], temp[100], *np, *fp; 70415061Sgarrison int j, getname(); 70515061Sgarrison 70615061Sgarrison if (getname(1, field, temp, ref)) { 70715061Sgarrison np = cp; 70815061Sgarrison fp = field; 70915061Sgarrison for (j = 1; j <= 3; j++) 71015061Sgarrison if (*fp != 0) 71115061Sgarrison *cp++ = *fp++; 71215061Sgarrison if (getname(2, field, temp, ref)) 71315061Sgarrison np[2] = field[0]; 71415061Sgarrison if (getname(3, field, temp, ref)) { 71515061Sgarrison np[1] = np[2]; 71615061Sgarrison np[2] = field[0]; 71715061Sgarrison } 71815061Sgarrison } 71915061Sgarrison return(cp); 72015061Sgarrison } 72115061Sgarrison 722*15890Srrh /* alternate alphabetic citation style - 723*15890Srrh entire last name of senior author 724*15890Srrh */ 725*15890Srrh char *aabetlast(cp, ref) 726*15890Srrh char *cp, ref[]; 727*15890Srrh { char field[REFSIZE], temp[100]; 728*15890Srrh char *fp; 729*15890Srrh int getname(); 730*15890Srrh 731*15890Srrh if (getname(1, field, temp, ref)) { 732*15890Srrh for (fp = field; *fp; ) 733*15890Srrh *cp++ = *fp++; 734*15890Srrh } 735*15890Srrh return(cp); 736*15890Srrh } 737*15890Srrh 73815061Sgarrison /* Astrophysical Journal style 73915061Sgarrison if 1 author - last name date 74015061Sgarrison if 2 authors - last name and last name date 74115061Sgarrison if 3 authors - last name, last name and last name date 74215061Sgarrison if 4 or more authors - last name et al. date */ 74315061Sgarrison char *astro(cp, ref) 74415061Sgarrison char *cp, ref[]; 74515061Sgarrison { char name1[100], name2[100], name3[100], temp[100], *fp; 74615061Sgarrison int getname(); 74715061Sgarrison 74815061Sgarrison if (getname(1, name1, temp, ref)) { 74915061Sgarrison for (fp = name1; *fp; ) 75015061Sgarrison *cp++ = *fp++; 75115061Sgarrison if (getname(4, name3, temp, ref)) { 75215061Sgarrison for (fp = " et al."; *fp; ) 75315061Sgarrison *cp++ = *fp++; 75415061Sgarrison } 75515061Sgarrison else if (getname(2, name2, temp, ref)) { 75615061Sgarrison if (getname(3, name3, temp, ref)) { 75715061Sgarrison for (fp = "\\*(c]"; *fp; ) 75815061Sgarrison *cp++ = *fp++; 75915061Sgarrison for (fp = name2; *fp; ) 76015061Sgarrison *cp++ = *fp++; 76115061Sgarrison for (fp = "\\*(m]"; *fp; ) 76215061Sgarrison *cp++ = *fp++; 76315061Sgarrison for (fp = name3; *fp; ) 76415061Sgarrison *cp++ = *fp++; 76515061Sgarrison } 76615061Sgarrison else { 76715061Sgarrison for (fp = "\\*(n]"; *fp; ) 76815061Sgarrison *cp++ = *fp++; 76915061Sgarrison for (fp = name2; *fp; ) 77015061Sgarrison *cp++ = *fp++; 77115061Sgarrison } 77215061Sgarrison } 77315061Sgarrison } 77415061Sgarrison return(cp); 77515061Sgarrison } 77615061Sgarrison 77715061Sgarrison /* getfield - get a single field from reference */ 77815061Sgarrison char *getfield(ptr, field, ref) 77915061Sgarrison char *ptr, field[], ref[]; 78015061Sgarrison { char *p, *q, temp[100]; 78115061Sgarrison int n, len, i, getname(); 78215061Sgarrison 78315061Sgarrison field[0] = 0; 78415061Sgarrison if (*ptr == 'A') 78515061Sgarrison getname(1, field, temp, ref); 78615061Sgarrison else 78715061Sgarrison for (p = ref; *p; p++) 78815061Sgarrison if (*p == '%' && *(p+1) == *ptr) { 78915061Sgarrison for (p = p + 2; *p == ' '; p++) 79015061Sgarrison ; 79115061Sgarrison for (q = field; (*p != '\n') && (*p != '\0'); ) 79215061Sgarrison *q++ = *p++; 79315061Sgarrison *q = 0; 79415061Sgarrison break; 79515061Sgarrison } 79615061Sgarrison n = 0; 79715061Sgarrison len = strlen(field); 79815061Sgarrison if (*++ptr == '-') { 79915061Sgarrison for (ptr++; isdigit(*ptr); ptr++) 80015061Sgarrison n = 10 * n + (*ptr - '0'); 80115061Sgarrison if (n > len) 80215061Sgarrison n = 0; 80315061Sgarrison else 80415061Sgarrison n = len - n; 80515061Sgarrison for (i = 0; field[i] = field[i+n]; i++) 80615061Sgarrison ; 80715061Sgarrison } 80815061Sgarrison else if (isdigit(*ptr)) { 80915061Sgarrison for (; isdigit(*ptr); ptr++) 81015061Sgarrison n = 10 * n + (*ptr - '0'); 81115061Sgarrison if (n > len) 81215061Sgarrison n = len; 81315061Sgarrison field[n] = 0; 81415061Sgarrison } 81515061Sgarrison 81615061Sgarrison if (*ptr == 'u') { 81715061Sgarrison ptr++; 81815061Sgarrison for (p = field; *p; p++) 81915061Sgarrison if (islower(*p)) 82015061Sgarrison *p = (*p - 'a') + 'A'; 82115061Sgarrison } 82215061Sgarrison else if (*ptr == 'l') { 82315061Sgarrison ptr++; 82415061Sgarrison for (p = field; *p; p++) 82515061Sgarrison if (isupper(*p)) 82615061Sgarrison *p = (*p - 'A') + 'a'; 82715061Sgarrison } 82815061Sgarrison return(ptr); 82915061Sgarrison } 83015061Sgarrison 83115061Sgarrison /* getname - get the nth name field from reference, breaking into 83215061Sgarrison first and last names */ 83315061Sgarrison int getname(n, last, first, ref) 83415061Sgarrison int n; 83515061Sgarrison char last[], first[], ref[]; 83615061Sgarrison { char *p; 83715061Sgarrison int m; 83815061Sgarrison 83915061Sgarrison m = n; 84015061Sgarrison for (p = ref; *p; p++) 84115061Sgarrison if (*p == '%' & *(p+1) == 'A') { 84215061Sgarrison n--; 84315061Sgarrison if (n == 0) { 84415061Sgarrison for (p = p + 2; *p == ' '; p++) ; 84515061Sgarrison breakname(p, first, last) ; 84615061Sgarrison return(true); 84715061Sgarrison } 84815061Sgarrison } 84915061Sgarrison 85015061Sgarrison if (n == m) /* no authors, try editors */ 85115061Sgarrison for (p = ref; *p; p++) 85215061Sgarrison if (*p == '%' & *(p+1) == 'E') { 85315061Sgarrison n--; 85415061Sgarrison if (n == 0) { 85515061Sgarrison for (p = p + 2; *p == ' '; p++) ; 85615061Sgarrison breakname(p, first, last) ; 85715061Sgarrison return(true); 85815061Sgarrison } 85915061Sgarrison } 86015061Sgarrison 86115061Sgarrison if (n == m) { /* no editors, either, try institution */ 86215061Sgarrison first[0] = last[0] = '\0'; 86315061Sgarrison getfield("I", last, ref); 86415061Sgarrison if (last[0] != '\0') 86515061Sgarrison return(true); 86615061Sgarrison } 86715061Sgarrison 86815061Sgarrison return(false); 86915061Sgarrison } 87015061Sgarrison 87115061Sgarrison /* disambiguate - compare adjacent citation strings, and if equal, add 87215061Sgarrison single character disambiguators */ 87315061Sgarrison disambiguate() 87415061Sgarrison { int i, j; 87515061Sgarrison char adstr[2]; 87615061Sgarrison 87715061Sgarrison for (i = 0; i < numrefs; i = j) { 87815061Sgarrison j = i + 1; 87915061Sgarrison if (strcmp(citestr[i], citestr[j])==0) { 88015061Sgarrison adstr[0] = 'a'; adstr[1] = 0; 88115061Sgarrison for (j = i+1; strcmp(citestr[i],citestr[j]) == 0; j++) { 88215061Sgarrison adstr[0] = 'a' + (j-i); 88315061Sgarrison strcat(citestr[j], adstr); 88415061Sgarrison if (j == numrefs) 88515061Sgarrison break; 88615061Sgarrison } 88715061Sgarrison adstr[0] = 'a'; 88815061Sgarrison strcat(citestr[i], adstr); 88915061Sgarrison } 89015061Sgarrison } 89115061Sgarrison } 89215061Sgarrison 89315061Sgarrison 89412910Sgarrison /* bldname - build a name field 89512910Sgarrison doing abbreviations, reversals, and caps/small caps 89612910Sgarrison */ 89712910Sgarrison bldname(first, last, name, reverse) 89812910Sgarrison char *first, *last, name[]; 89912910Sgarrison int reverse; 90012910Sgarrison { 90112910Sgarrison char newfirst[120], newlast[120], *p, *q, *f, *l, *scopy(); 90212910Sgarrison int flag; 90312910Sgarrison 90412910Sgarrison if (abbrev) { 90512910Sgarrison p = first; 90612910Sgarrison q = newfirst; 90712910Sgarrison flag = false; 90812910Sgarrison while (*p) { 90912910Sgarrison while (*p == ' ') 91012910Sgarrison p++; 91112910Sgarrison if (*p == 0) 91212910Sgarrison break; 91312910Sgarrison if (isupper(*p)) { 91415061Sgarrison if (flag) /* between initial gap */ 91512910Sgarrison q = scopy(q, "\\*(a]"); 91612910Sgarrison flag = true; 91712910Sgarrison *q++ = *p; 91815061Sgarrison q = scopy(q, "\\*(p]"); 91912910Sgarrison } 92012910Sgarrison if (*++p == '.') 92112910Sgarrison p++; 92212910Sgarrison else while (*p != 0 && ! isspace(*p)) 92312910Sgarrison p++; 92412910Sgarrison } 92512910Sgarrison *q = 0; 92612910Sgarrison f = newfirst; 92712910Sgarrison } 92812910Sgarrison else 92912910Sgarrison f = first; 93012910Sgarrison 93112910Sgarrison if (capsmcap) { 93212910Sgarrison p = last; 93312910Sgarrison q = newlast; 93412910Sgarrison flag = 0; /* 1 - printing cap, 2 - printing small */ 93512910Sgarrison while (*p) 93612910Sgarrison if (islower(*p)) { 93712910Sgarrison if (flag != 2) 93812910Sgarrison q = scopy(q, "\\s-2"); 93912910Sgarrison flag = 2; 94012910Sgarrison *q++ = (*p++ - 'a') + 'A'; 94112910Sgarrison } 94212910Sgarrison else { 94312910Sgarrison if (flag == 2) 94412910Sgarrison q = scopy(q,"\\s+2"); 94512910Sgarrison flag = 1; 94612910Sgarrison *q++ = *p++; 94712910Sgarrison } 94812910Sgarrison if (flag == 2) 94912910Sgarrison q = scopy(q, "\\s+2"); 95012910Sgarrison *q = 0; 95112910Sgarrison l = newlast; 95212910Sgarrison } 95312910Sgarrison else 95412910Sgarrison l = last; 95512910Sgarrison 95615061Sgarrison if (f[0] == 0) 95715061Sgarrison sprintf(name, "%s\n", l); 95815061Sgarrison else if (reverse) 95915061Sgarrison sprintf(name, "%s\\*(b]%s\n", l, f); 96012910Sgarrison else 96112910Sgarrison sprintf(name, "%s %s\n", f, l); 96212910Sgarrison } 96312910Sgarrison 96412910Sgarrison /* prtauth - print author or editor field */ 96512910Sgarrison prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev) 96612910Sgarrison char c, *line; 96712910Sgarrison int num, max, abbrev, capsmcap, numrev; 96812910Sgarrison FILE *ofd; 96912910Sgarrison { char first[LINELENGTH], last[LINELENGTH]; 97012910Sgarrison 97112910Sgarrison if (num <= numrev || abbrev || capsmcap) { 97212910Sgarrison breakname(line, first, last); 97312910Sgarrison bldname(first, last, line, num <= numrev); 97412910Sgarrison } 97512910Sgarrison if (num == 1) 97612910Sgarrison fprintf(ofd,".ds [%c %s", c, line); 97712910Sgarrison else if (num < max) 97812910Sgarrison fprintf(ofd,".as [%c \\*(c]%s", c, line); 97912910Sgarrison else if (max == 2) 98012910Sgarrison fprintf(ofd,".as [%c \\*(n]%s", c, line); 98112910Sgarrison else 98212910Sgarrison fprintf(ofd,".as [%c \\*(m]%s", c, line); 98312910Sgarrison if (num == max && index(trailstr, c)) 98412910Sgarrison fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]); 98512910Sgarrison } 98612910Sgarrison 98712910Sgarrison /* doline - actually print out a line of reference information */ 98812910Sgarrison doline(c, line, numauths, maxauths, numeds, maxeds, ofd) 98912910Sgarrison char c, *line; 99012910Sgarrison int numauths, maxauths, numeds, maxeds; 99112910Sgarrison FILE *ofd; 99212910Sgarrison { 99312910Sgarrison 99412910Sgarrison switch(c) { 99512910Sgarrison case 'A': 99612910Sgarrison prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev); 99712910Sgarrison break; 99812910Sgarrison 99912910Sgarrison case 'E': 100012910Sgarrison prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, ednumrev); 100112910Sgarrison if (numeds == maxeds) 100212910Sgarrison fprintf(ofd,".nr [E %d\n", maxeds); 100312910Sgarrison break; 100412910Sgarrison 100512910Sgarrison case 'P': 100612910Sgarrison if (index(line, '-')) 100712910Sgarrison fprintf(ofd,".nr [P 1\n"); 100812910Sgarrison else 100912910Sgarrison fprintf(ofd,".nr [P 0\n"); 101012910Sgarrison fprintf(ofd,".ds [P %s",line); 101112910Sgarrison if (index(trailstr, 'P')) 101212910Sgarrison fprintf(ofd,".ds ]P %c\n",line[strlen(line)-2]); 101312910Sgarrison break; 101412910Sgarrison 101512910Sgarrison case 'F': 101612910Sgarrison case 'K': break; 101712910Sgarrison 101812910Sgarrison default: 101912910Sgarrison fprintf(ofd,".ds [%c %s", c, line); 102012910Sgarrison if (index(trailstr, c)) 102112910Sgarrison fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]); 102212910Sgarrison } 102312910Sgarrison } 102412910Sgarrison 102515061Sgarrison /* dumpref - dump reference number i */ 102615061Sgarrison dumpref(i, ofd) 102715061Sgarrison int i; 102815061Sgarrison FILE *ofd; 102915061Sgarrison { char ref[REFSIZE], *p, line[REFSIZE]; 103015061Sgarrison int numauths, maxauths, numeds, maxeds; 103115061Sgarrison 103215061Sgarrison rdref(refspos[i], ref); 103315061Sgarrison maxauths = maxeds = 0; 103415061Sgarrison numauths = numeds = 0; 103515061Sgarrison for (p = ref; *p; p++) 103615061Sgarrison if (*p == '%') 103715061Sgarrison if (*(p+1) == 'A') maxauths++; 103815061Sgarrison else if (*(p+1) == 'E') maxeds++; 103915061Sgarrison fprintf(ofd, ".[-\n"); 104015061Sgarrison fprintf(ofd, ".ds [F %s\n",citestr[i]); 104115061Sgarrison fseek(rfd, (long) refspos[i], 0); 104215061Sgarrison while (fgets(line, REFSIZE, rfd) != NULL) { 104315061Sgarrison if (line[0] == 0) break; 104415061Sgarrison else if (line[0] == '.') fprintf(ofd,"%s",line); 104515061Sgarrison else { 104615061Sgarrison if (line[0] == '%') { 104715061Sgarrison for (p = &line[2]; *p == ' '; p++); 104815061Sgarrison if (line[1] == 'A') numauths++; 104915061Sgarrison else if (line[1] == 'E') numeds++; 105015061Sgarrison 105115061Sgarrison doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd); 105215061Sgarrison } 105315061Sgarrison } 105415061Sgarrison } 105515061Sgarrison fprintf(ofd,".][\n"); 105615061Sgarrison } 1057