Commit | Line | Data |
---|---|---|
d3ce25cd | 1 | #ifndef lint |
95f51977 | 2 | static char sccsid[] = "@(#)bibargs.c 2.10 11/22/85"; |
d3ce25cd | 3 | #endif not lint |
f0a950c2 | 4 | /* |
db589048 GL |
5 | Authored by: Tim Budd, University of Arizona, 1983. |
6 | version 7/4/83 | |
7 | ||
8 | Various modifications suggested by: | |
9 | David Cherveny - Duke University Medical Center | |
10 | Phil Garrison - UC Berkeley | |
11 | M. J. Hawley - Yale University | |
12 | ||
13 | ||
14 | ||
15 | ||
f0a950c2 GL |
16 | read argument strings for bib and listrefs |
17 | do name formatting, printing lines, other actions common to both | |
18 | */ | |
19 | # include <stdio.h> | |
20 | # include <ctype.h> | |
21 | # include "bib.h" | |
22 | # define LINELENGTH 1024 | |
23 | # define MAXDEFS 500 /* maximum number of defined words */ | |
24 | ||
25 | /* global variables */ | |
db589048 GL |
26 | char bibfname[120]; /* file name currently being read */ |
27 | int biblineno; /* line number currently being referenced */ | |
f0a950c2 GL |
28 | int abbrev = false; /* automatically abbreviate names */ |
29 | int capsmcap = false; /* print names in caps small caps (CACM form)*/ | |
30 | int numrev = 0; /* number of authors names to reverse */ | |
31 | int edabbrev = false; /* abbreviate editors names ? */ | |
32 | int edcapsmcap = false; /* print editors in cap small caps */ | |
33 | int ednumrev = 0; /* number of editors to reverse */ | |
ccbea45a | 34 | int max_klen = 6; /* max size of key */ |
f0a950c2 GL |
35 | int sort = false; /* sort references ? (default no) */ |
36 | int foot = false; /* footnoted references ? (default endnotes) */ | |
4e880a3e | 37 | int doacite = true; /* place citations ? */ |
f0a950c2 GL |
38 | int hyphen = false; /* hypenate contiguous references */ |
39 | int ordcite = true; /* order multiple citations */ | |
40 | char sortstr[80] = "1"; /* sorting template */ | |
41 | char trailstr[80] = ""; /* trailing characters to output */ | |
c3076612 | 42 | char pfile[400]; /* private file name */ |
f0a950c2 GL |
43 | int personal = false; /* personal file given ? (default no) */ |
44 | char citetemplate[80] = "1"; /* citation template */ | |
dca84ce7 RH |
45 | struct wordinfo words[MAXDEFS]; /* defined words */ |
46 | struct wordinfo *wordhash[HASHSIZE]; | |
47 | struct wordinfo *wordsearch(); | |
48 | int wordtop = 0; /* number of defined words */ | |
f0a950c2 GL |
49 | |
50 | /* where output goes */ | |
51 | extern FILE *tfd; | |
db589048 | 52 | /* reference file information */ |
dca84ce7 | 53 | extern struct refinfo refinfo[]; |
db589048 | 54 | extern char reffile[]; |
dca84ce7 | 55 | #ifndef INCORE |
db589048 | 56 | extern FILE *rfd; |
dca84ce7 | 57 | #endif not INCORE |
db589048 | 58 | extern int numrefs; |
f0a950c2 GL |
59 | |
60 | /* doargs - read command argument line for both bib and listrefs | |
61 | set switch values | |
62 | call rdtext on file arguments, after dumping | |
63 | default style file if no alternative style is given | |
64 | */ | |
65 | int doargs(argc, argv, defstyle) | |
66 | int argc; | |
67 | char **argv, defstyle[]; | |
68 | { int numfiles, i, style; | |
69 | char *p, *q, *walloc(); | |
70 | FILE *fd; | |
71 | ||
72 | numfiles = 0; | |
73 | style = true; | |
857232a7 | 74 | newbibdir(BMACLIB); |
f0a950c2 GL |
75 | |
76 | for (i = 1; i < argc; i++) | |
77 | if (argv[i][0] == '-') | |
78 | switch(argv[i][1]) { | |
857232a7 RH |
79 | case 'd': |
80 | if (argv[i][2]) | |
81 | p = &argv[i][2]; | |
82 | else { /* take next arg */ | |
83 | i++; | |
84 | p = argv[i]; | |
85 | } | |
86 | newbibdir(p); | |
db589048 GL |
87 | case 'a': for (p = &argv[i][2]; *p; p++) |
88 | if (*p == 'a' || *p == 0) | |
b9b4916e GL |
89 | abbrev = true; |
90 | else if (*p == 'x') | |
91 | capsmcap = true; | |
92 | else if (*p == 'r') { | |
93 | if (*(p+1)) | |
94 | numrev = atoi(p+1); | |
95 | else | |
96 | numrev = 1000; | |
97 | break; | |
98 | } | |
f0a950c2 GL |
99 | break; |
100 | ||
101 | case 'c': if (argv[i][2] == 0) | |
dca84ce7 | 102 | error("citation string expected for 'c'"); |
f0a950c2 GL |
103 | else |
104 | for (p = citetemplate,q = &argv[i][2]; *p++ = *q++; ); | |
105 | break; | |
106 | ||
107 | case 'e': for (p = &argv[i][2]; *p; p++) | |
108 | if (*p == 'a') | |
109 | edabbrev = true; | |
110 | else if (*p == 'x') | |
111 | edcapsmcap = true; | |
112 | else if (*p == 'r') { | |
113 | if (*(p+1)) | |
114 | ednumrev = atoi(p+1); | |
115 | else | |
116 | ednumrev = 1000; | |
117 | break; | |
118 | } | |
119 | break; | |
120 | ||
ccbea45a GL |
121 | case 'l': if (argv[i][2]){ |
122 | max_klen = atoi(&argv[i][2]); | |
123 | if (max_klen > REFSIZE) | |
124 | error("too long key size"); | |
125 | } else { | |
126 | error("-l needs a numeric value"); | |
127 | } | |
128 | break; | |
129 | ||
4e880a3e RH |
130 | case 'v': doacite = false; |
131 | /*FALLTHROUGH*/ | |
f0a950c2 GL |
132 | case 'f': foot = true; |
133 | hyphen = false; | |
134 | break; | |
135 | ||
136 | case 'h': hyphen = ordcite = true; | |
137 | break; | |
138 | ||
139 | case 'n': for (p = &argv[i][2]; *p; p++) | |
140 | if (*p == 'a') | |
141 | abbrev = false; | |
4e880a3e RH |
142 | else if (*p == 'v') |
143 | doacite = true; | |
f0a950c2 GL |
144 | else if (*p == 'f') |
145 | foot = false; | |
146 | else if (*p == 'h') | |
147 | hyphen = false; | |
148 | else if (*p == 'o') | |
149 | ordcite = false; | |
150 | else if (*p == 'r') | |
151 | numrev = 0; | |
152 | else if (*p == 's') | |
153 | sort = false; | |
154 | else if (*p == 'x') | |
155 | capsmcap = false; | |
156 | break; | |
157 | ||
158 | case 'o': ordcite = true; | |
159 | break; | |
160 | ||
161 | case 'p': if (argv[i][2]) | |
162 | p = &argv[i][2]; | |
163 | else { /* take next arg */ | |
164 | i++; | |
165 | p = argv[i]; | |
166 | } | |
167 | strcpy(pfile, p); | |
168 | personal = true; | |
169 | break; | |
170 | ||
db589048 | 171 | case 'r': if (argv[i][2] == 0) /* this is now replaced by -ar */ |
f0a950c2 GL |
172 | numrev = 1000; |
173 | else | |
174 | numrev = atoi(&argv[i][2]); | |
175 | break; | |
176 | ||
177 | case 's': sort = true; | |
178 | if (argv[i][2]) | |
179 | for (p = sortstr,q = &argv[i][2]; *p++ = *q++; ); | |
180 | break; | |
181 | ||
db589048 GL |
182 | case 't': style = false; /* fall through */ |
183 | case 'i': if (argv[i][2]) | |
f0a950c2 GL |
184 | p = &argv[i][2]; |
185 | else { /* take next arg */ | |
186 | i++; | |
187 | p = argv[i]; | |
188 | } | |
189 | incfile(p); | |
190 | break; | |
191 | ||
db589048 | 192 | case 'x': capsmcap = true; /* this is now replaced by -ax */ |
f0a950c2 GL |
193 | break; |
194 | ||
195 | case 0: if (style) { /* no style command given, take default */ | |
196 | style = false; | |
197 | incfile( defstyle ); | |
198 | } | |
db589048 | 199 | strcpy(bibfname,"<stdin>"); |
f0a950c2 GL |
200 | rdtext(stdin); |
201 | numfiles++; | |
202 | break; | |
203 | ||
204 | default: fputs(argv[i], stderr); | |
dca84ce7 | 205 | error("'%c' invalid switch", argv[i][1]); |
f0a950c2 GL |
206 | } |
207 | else { /* file name */ | |
208 | numfiles++; | |
209 | if (style) { | |
210 | style = false; | |
211 | incfile( defstyle ); | |
212 | } | |
213 | fd = fopen(argv[i], "r"); | |
214 | if (fd == NULL) { | |
dca84ce7 | 215 | error("can't open file %s", argv[i]); |
f0a950c2 GL |
216 | } |
217 | else { | |
db589048 | 218 | strcpy(bibfname, argv[i]); |
f0a950c2 GL |
219 | rdtext(fd); |
220 | fclose(fd); | |
221 | } | |
222 | } | |
223 | ||
224 | if (style) incfile( defstyle ); | |
225 | return(numfiles); | |
226 | ||
227 | } | |
228 | ||
857232a7 RH |
229 | newbibdir(name) |
230 | char *name; | |
231 | { | |
232 | strreplace(COMFILE, BMACLIB, name); | |
233 | strreplace(DEFSTYLE, BMACLIB, name); | |
234 | strcpy(BMACLIB, name); | |
235 | wordstuff("BMACLIB", BMACLIB); | |
236 | fprintf(tfd, ".ds l] %s\n", BMACLIB); | |
237 | } | |
238 | ||
f0a950c2 GL |
239 | /* incfile - read in an included file */ |
240 | incfile(np) | |
241 | char *np; | |
242 | { char name[120]; | |
243 | FILE *fd; | |
db589048 | 244 | char *p, line[LINELENGTH], dline[LINELENGTH], word[80], *tfgets(); |
20e80ec2 | 245 | int i, getwrd(); |
f0a950c2 | 246 | |
db589048 | 247 | strcpy(bibfname, np); |
f0a950c2 GL |
248 | fd = fopen(np, "r"); |
249 | if (fd == NULL && *np != '/') { | |
250 | strcpy(name, "bib."); | |
251 | strcat(name, np); | |
db589048 | 252 | strcpy(bibfname, name); |
f0a950c2 GL |
253 | fd = fopen(name, "r"); |
254 | } | |
255 | if (fd == NULL && *np != '/') { | |
256 | strcpy(name,BMACLIB); | |
257 | strcat(name, "/bib."); | |
258 | strcat(name, np); | |
db589048 | 259 | strcpy(bibfname, name); |
f0a950c2 GL |
260 | fd = fopen(name, "r"); |
261 | } | |
262 | if (fd == NULL) { | |
db589048 GL |
263 | bibwarning("%s: can't open", np); |
264 | exit(1); | |
f0a950c2 | 265 | } |
f0a950c2 | 266 | |
db589048 GL |
267 | /* now go off and process file */ |
268 | biblineno = 1; | |
269 | while (tfgets(line, LINELENGTH, fd) != NULL) { | |
270 | biblineno++; | |
f0a950c2 GL |
271 | switch(line[0]) { |
272 | ||
273 | case '#': break; | |
274 | ||
b9b4916e | 275 | case 'A': for (p = &line[1]; *p; p++) |
db589048 | 276 | if (*p == 'A' || *p == '\0') |
b9b4916e GL |
277 | abbrev = true; |
278 | else if (*p == 'X') | |
279 | capsmcap = true; | |
280 | else if (*p == 'R') { | |
281 | if (*(p+1)) | |
282 | numrev = atoi(p+1); | |
283 | else | |
284 | numrev = 1000; | |
285 | break; | |
286 | } | |
f0a950c2 GL |
287 | break; |
288 | ||
289 | case 'C': for (p = &line[1]; *p == ' '; p++) ; | |
290 | strcpy(citetemplate, p); | |
291 | break; | |
292 | ||
293 | case 'D': if ((i = getwrd(line, 1, word)) == 0) | |
294 | error("word expected in definition"); | |
a486c0ef GL |
295 | if (wordsearch(word)) { /* already there-toss rest of def.*/ |
296 | while(line[strlen(line)-1] == '\\' ) { | |
297 | if (tfgets(line, LINELENGTH, fd) == NULL) break; | |
298 | } | |
dca84ce7 | 299 | break; |
a486c0ef | 300 | } |
f0a950c2 GL |
301 | for (p = &line[i]; *p == ' '; p++) ; |
302 | for (strcpy(dline, p); dline[strlen(dline)-1] == '\\'; ){ | |
303 | dline[strlen(dline)-1] = '\n'; | |
db589048 | 304 | if (tfgets(line, LINELENGTH, fd) == NULL) break; |
f0a950c2 GL |
305 | strcat(dline, line); |
306 | } | |
dca84ce7 | 307 | wordstuff(word, dline); |
f0a950c2 GL |
308 | break; |
309 | ||
310 | case 'E': for (p = &line[1]; *p; p++) | |
311 | if (*p == 'A') | |
312 | edabbrev = true; | |
313 | else if (*p == 'X') | |
314 | edcapsmcap = true; | |
315 | else if (*p == 'R') { | |
316 | if (*(p+1)) | |
317 | ednumrev = atoi(p+1); | |
318 | else | |
319 | ednumrev = 1000; | |
320 | break; | |
321 | } | |
322 | break; | |
323 | ||
324 | case 'F': foot = true; | |
325 | hyphen = false; | |
326 | break; | |
327 | ||
328 | case 'I': for (p = &line[1]; *p == ' '; p++); | |
329 | expand(p); | |
330 | incfile(p); | |
331 | break; | |
332 | ||
333 | case 'H': hyphen = ordcite = true; | |
334 | break; | |
335 | ||
336 | case 'O': ordcite = true; | |
337 | break; | |
338 | ||
db589048 | 339 | case 'R': if (line[1] == 0) /* this is now replaced by AR */ |
f0a950c2 GL |
340 | numrev = 1000; |
341 | else | |
342 | numrev = atoi(&line[1]); | |
343 | break; | |
344 | ||
345 | case 'S': sort = true; | |
346 | for (p = &line[1]; *p == ' '; p++) ; | |
347 | strcpy(sortstr, p); | |
348 | break; | |
349 | ||
350 | case 'T': for (p = &line[1]; *p == ' '; p++) ; | |
351 | strcpy(trailstr, p); | |
352 | break; | |
353 | ||
db589048 | 354 | case 'X': capsmcap = true; /* this is now replace by AX */ |
f0a950c2 GL |
355 | break; |
356 | ||
357 | default: fprintf(tfd,"%s\n",line); | |
db589048 | 358 | while (fgets(line, LINELENGTH, fd) != NULL) |
f0a950c2 GL |
359 | fputs(line, tfd); |
360 | return; | |
361 | } | |
db589048 GL |
362 | |
363 | } | |
364 | /* close up */ | |
365 | fclose(fd); | |
366 | } | |
367 | ||
368 | /* bibwarning - print out a warning message */ | |
dca84ce7 RH |
369 | /*VARARGS1*/ |
370 | bibwarning(msg, a1, a2) | |
371 | char *msg; | |
db589048 GL |
372 | { |
373 | fprintf(stderr,"`%s', line %d: ", bibfname, biblineno); | |
dca84ce7 | 374 | fprintf(stderr, msg, a1, a2); |
857232a7 | 375 | fprintf(stderr, "\n"); |
db589048 GL |
376 | } |
377 | ||
378 | /* error - report unrecoverable error message */ | |
dca84ce7 RH |
379 | /*VARARGS1*/ |
380 | error(str, a1, a2) | |
381 | char *str; | |
db589048 | 382 | { |
dca84ce7 RH |
383 | bibwarning(str, a1, a2); |
384 | /* | |
385 | * clean up temp files and exit | |
386 | */ | |
387 | cleanup(1); | |
db589048 GL |
388 | } |
389 | ||
dca84ce7 | 390 | #ifndef INCORE |
db589048 GL |
391 | #ifdef READWRITE |
392 | /* | |
393 | ** fixrfd( mode ) -- re-opens the rfd file to be read or write, | |
394 | ** depending on the mode. Uses a static int to save the current mode | |
395 | ** and avoid unnecessary re-openings. | |
396 | */ | |
397 | fixrfd( mode ) | |
398 | register int mode; | |
399 | { | |
400 | static int cur_mode = WRITE; /* rfd open for writing initially */ | |
401 | ||
402 | if (mode != cur_mode) | |
403 | { | |
404 | rfd = freopen(reffile, ((mode == READ)? "r" : "a"), rfd); | |
405 | cur_mode = mode; | |
406 | if (rfd == NULL) | |
dca84ce7 RH |
407 | error("Hell! Couldn't re-open reference file %s", |
408 | reffile); | |
db589048 GL |
409 | } |
410 | } | |
411 | #endif | |
dca84ce7 | 412 | #endif not INCORE |
db589048 GL |
413 | |
414 | ||
415 | /* tfgets - fgets which trims off newline */ | |
416 | char *tfgets(line, n, ptr) | |
417 | char line[]; | |
418 | int n; | |
419 | FILE *ptr; | |
dca84ce7 | 420 | { reg char *p; |
db589048 GL |
421 | |
422 | p = fgets(line, n, ptr); | |
423 | if (p == NULL) | |
424 | return(NULL); | |
425 | else | |
426 | for (p = line; *p; p++) | |
427 | if (*p == '\n') | |
428 | *p = 0; | |
429 | return(line); | |
430 | } | |
431 | ||
432 | /* getwrd - place next word from in[i] into out */ | |
433 | int getwrd(in, i, out) | |
dca84ce7 RH |
434 | reg char in[], out[]; |
435 | reg int i; | |
db589048 GL |
436 | { int j; |
437 | ||
438 | j = 0; | |
439 | while (in[i] == ' ' || in[i] == '\n' || in[i] == '\t') | |
440 | i++; | |
441 | if (in[i]) | |
442 | while (in[i] && in[i] != ' ' && in[i] != '\t' && in[i] != '\n') | |
443 | out[j++] = in[i++]; | |
444 | else | |
445 | i = 0; /* signals end of in[i..] */ | |
446 | out[j] = 0; | |
447 | return (i); | |
448 | } | |
449 | ||
450 | /* walloc - allocate enough space for a word */ | |
451 | char *walloc(word) | |
452 | char *word; | |
453 | { char *i, *malloc(); | |
454 | i = malloc(1 + strlen(word)); | |
455 | if (i == NULL) | |
456 | error("out of storage"); | |
457 | strcpy(i, word); | |
458 | return(i); | |
f0a950c2 GL |
459 | } |
460 | ||
461 | /* isword - see if character is legit word char */ | |
462 | int iswordc(c) | |
463 | char c; | |
464 | { | |
465 | if (isalnum(c) || c == '&' || c == '_') | |
466 | return(true); | |
467 | return(false); | |
468 | } | |
f0a950c2 GL |
469 | expand(line) |
470 | char *line; | |
dca84ce7 RH |
471 | { char line2[REFSIZE], word[LINELENGTH]; |
472 | reg struct wordinfo *wp; | |
473 | reg char *p, *q, *w; | |
dca84ce7 RH |
474 | |
475 | q = line2; | |
476 | for (p = line; *p; /*VOID*/){ | |
477 | if (isalnum(*p)) { | |
478 | for (w = word; *p && iswordc(*p); ) *w++ = *p++; | |
479 | *w = 0; | |
480 | if (wp = wordsearch(word)){ | |
481 | strcpy(word, wp->wi_def); | |
482 | expand(word); | |
483 | } | |
484 | strcpy(q, word); | |
485 | q += strlen(q); | |
486 | } else { | |
487 | *q++ = *p++; | |
488 | } | |
489 | } | |
490 | *q = 0; | |
491 | strcpy(line, line2); | |
492 | } | |
493 | ||
494 | /* wordstuff- save a word and its definition, building a hash table */ | |
495 | wordstuff(word, def) | |
496 | char *word, *def; | |
497 | { | |
498 | int i; | |
499 | if (wordtop >= MAXDEFS) | |
500 | error("too many definitions, max of %d", MAXDEFS); | |
501 | words[wordtop].wi_length = strlen(word); | |
502 | words[wordtop].wi_word = word ? walloc(word) : 0; | |
503 | words[wordtop].wi_def = def ? walloc(def) : 0; | |
504 | i = strhash(word); | |
505 | words[wordtop].wi_hp = wordhash[i]; | |
506 | wordhash[i] = &words[wordtop]; | |
507 | wordtop++; | |
508 | } | |
509 | struct wordinfo *wordsearch(word) | |
510 | char *word; | |
511 | { | |
dca84ce7 RH |
512 | reg int lg; |
513 | reg struct wordinfo *wp; | |
514 | lg = strlen(word); | |
515 | for (wp = wordhash[strhash(word)]; wp; wp = wp->wi_hp){ | |
516 | if (wp->wi_length == lg && (strcmp(wp->wi_word, word) == 0)){ | |
517 | return(wp); | |
518 | } | |
519 | } | |
520 | return(0); | |
521 | } | |
522 | ||
523 | int strhash(str) | |
524 | reg char *str; | |
525 | { | |
526 | reg int value = 0; | |
527 | for (value = 0; *str; value <<= 2, value += *str++)/*VOID*/; | |
528 | value %= HASHSIZE; | |
529 | if (value < 0) | |
530 | value += HASHSIZE; | |
531 | return(value); | |
f0a950c2 GL |
532 | } |
533 | ||
db589048 | 534 | /* rdref - read text for an already cited reference */ |
dca84ce7 RH |
535 | rdref(p, ref) |
536 | struct refinfo *p; | |
db589048 GL |
537 | char ref[REFSIZE]; |
538 | { | |
539 | ref[0] = 0; | |
dca84ce7 | 540 | #ifndef INCORE |
db589048 GL |
541 | #ifdef READWRITE |
542 | fixrfd( READ ); /* fix access mode of rfd, if nec. */ | |
543 | #endif | |
dca84ce7 RH |
544 | fseek(rfd, p->ri_pos, 0); |
545 | fread(ref, p->ri_length, 1, rfd); | |
546 | #else INCORE | |
547 | strcpy(ref, p->ri_ref); | |
548 | #endif INCORE | |
549 | } | |
550 | ||
551 | /* wrref - write text for a new reference */ | |
552 | wrref(p, ref) | |
553 | struct refinfo *p; | |
554 | char ref[REFSIZE]; | |
555 | { | |
556 | #ifndef INCORE | |
557 | #ifdef READWRITE | |
558 | fixrfd( WRITE ); /* fix access mode of rfd, if nec. */ | |
559 | #else | |
560 | fseek(rfd, p->ri_pos, 0); /* go to end of rfd */ | |
561 | #endif | |
562 | fwrite(ref, p->ri_length, 1, rfd); | |
563 | #else INCORE | |
564 | p->ri_ref = walloc(ref); | |
565 | #endif INCORE | |
db589048 GL |
566 | } |
567 | ||
f0a950c2 GL |
568 | /* breakname - break a name into first and last name */ |
569 | breakname(line, first, last) | |
570 | char line[], first[], last[]; | |
dca84ce7 | 571 | { reg char *t, *f, *q, *r, *p; |
f0a950c2 GL |
572 | |
573 | for (t = line; *t != '\n'; t++); | |
574 | for (t--; isspace(*t); t--); | |
575 | ||
576 | /* now strip off last name */ | |
577 | for (q = t; isspace(*q) == 0 || ((*q == ' ') & (*(q-1) == '\\')); q--) | |
578 | if (q == line) | |
579 | break; | |
580 | f = q; | |
db589048 | 581 | if (q != line) { |
f0a950c2 | 582 | q++; |
db589048 GL |
583 | for (; isspace(*f); f--); |
584 | f++; | |
585 | } | |
f0a950c2 GL |
586 | |
587 | /* first name is start to f, last name is q to t */ | |
588 | ||
db589048 | 589 | for (r = first, p = line; p != f; ) |
f0a950c2 GL |
590 | *r++ = *p++; |
591 | *r = 0; | |
592 | for (r = last, p = q, t++; q != t; ) | |
593 | *r++ = *q++; | |
594 | *r = 0; | |
db589048 | 595 | |
f0a950c2 GL |
596 | } |
597 | ||
598 | /* match - see if string1 is a substring of string2 (case independent)*/ | |
599 | int match(str1, str2) | |
dca84ce7 RH |
600 | reg char str1[], str2[]; |
601 | { reg int j, i; | |
f0a950c2 GL |
602 | char a, b; |
603 | ||
604 | for (i = 0; str2[i]; i++) { | |
605 | for (j = 0; str1[j]; j++) { | |
606 | if (isupper(a = str2[i+j])) | |
607 | a = (a - 'A') + 'a'; | |
608 | if (isupper(b = str1[j])) | |
609 | b = (b - 'A') + 'a'; | |
610 | if (a != b) | |
611 | break; | |
612 | } | |
613 | if (str1[j] == 0) | |
614 | return(true); | |
615 | } | |
616 | return(false); | |
617 | } | |
618 | ||
619 | /* scopy - append a copy of one string to another */ | |
620 | char *scopy(p, q) | |
dca84ce7 | 621 | reg char *p, *q; |
f0a950c2 GL |
622 | { |
623 | while (*p++ = *q++) | |
624 | ; | |
625 | return(--p); | |
626 | } | |
627 | ||
db589048 GL |
628 | /* rcomp - reference comparison routine for qsort utility */ |
629 | int rcomp(ap, bp) | |
dca84ce7 | 630 | struct refinfo *ap, *bp; |
db589048 | 631 | { char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD]; |
dca84ce7 RH |
632 | reg char *p, *q; |
633 | char *getfield(); | |
db589048 GL |
634 | int neg, res; |
635 | int fields_found; | |
636 | ||
dca84ce7 RH |
637 | rdref(ap, ref1); |
638 | rdref(bp, ref2); | |
db589048 GL |
639 | for (p = sortstr; *p; p = q) { |
640 | if (*p == '-') { | |
641 | p++; | |
642 | neg = true; | |
643 | } | |
644 | else | |
645 | neg = false; | |
646 | q = getfield(p, field1, ref1); | |
647 | fields_found = true; | |
648 | if (q == 0) { | |
649 | res = 1; | |
650 | fields_found = false; | |
651 | } else if (strcmp (field1, "") == 0) { /* field not found */ | |
652 | if (*p == 'A') { | |
653 | getfield("F", field1, ref1); | |
654 | if (strcmp (field1, "") == 0) { | |
655 | getfield("I", field1, ref1); | |
656 | if (strcmp (field1, "") == 0) { | |
657 | res = 1; | |
658 | fields_found = false; | |
659 | } | |
660 | } | |
661 | } else { | |
662 | res = 1; | |
663 | fields_found = false; | |
664 | } | |
665 | } | |
666 | ||
667 | if (getfield(p, field2, ref2) == 0) { | |
668 | res = -1; | |
669 | fields_found = false; | |
670 | } else if (strcmp (field2, "") == 0) { /* field not found */ | |
671 | if (*p == 'A') { | |
672 | getfield("F", field2, ref2); | |
673 | if (strcmp (field2, "") == 0) { | |
674 | getfield("I", field2, ref2); | |
675 | if (strcmp (field2, "") == 0) { | |
676 | res = -1; | |
677 | fields_found = false; | |
678 | } | |
679 | } | |
680 | } else { | |
681 | res = -1; | |
682 | fields_found = false; | |
683 | } | |
684 | } | |
685 | if (fields_found) { | |
686 | if (*p == 'A') { | |
687 | if (isupper(field1[0])) | |
688 | field1[0] -= 'A' - 'a'; | |
689 | if (isupper(field2[0])) | |
690 | field2[0] -= 'A' - 'a'; | |
691 | } | |
692 | res = strcmp(field1, field2); | |
693 | } | |
694 | if (neg) | |
695 | res = - res; | |
696 | if (res != 0) | |
697 | break; | |
698 | } | |
699 | if (res == 0) | |
700 | if (ap < bp) | |
701 | res = -1; | |
702 | else | |
703 | res = 1; | |
704 | return(res); | |
705 | } | |
706 | ||
20e80ec2 | 707 | /* makecites - make standard citation strings, using citetemplate currently in effect */ |
dca84ce7 | 708 | makecites() |
db589048 | 709 | { char ref[REFSIZE], tempcite[100], *malloc(); |
dca84ce7 | 710 | reg int i; |
db589048 | 711 | |
dca84ce7 RH |
712 | for (i = 0; i < numrefs; i++) { |
713 | rdref(&refinfo[i], ref); | |
db589048 | 714 | bldcite(tempcite, i, ref); |
20e80ec2 | 715 | refinfo[i].ri_cite = malloc(2 + strlen(tempcite)); |
dca84ce7 | 716 | if (refinfo[i].ri_cite == NULL) |
db589048 | 717 | error("out of storage"); |
dca84ce7 | 718 | strcpy(refinfo[i].ri_cite, tempcite); |
db589048 GL |
719 | } |
720 | } | |
721 | ||
722 | /* bldcite - build a single citation string */ | |
723 | bldcite(cp, i, ref) | |
724 | char *cp, ref[]; | |
725 | int i; | |
dca84ce7 RH |
726 | { reg char *p, *q, *fp; |
727 | char c; | |
728 | char field[REFSIZE]; | |
ccbea45a | 729 | char *getfield(), *aabet(), *aabetlast(), *fullaabet(), *astro(); |
db589048 GL |
730 | |
731 | getfield("F", field, ref); | |
732 | if (field[0] != 0) | |
733 | for (p = field; *p; p++) | |
734 | *cp++ = *p; | |
735 | else { | |
736 | p = citetemplate; | |
737 | field[0] = 0; | |
738 | while (c = *p++) { | |
739 | if (isalpha(c)) { /* field name */ | |
740 | q = getfield(p-1, field, ref); | |
741 | if (q != 0) { | |
742 | p = q; | |
743 | for (fp = field; *fp; ) | |
744 | *cp++ = *fp++; | |
745 | } | |
746 | } | |
747 | else if (c == '1') { /* numeric order */ | |
748 | sprintf(field,"%d",1 + i); | |
749 | for (fp = field; *fp; ) | |
750 | *cp++ = *fp++; | |
751 | } | |
752 | else if (c == '2') /* alternate alphabetic */ | |
753 | cp = aabet(cp, ref); | |
754 | else if (c == '3') /* Astrophysical Journal style*/ | |
755 | cp = astro(cp, ref); | |
ccbea45a GL |
756 | else if (c == '8') /* Full alphabetic */ |
757 | cp = fullaabet(cp, ref); | |
30ec19d9 RH |
758 | else if (c == '9') /* Last name of Senior Author*/ |
759 | cp = aabetlast(cp, ref); | |
4e880a3e RH |
760 | else if (c == '0') { /* print nothing */ |
761 | for (fp = field; *fp; ) | |
762 | *cp++ = *fp++; | |
763 | } | |
db589048 GL |
764 | /* else if (c == '4') here is how to add new styles */ |
765 | else if (c == '{') { /* other information */ | |
766 | while (*p != '}') | |
767 | if (*p == 0) | |
768 | error("unexpected end of citation template"); | |
769 | else | |
770 | *cp++ = *p++; | |
771 | p++; | |
772 | } | |
773 | else if (c == '<') { | |
774 | while (*p != '>') { | |
775 | if (*p == 0) | |
776 | error("unexpected end of citation template"); | |
777 | else | |
778 | *cp++ = *p++; | |
779 | } | |
780 | p++; | |
781 | } | |
782 | else if (c != '@') | |
783 | *cp++ = c; | |
784 | } | |
785 | } | |
786 | *cp++ = 0; | |
787 | } | |
788 | ||
789 | /* alternate alphabetic citation style - | |
790 | if 1 author - first three letters of last name | |
791 | if 2 authors - first two letters of first, followed by first letter of | |
792 | seond | |
793 | if 3 or more authors - first letter of first three authors */ | |
794 | char *aabet(cp, ref) | |
795 | char *cp, ref[]; | |
dca84ce7 RH |
796 | { char field[REFSIZE], temp[100]; |
797 | reg char *np, *fp; | |
db589048 GL |
798 | int j, getname(); |
799 | ||
800 | if (getname(1, field, temp, ref)) { | |
801 | np = cp; | |
802 | fp = field; | |
803 | for (j = 1; j <= 3; j++) | |
804 | if (*fp != 0) | |
805 | *cp++ = *fp++; | |
806 | if (getname(2, field, temp, ref)) | |
807 | np[2] = field[0]; | |
808 | if (getname(3, field, temp, ref)) { | |
809 | np[1] = np[2]; | |
810 | np[2] = field[0]; | |
811 | } | |
812 | } | |
813 | return(cp); | |
814 | } | |
815 | ||
ccbea45a GL |
816 | /* alternate alphabetic citation style - |
817 | first two characters of last names of all authors | |
818 | up to max_klen characters. | |
819 | */ | |
820 | char *fullaabet(cp, ref) | |
821 | char *cp, ref[]; | |
822 | { char field[REFSIZE], temp[100]; | |
823 | reg char *fp; | |
824 | char *lastcp; | |
825 | int getname(); | |
826 | int i; | |
827 | ||
828 | lastcp = cp + max_klen; | |
829 | for (i= 1; getname(i, field, temp, ref); i++) { | |
830 | for (fp = field; *fp && (fp < &(field[3])); ) | |
831 | if (cp > lastcp) | |
832 | break; | |
833 | else if (isalpha(*fp)) | |
834 | *cp++ = *fp++; | |
835 | else | |
836 | fp++; | |
837 | } | |
838 | return(cp); | |
839 | } | |
840 | ||
841 | ||
30ec19d9 RH |
842 | /* alternate alphabetic citation style - |
843 | entire last name of senior author | |
844 | */ | |
845 | char *aabetlast(cp, ref) | |
846 | char *cp, ref[]; | |
847 | { char field[REFSIZE], temp[100]; | |
dca84ce7 | 848 | reg char *fp; |
30ec19d9 RH |
849 | int getname(); |
850 | ||
851 | if (getname(1, field, temp, ref)) { | |
852 | for (fp = field; *fp; ) | |
853 | *cp++ = *fp++; | |
854 | } | |
855 | return(cp); | |
856 | } | |
857 | ||
db589048 GL |
858 | /* Astrophysical Journal style |
859 | if 1 author - last name date | |
860 | if 2 authors - last name and last name date | |
861 | if 3 authors - last name, last name and last name date | |
862 | if 4 or more authors - last name et al. date */ | |
863 | char *astro(cp, ref) | |
864 | char *cp, ref[]; | |
dca84ce7 RH |
865 | { char name1[100], name2[100], name3[100], temp[100]; |
866 | reg char *fp; | |
db589048 GL |
867 | int getname(); |
868 | ||
869 | if (getname(1, name1, temp, ref)) { | |
870 | for (fp = name1; *fp; ) | |
871 | *cp++ = *fp++; | |
872 | if (getname(4, name3, temp, ref)) { | |
873 | for (fp = " et al."; *fp; ) | |
874 | *cp++ = *fp++; | |
875 | } | |
876 | else if (getname(2, name2, temp, ref)) { | |
877 | if (getname(3, name3, temp, ref)) { | |
878 | for (fp = "\\*(c]"; *fp; ) | |
879 | *cp++ = *fp++; | |
880 | for (fp = name2; *fp; ) | |
881 | *cp++ = *fp++; | |
882 | for (fp = "\\*(m]"; *fp; ) | |
883 | *cp++ = *fp++; | |
884 | for (fp = name3; *fp; ) | |
885 | *cp++ = *fp++; | |
886 | } | |
887 | else { | |
888 | for (fp = "\\*(n]"; *fp; ) | |
889 | *cp++ = *fp++; | |
890 | for (fp = name2; *fp; ) | |
891 | *cp++ = *fp++; | |
892 | } | |
893 | } | |
894 | } | |
895 | return(cp); | |
896 | } | |
897 | ||
898 | /* getfield - get a single field from reference */ | |
899 | char *getfield(ptr, field, ref) | |
900 | char *ptr, field[], ref[]; | |
dca84ce7 RH |
901 | { reg char *p, *q; |
902 | char temp[100]; | |
db589048 GL |
903 | int n, len, i, getname(); |
904 | ||
905 | field[0] = 0; | |
906 | if (*ptr == 'A') | |
907 | getname(1, field, temp, ref); | |
908 | else | |
909 | for (p = ref; *p; p++) | |
910 | if (*p == '%' && *(p+1) == *ptr) { | |
911 | for (p = p + 2; *p == ' '; p++) | |
912 | ; | |
913 | for (q = field; (*p != '\n') && (*p != '\0'); ) | |
914 | *q++ = *p++; | |
915 | *q = 0; | |
916 | break; | |
917 | } | |
918 | n = 0; | |
919 | len = strlen(field); | |
920 | if (*++ptr == '-') { | |
921 | for (ptr++; isdigit(*ptr); ptr++) | |
922 | n = 10 * n + (*ptr - '0'); | |
923 | if (n > len) | |
924 | n = 0; | |
925 | else | |
926 | n = len - n; | |
927 | for (i = 0; field[i] = field[i+n]; i++) | |
928 | ; | |
929 | } | |
930 | else if (isdigit(*ptr)) { | |
931 | for (; isdigit(*ptr); ptr++) | |
932 | n = 10 * n + (*ptr - '0'); | |
933 | if (n > len) | |
934 | n = len; | |
935 | field[n] = 0; | |
936 | } | |
937 | ||
938 | if (*ptr == 'u') { | |
939 | ptr++; | |
940 | for (p = field; *p; p++) | |
941 | if (islower(*p)) | |
942 | *p = (*p - 'a') + 'A'; | |
943 | } | |
944 | else if (*ptr == 'l') { | |
945 | ptr++; | |
946 | for (p = field; *p; p++) | |
947 | if (isupper(*p)) | |
948 | *p = (*p - 'A') + 'a'; | |
949 | } | |
950 | return(ptr); | |
951 | } | |
952 | ||
953 | /* getname - get the nth name field from reference, breaking into | |
954 | first and last names */ | |
955 | int getname(n, last, first, ref) | |
956 | int n; | |
957 | char last[], first[], ref[]; | |
dca84ce7 | 958 | { reg char *p; |
db589048 GL |
959 | int m; |
960 | ||
961 | m = n; | |
962 | for (p = ref; *p; p++) | |
963 | if (*p == '%' & *(p+1) == 'A') { | |
964 | n--; | |
965 | if (n == 0) { | |
966 | for (p = p + 2; *p == ' '; p++) ; | |
967 | breakname(p, first, last) ; | |
968 | return(true); | |
969 | } | |
970 | } | |
971 | ||
972 | if (n == m) /* no authors, try editors */ | |
973 | for (p = ref; *p; p++) | |
974 | if (*p == '%' & *(p+1) == 'E') { | |
975 | n--; | |
976 | if (n == 0) { | |
977 | for (p = p + 2; *p == ' '; p++) ; | |
978 | breakname(p, first, last) ; | |
979 | return(true); | |
980 | } | |
981 | } | |
982 | ||
983 | if (n == m) { /* no editors, either, try institution */ | |
984 | first[0] = last[0] = '\0'; | |
985 | getfield("I", last, ref); | |
986 | if (last[0] != '\0') | |
987 | return(true); | |
988 | } | |
989 | ||
990 | return(false); | |
991 | } | |
992 | ||
993 | /* disambiguate - compare adjacent citation strings, and if equal, add | |
994 | single character disambiguators */ | |
995 | disambiguate() | |
dca84ce7 | 996 | { reg int i, j; |
20e80ec2 | 997 | char adstr; |
db589048 | 998 | |
a486c0ef | 999 | for (i = 0; i < numrefs-1; i = j) { |
db589048 | 1000 | j = i + 1; |
dca84ce7 | 1001 | if (strcmp(refinfo[i].ri_cite, refinfo[j].ri_cite)==0) { |
20e80ec2 | 1002 | adstr = 'a'; |
a486c0ef GL |
1003 | for(j = i+1; |
1004 | j<numrefs && strcmp(refinfo[i].ri_cite,refinfo[j].ri_cite) == 0; | |
1005 | j++) { | |
20e80ec2 | 1006 | adstr = 'a' + (j-i); |
20e80ec2 | 1007 | refinfo[j].ri_disambig[0] = adstr; |
db589048 | 1008 | } |
20e80ec2 | 1009 | refinfo[i].ri_disambig[0] = 'a'; |
db589048 GL |
1010 | } |
1011 | } | |
20e80ec2 RH |
1012 | for (i = 0; i < numrefs; i++){ |
1013 | strcat(refinfo[i].ri_cite, refinfo[i].ri_disambig); | |
1014 | } | |
db589048 GL |
1015 | } |
1016 | ||
1017 | ||
f0a950c2 GL |
1018 | /* bldname - build a name field |
1019 | doing abbreviations, reversals, and caps/small caps | |
1020 | */ | |
1021 | bldname(first, last, name, reverse) | |
1022 | char *first, *last, name[]; | |
1023 | int reverse; | |
1024 | { | |
dca84ce7 RH |
1025 | char newfirst[120], newlast[120]; |
1026 | reg char *p, *q, *f, *l; | |
1027 | char *scopy(); | |
f0a950c2 GL |
1028 | int flag; |
1029 | ||
1030 | if (abbrev) { | |
1031 | p = first; | |
1032 | q = newfirst; | |
1033 | flag = false; | |
1034 | while (*p) { | |
1035 | while (*p == ' ') | |
1036 | p++; | |
1037 | if (*p == 0) | |
1038 | break; | |
1039 | if (isupper(*p)) { | |
db589048 | 1040 | if (flag) /* between initial gap */ |
f0a950c2 GL |
1041 | q = scopy(q, "\\*(a]"); |
1042 | flag = true; | |
1043 | *q++ = *p; | |
db589048 | 1044 | q = scopy(q, "\\*(p]"); |
f0a950c2 GL |
1045 | } |
1046 | if (*++p == '.') | |
1047 | p++; | |
1048 | else while (*p != 0 && ! isspace(*p)) | |
1049 | p++; | |
1050 | } | |
1051 | *q = 0; | |
1052 | f = newfirst; | |
1053 | } | |
1054 | else | |
1055 | f = first; | |
1056 | ||
1057 | if (capsmcap) { | |
1058 | p = last; | |
1059 | q = newlast; | |
1060 | flag = 0; /* 1 - printing cap, 2 - printing small */ | |
1061 | while (*p) | |
1062 | if (islower(*p)) { | |
1063 | if (flag != 2) | |
1064 | q = scopy(q, "\\s-2"); | |
1065 | flag = 2; | |
1066 | *q++ = (*p++ - 'a') + 'A'; | |
1067 | } | |
1068 | else { | |
1069 | if (flag == 2) | |
1070 | q = scopy(q,"\\s+2"); | |
1071 | flag = 1; | |
1072 | *q++ = *p++; | |
1073 | } | |
1074 | if (flag == 2) | |
1075 | q = scopy(q, "\\s+2"); | |
1076 | *q = 0; | |
1077 | l = newlast; | |
1078 | } | |
1079 | else | |
1080 | l = last; | |
1081 | ||
db589048 GL |
1082 | if (f[0] == 0) |
1083 | sprintf(name, "%s\n", l); | |
1084 | else if (reverse) | |
1085 | sprintf(name, "%s\\*(b]%s\n", l, f); | |
f0a950c2 GL |
1086 | else |
1087 | sprintf(name, "%s %s\n", f, l); | |
1088 | } | |
1089 | ||
1090 | /* prtauth - print author or editor field */ | |
1091 | prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev) | |
1092 | char c, *line; | |
1093 | int num, max, abbrev, capsmcap, numrev; | |
1094 | FILE *ofd; | |
1095 | { char first[LINELENGTH], last[LINELENGTH]; | |
1096 | ||
1097 | if (num <= numrev || abbrev || capsmcap) { | |
1098 | breakname(line, first, last); | |
1099 | bldname(first, last, line, num <= numrev); | |
1100 | } | |
1101 | if (num == 1) | |
1102 | fprintf(ofd,".ds [%c %s", c, line); | |
1103 | else if (num < max) | |
1104 | fprintf(ofd,".as [%c \\*(c]%s", c, line); | |
1105 | else if (max == 2) | |
1106 | fprintf(ofd,".as [%c \\*(n]%s", c, line); | |
1107 | else | |
1108 | fprintf(ofd,".as [%c \\*(m]%s", c, line); | |
1109 | if (num == max && index(trailstr, c)) | |
1110 | fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]); | |
1111 | } | |
1112 | ||
1113 | /* doline - actually print out a line of reference information */ | |
1114 | doline(c, line, numauths, maxauths, numeds, maxeds, ofd) | |
1115 | char c, *line; | |
1116 | int numauths, maxauths, numeds, maxeds; | |
1117 | FILE *ofd; | |
1118 | { | |
1119 | ||
1120 | switch(c) { | |
1121 | case 'A': | |
1122 | prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev); | |
1123 | break; | |
1124 | ||
1125 | case 'E': | |
1126 | prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, ednumrev); | |
1127 | if (numeds == maxeds) | |
1128 | fprintf(ofd,".nr [E %d\n", maxeds); | |
1129 | break; | |
1130 | ||
1131 | case 'P': | |
1132 | if (index(line, '-')) | |
1133 | fprintf(ofd,".nr [P 1\n"); | |
1134 | else | |
1135 | fprintf(ofd,".nr [P 0\n"); | |
1136 | fprintf(ofd,".ds [P %s",line); | |
1137 | if (index(trailstr, 'P')) | |
1138 | fprintf(ofd,".ds ]P %c\n",line[strlen(line)-2]); | |
1139 | break; | |
1140 | ||
1141 | case 'F': | |
1142 | case 'K': break; | |
1143 | ||
1144 | default: | |
1145 | fprintf(ofd,".ds [%c %s", c, line); | |
1146 | if (index(trailstr, c)) | |
1147 | fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]); | |
1148 | } | |
1149 | } | |
1150 | ||
db589048 GL |
1151 | /* dumpref - dump reference number i */ |
1152 | dumpref(i, ofd) | |
1153 | int i; | |
1154 | FILE *ofd; | |
dca84ce7 RH |
1155 | { char ref[REFSIZE], line[REFSIZE]; |
1156 | reg char *p, *q; | |
1157 | char *from; | |
db589048 GL |
1158 | int numauths, maxauths, numeds, maxeds; |
1159 | ||
dca84ce7 | 1160 | rdref(&refinfo[i], ref); |
db589048 GL |
1161 | maxauths = maxeds = 0; |
1162 | numauths = numeds = 0; | |
1163 | for (p = ref; *p; p++) | |
1164 | if (*p == '%') | |
1165 | if (*(p+1) == 'A') maxauths++; | |
1166 | else if (*(p+1) == 'E') maxeds++; | |
1167 | fprintf(ofd, ".[-\n"); | |
dca84ce7 RH |
1168 | fprintf(ofd, ".ds [F %s\n", refinfo[i].ri_cite); |
1169 | #ifndef INCORE | |
1170 | fseek(rfd, (long)refinfo[i].ri_pos, 0); | |
db589048 | 1171 | while (fgets(line, REFSIZE, rfd) != NULL) { |
dca84ce7 RH |
1172 | #else INCORE |
1173 | for (q = line, from = refinfo[i].ri_ref; *from; /*VOID*/) { /*} */ | |
1174 | if (*from == '\n'){ | |
1175 | *q++ = '\n'; | |
1176 | *q = 0; | |
1177 | q = line; | |
1178 | from++; | |
1179 | } else { | |
1180 | *q++ = *from++; | |
1181 | continue; | |
1182 | } | |
1183 | #endif INCORE | |
1184 | switch(line[0]){ | |
1185 | case 0: | |
1186 | goto doneref; | |
1187 | case '.': | |
1188 | fprintf(ofd, "%s", line); | |
1189 | break; | |
1190 | case '%': | |
1191 | switch(line[1]){ | |
1192 | case 'A': numauths++; break; | |
1193 | case 'E': numeds++; break; | |
1194 | } | |
1195 | for (p = &line[2]; *p == ' '; p++) /*VOID*/; | |
1196 | doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd); | |
1197 | } | |
1198 | } | |
1199 | doneref:; | |
db589048 GL |
1200 | fprintf(ofd,".][\n"); |
1201 | } |