static char sccsid
[] = "@(#)bibargs.c 2.12 11/16/87";
Authored by: Tim Budd, University of Arizona, 1983.
Various modifications suggested by:
David Cherveny - Duke University Medical Center
Phil Garrison - UC Berkeley
M. J. Hawley - Yale University
read argument strings for bib and listrefs
do name formatting, printing lines, other actions common to both
# define MAXDEFS 500 /* maximum number of defined words */
char bibfname
[120]; /* file name currently being read */
int biblineno
; /* line number currently being referenced */
int abbrev
= false; /* automatically abbreviate names */
int capsmcap
= false; /* print names in caps small caps (CACM form)*/
int numrev
= 0; /* number of authors names to reverse */
int edabbrev
= false; /* abbreviate editors names ? */
int edcapsmcap
= false; /* print editors in cap small caps */
int ednumrev
= 0; /* number of editors to reverse */
int max_klen
= 6; /* max size of key */
int sort
= false; /* sort references ? (default no) */
int foot
= false; /* footnoted references ? (default endnotes) */
int doacite
= true; /* place citations ? */
int hyphen
= false; /* hypenate contiguous references */
int ordcite
= true; /* order multiple citations */
char sortstr
[80] = "1"; /* sorting template */
char trailstr
[80] = ""; /* trailing characters to output */
char pfile
[400]; /* private file name */
int personal
= false; /* personal file given ? (default no) */
char citetemplate
[80] = "1"; /* citation template */
struct wordinfo words
[MAXDEFS
]; /* defined words */
struct wordinfo
*wordhash
[HASHSIZE
];
struct wordinfo
*wordsearch();
int wordtop
= 0; /* number of defined words */
/* reference file information */
extern struct refinfo refinfo
[];
/* doargs - read command argument line for both bib and listrefs
call rdtext on file arguments, after dumping
default style file if no alternative style is given
int doargs(argc
, argv
, defstyle
)
{ int numfiles
, i
, style
;
for (i
= 1; i
< argc
; i
++)
else { /* take next arg */
case 'a': for (p
= &argv
[i
][2]; *p
; p
++)
if (*p
== 'a' || *p
== 0)
case 'c': if (argv
[i
][2] == 0)
error("citation string expected for 'c'");
for (p
= citetemplate
,q
= &argv
[i
][2]; *p
++ = *q
++; );
case 'e': for (p
= &argv
[i
][2]; *p
; p
++)
case 'l': if (argv
[i
][2]){
max_klen
= atoi(&argv
[i
][2]);
error("too long key size");
error("-l needs a numeric value");
case 'v': doacite
= false;
case 'h': hyphen
= ordcite
= true;
case 'n': for (p
= &argv
[i
][2]; *p
; p
++)
case 'o': ordcite
= true;
case 'p': if (argv
[i
][2])
else { /* take next arg */
case 'r': if (argv
[i
][2] == 0) /* this is now replaced by -ar */
numrev
= atoi(&argv
[i
][2]);
for (p
= sortstr
,q
= &argv
[i
][2]; *p
++ = *q
++; );
case 't': style
= false; /* fall through */
case 'i': if (argv
[i
][2])
else { /* take next arg */
case 'x': capsmcap
= true; /* this is now replaced by -ax */
case 0: if (style
) { /* no style command given, take default */
strcpy(bibfname
,"<stdin>");
default: fputs(argv
[i
], stderr
);
error("'%c' invalid switch", argv
[i
][1]);
fd
= fopen(argv
[i
], "r");
error("can't open file %s", argv
[i
]);
strcpy(bibfname
, argv
[i
]);
if (style
) incfile( defstyle
);
strreplace(COMFILE
, BMACLIB
, name
);
strreplace(DEFSTYLE
, BMACLIB
, name
);
wordstuff("BMACLIB", BMACLIB
);
fprintf(tfd
, ".ds l] %s\n", BMACLIB
);
/* incfile - read in an included file */
char *p
, line
[LINELENGTH
], dline
[LINELENGTH
], word
[80], *tfgets();
if (fd
== NULL
&& *np
!= '/') {
if (fd
== NULL
&& *np
!= '/') {
bibwarning("%s: can't open", np
);
/* now go off and process file */
while (tfgets(line
, LINELENGTH
, fd
) != NULL
) {
case 'A': for (p
= &line
[1]; *p
; p
++)
if (*p
== 'A' || *p
== '\0')
case 'C': for (p
= &line
[1]; *p
== ' '; p
++) ;
case 'D': if ((i
= getwrd(line
, 1, word
)) == 0)
error("word expected in definition");
if (wordsearch(word
)) { /* already there-toss rest of def.*/
while(line
[strlen(line
)-1] == '\\' ) {
if (tfgets(line
, LINELENGTH
, fd
) == NULL
) break;
for (p
= &line
[i
]; *p
== ' '; p
++) ;
for (strcpy(dline
, p
); dline
[strlen(dline
)-1] == '\\'; ){
dline
[strlen(dline
)-1] = '\n';
if (tfgets(line
, LINELENGTH
, fd
) == NULL
) break;
case 'E': for (p
= &line
[1]; *p
; p
++)
case 'I': for (p
= &line
[1]; *p
== ' '; p
++);
case 'H': hyphen
= ordcite
= true;
case 'O': ordcite
= true;
case 'R': if (line
[1] == 0) /* this is now replaced by AR */
for (p
= &line
[1]; *p
== ' '; p
++) ;
case 'T': for (p
= &line
[1]; *p
== ' '; p
++) ;
case 'X': capsmcap
= true; /* this is now replace by AX */
default: fprintf(tfd
,"%s\n",line
);
while (fgets(line
, LINELENGTH
, fd
) != NULL
)
/* bibwarning - print out a warning message */
fprintf(stderr
,"`%s', line %d: ", bibfname
, biblineno
);
fprintf(stderr
, msg
, a1
, a2
);
/* error - report unrecoverable error message */
* clean up temp files and exit
** fixrfd( mode ) -- re-opens the rfd file to be read or write,
** depending on the mode. Uses a static int to save the current mode
** and avoid unnecessary re-openings.
static int cur_mode
= WRITE
; /* rfd open for writing initially */
rfd
= freopen(reffile
, ((mode
== READ
)? "r" : "a"), rfd
);
error("Hell! Couldn't re-open reference file %s",
/* tfgets - fgets which trims off newline */
char *tfgets(line
, n
, ptr
)
/* getwrd - place next word from in[i] into out */
while (in
[i
] == ' ' || in
[i
] == '\n' || in
[i
] == '\t')
while (in
[i
] && in
[i
] != ' ' && in
[i
] != '\t' && in
[i
] != '\n')
i
= 0; /* signals end of in[i..] */
/* walloc - allocate enough space for a word */
i
= malloc(1 + strlen(word
));
/* isword - see if character is legit word char */
if (isalnum(c
) || c
== '&' || c
== '_')
{ char line2
[REFSIZE
], word
[LINELENGTH
];
for (p
= line
; *p
; /*VOID*/){
for (w
= word
; *p
&& iswordc(*p
); ) *w
++ = *p
++;
if (wp
= wordsearch(word
)){
strcpy(word
, wp
->wi_def
);
/* wordstuff- save a word and its definition, building a hash table */
error("too many definitions, max of %d", MAXDEFS
);
words
[wordtop
].wi_length
= strlen(word
);
words
[wordtop
].wi_word
= word
? walloc(word
) : 0;
words
[wordtop
].wi_def
= def
? walloc(def
) : 0;
words
[wordtop
].wi_hp
= wordhash
[i
];
wordhash
[i
] = &words
[wordtop
];
struct wordinfo
*wordsearch(word
)
for (wp
= wordhash
[strhash(word
)]; wp
; wp
= wp
->wi_hp
){
if (wp
->wi_length
== lg
&& (strcmp(wp
->wi_word
, word
) == 0)){
for (value
= 0; *str
; value
<<= 2, value
+= *str
++)/*VOID*/;
/* rdref - read text for an already cited reference */
fixrfd( READ
); /* fix access mode of rfd, if nec. */
fseek(rfd
, p
->ri_pos
, 0);
fread(ref
, p
->ri_length
, 1, rfd
);
/* wrref - write text for a new reference */
fixrfd( WRITE
); /* fix access mode of rfd, if nec. */
fseek(rfd
, p
->ri_pos
, 0); /* go to end of rfd */
fwrite(ref
, p
->ri_length
, 1, rfd
);
/* breakname - break a name into first and last name */
breakname(line
, first
, last
)
char line
[], first
[], last
[];
{ reg
char *t
, *f
, *q
, *r
, *p
;
for (t
= line
; *t
!= '\n'; t
++);
for (t
--; isspace(*t
); t
--);
/* now strip off last name */
for (q
= t
; isspace(*q
) == 0 || ((*q
== ' ') & (*(q
-1) == '\\')); q
--)
for (; isspace(*f
); f
--);
/* first name is start to f, last name is q to t */
for (r
= first
, p
= line
; p
!= f
; )
for (r
= last
, p
= q
, t
++; q
!= t
; )
/* match - see if string1 is a substring of string2 (case independent)*/
for (i
= 0; str2
[i
]; i
++) {
for (j
= 0; str1
[j
]; j
++) {
if (isupper(a
= str2
[i
+j
]))
if (isupper(b
= str1
[j
]))
/* scopy - append a copy of one string to another */
/* rcomp - reference comparison routine for qsort utility */
{ char ref1
[REFSIZE
], ref2
[REFSIZE
], field1
[MAXFIELD
], field2
[MAXFIELD
];
for (p
= sortstr
; *p
; p
= q
) {
q
= getfield(p
, field1
, ref1
);
} else if (strcmp (field1
, "") == 0) { /* field not found */
getfield("F", field1
, ref1
);
if (strcmp (field1
, "") == 0) {
getfield("I", field1
, ref1
);
if (strcmp (field1
, "") == 0) {
if (getfield(p
, field2
, ref2
) == 0) {
} else if (strcmp (field2
, "") == 0) { /* field not found */
getfield("F", field2
, ref2
);
if (strcmp (field2
, "") == 0) {
getfield("I", field2
, ref2
);
if (strcmp (field2
, "") == 0) {
res
= strcmp(field1
, field2
);
/* makecites - make standard citation strings, using citetemplate currently in effect */
{ char ref
[REFSIZE
], tempcite
[100], *malloc();
for (i
= 0; i
< numrefs
; i
++) {
bldcite(tempcite
, i
, ref
);
refinfo
[i
].ri_cite
= malloc(2 + strlen(tempcite
));
if (refinfo
[i
].ri_cite
== NULL
)
strcpy(refinfo
[i
].ri_cite
, tempcite
);
/* bldcite - build a single citation string */
char *getfield(), *aabet(), *aabetlast(),
*fullaabet(), *multfull();
getfield("F", field
, ref
);
if (isalpha(c
)) { /* field name */
q
= getfield(p
-1, field
, ref
);
else if (c
== '1') { /* numeric order */
sprintf(field
,"%d",1 + i
);
else if (c
== '2') /* alternate alphabetic */
else if (c
== '3') /* Astrophysical Journal style*/
cp
= multfull(cp
, ref
, 3);
else if (c
== '4') /* Computing Surveys style*/
cp
= multfull(cp
, ref
, 2);
else if (c
== '8') /* Full alphabetic */
else if (c
== '9') /* Last name of Senior Author*/
else if (c
== '0') { /* print nothing */
/* else if (c == '4') here is how to add new styles */
else if (c
== '{') { /* other information */
error("unexpected end of citation template");
error("unexpected end of citation template");
/* alternate alphabetic citation style -
if 1 author - first three letters of last name
if 2 authors - first two letters of first, followed by first letter of
if 3 or more authors - first letter of first three authors */
{ char field
[REFSIZE
], temp
[100];
if (getname(1, field
, temp
, ref
)) {
if (getname(2, field
, temp
, ref
))
if (getname(3, field
, temp
, ref
)) {
/* alternate alphabetic citation style -
first two characters of last names of all authors
up to max_klen characters.
{ char field
[REFSIZE
], temp
[100];
for (i
= 1; getname(i
, field
, temp
, ref
); i
++) {
for (fp
= field
; *fp
&& (fp
< &(field
[3])); )
/* alternate alphabetic citation style -
entire last name of senior author
{ char field
[REFSIZE
], temp
[100];
if (getname(1, field
, temp
, ref
)) {
Multiple full authors last names (1, 2 or 3 full names).
if 1 author - last name date
if 2 authors - last name and last name date
if 3 or more authors - last name et al. date
if 1 author - last name date
if 2 authors - last name and last name date
if 3 authors - last name, last name and last name date
if 4 or more authors - last name et al. date */
char *multfull(cp
, ref
, maxauthors
)
{ char name1
[100], name2
[100], name3
[100], temp
[100];
if (getname(1, name1
, temp
, ref
)) {
if (((maxauthors
>= 3) && (getname(4, name3
, temp
, ref
)))
|| ((maxauthors
< 3) && (getname(3, name3
, temp
, ref
)))) {
for (fp
= " \\*(e]"; *fp
; )
else if (getname(2, name2
, temp
, ref
)) {
if (getname(3, name3
, temp
, ref
)) {
for (fp
= "\\*(c]"; *fp
; )
for (fp
= "\\*(m]"; *fp
; )
for (fp
= "\\*(n]"; *fp
; )
/* getfield - get a single field from reference */
char *getfield(ptr
, field
, ref
)
char *ptr
, field
[], ref
[];
int n
, len
, i
, getname();
getname(1, field
, temp
, ref
);
if (*p
== '%' && *(p
+1) == *ptr
) {
for (p
= p
+ 2; *p
== ' '; p
++)
for (q
= field
; (*p
!= '\n') && (*p
!= '\0'); )
for (ptr
++; isdigit(*ptr
); ptr
++)
n
= 10 * n
+ (*ptr
- '0');
for (i
= 0; field
[i
] = field
[i
+n
]; i
++)
else if (isdigit(*ptr
)) {
for (; isdigit(*ptr
); ptr
++)
n
= 10 * n
+ (*ptr
- '0');
/* getname - get the nth name field from reference, breaking into
int getname(n
, last
, first
, ref
)
char last
[], first
[], ref
[];
if (*p
== '%' & *(p
+1) == 'A') {
for (p
= p
+ 2; *p
== ' '; p
++) ;
breakname(p
, first
, last
) ;
if (n
== m
) /* no authors, try editors */
if (*p
== '%' & *(p
+1) == 'E') {
for (p
= p
+ 2; *p
== ' '; p
++) ;
breakname(p
, first
, last
) ;
if (n
== m
) { /* no editors, either, try institution */
first
[0] = last
[0] = '\0';
getfield("I", last
, ref
);
/* disambiguate - compare adjacent citation strings, and if equal, add
single character disambiguators */
for (i
= 0; i
< numrefs
-1; i
= j
) {
if (strcmp(refinfo
[i
].ri_cite
, refinfo
[j
].ri_cite
)==0) {
j
<numrefs
&& strcmp(refinfo
[i
].ri_cite
,refinfo
[j
].ri_cite
) == 0;
refinfo
[j
].ri_disambig
[0] = adstr
;
refinfo
[i
].ri_disambig
[0] = 'a';
for (i
= 0; i
< numrefs
; i
++){
strcat(refinfo
[i
].ri_cite
, refinfo
[i
].ri_disambig
);
/* bldname - build a name field
doing abbreviations, reversals, and caps/small caps
bldname(first
, last
, name
, reverse
)
char *first
, *last
, name
[];
char newfirst
[120], newlast
[120];
if (flag
) /* between initial gap */
else while (*p
!= 0 && ! isspace(*p
))
flag
= 0; /* 1 - printing cap, 2 - printing small */
*q
++ = (*p
++ - 'a') + 'A';
sprintf(name
, "%s\n", l
);
sprintf(name
, "%s\\*(b]%s\n", l
, f
);
sprintf(name
, "%s %s\n", f
, l
);
/* prtauth - print author or editor field */
prtauth(c
, line
, num
, max
, ofd
, abbrev
, capsmcap
, numrev
)
int num
, max
, abbrev
, capsmcap
, numrev
;
{ char first
[LINELENGTH
], last
[LINELENGTH
];
if (num
<= numrev
|| abbrev
|| capsmcap
) {
breakname(line
, first
, last
);
bldname(first
, last
, line
, num
<= numrev
);
fprintf(ofd
,".ds [%c %s", c
, line
);
fprintf(ofd
,".as [%c \\*(c]%s", c
, line
);
fprintf(ofd
,".as [%c \\*(n]%s", c
, line
);
fprintf(ofd
,".as [%c \\*(m]%s", c
, line
);
if (num
== max
&& index(trailstr
, c
))
fprintf(ofd
,".ds ]%c %c\n", c
, line
[strlen(line
)-2]);
/* doline - actually print out a line of reference information */
doline(c
, line
, numauths
, maxauths
, numeds
, maxeds
, ofd
)
int numauths
, maxauths
, numeds
, maxeds
;
prtauth(c
, line
, numauths
, maxauths
, ofd
, abbrev
, capsmcap
, numrev
);
prtauth(c
, line
, numeds
, maxeds
, ofd
, edabbrev
, edcapsmcap
, ednumrev
);
fprintf(ofd
,".nr [E %d\n", maxeds
);
fprintf(ofd
,".nr [P 1\n");
fprintf(ofd
,".nr [P 0\n");
fprintf(ofd
,".ds [P %s",line
);
if (index(trailstr
, 'P'))
fprintf(ofd
,".ds ]P %c\n",line
[strlen(line
)-2]);
fprintf(ofd
,".ds [%c %s", c
, line
);
fprintf(ofd
,".ds ]%c %c\n", c
, line
[strlen(line
)-2]);
/* dumpref - dump reference number i */
{ char ref
[REFSIZE
], line
[REFSIZE
];
int numauths
, maxauths
, numeds
, maxeds
;
if ( i
< 0 ) ref
[0] = 0; /* ref not found */
if (*(p
+1) == 'A') maxauths
++;
else if (*(p
+1) == 'E') maxeds
++;
fprintf(ofd
, ".ds [F %s\n", refinfo
[i
].ri_cite
);
fseek(rfd
, (long)refinfo
[i
].ri_pos
, 0);
while (fgets(line
, REFSIZE
, rfd
) != NULL
) {
for (q
= line
, from
= refinfo
[i
].ri_ref
; *from
; /*VOID*/) { /*} */
fprintf(ofd
, "%s", line
);
case 'A': numauths
++; break;
case 'E': numeds
++; break;
for (p
= &line
[2]; *p
== ' '; p
++) /*VOID*/;
doline(line
[1], p
, numauths
, maxauths
, numeds
, maxeds
, ofd
);