113110Srrh #ifndef lint 2*15061Sgarrison static char sccsid[] = "@(#)bibargs.c 2.2 09/23/83"; 313110Srrh #endif not lint 4*15061Sgarrison /* 5*15061Sgarrison Authored by: Tim Budd, University of Arizona, 1983. 6*15061Sgarrison version 7/4/83 713110Srrh 8*15061Sgarrison Various modifications suggested by: 9*15061Sgarrison David Cherveny - Duke University Medical Center 10*15061Sgarrison Phil Garrison - UC Berkeley 11*15061Sgarrison M. J. Hawley - Yale University 12*15061Sgarrison 13*15061Sgarrison 14*15061Sgarrison 15*15061Sgarrison 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 */ 26*15061Sgarrison char bibfname[120]; /* file name currently being read */ 27*15061Sgarrison 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; 49*15061Sgarrison /* reference file information */ 50*15061Sgarrison extern long int refspos[]; 51*15061Sgarrison extern char reffile[]; 52*15061Sgarrison extern FILE *rfd; 53*15061Sgarrison extern char *citestr[]; 54*15061Sgarrison 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 81*15061Sgarrison case 'a': for (p = &argv[i][2]; *p; p++) 82*15061Sgarrison 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 152*15061Sgarrison 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 163*15061Sgarrison case 't': style = false; /* fall through */ 164*15061Sgarrison 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 173*15061Sgarrison 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 } 180*15061Sgarrison 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 { 200*15061Sgarrison 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; 216*15061Sgarrison char *p, line[LINELENGTH], dline[LINELENGTH], word[80], *tfgets(); 217*15061Sgarrison int i, j, getwrd(); 21812910Sgarrison 219*15061Sgarrison strcpy(bibfname, np); 22012910Sgarrison fd = fopen(np, "r"); 22112910Sgarrison if (fd == NULL && *np != '/') { 22212910Sgarrison strcpy(name, "bib."); 22312910Sgarrison strcat(name, np); 224*15061Sgarrison 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); 231*15061Sgarrison strcpy(bibfname, name); 23212910Sgarrison fd = fopen(name, "r"); 23312910Sgarrison } 23412910Sgarrison if (fd == NULL) { 235*15061Sgarrison bibwarning("%s: can't open", np); 236*15061Sgarrison exit(1); 23712910Sgarrison } 23812910Sgarrison 239*15061Sgarrison /* now go off and process file */ 240*15061Sgarrison biblineno = 1; 241*15061Sgarrison while (tfgets(line, LINELENGTH, fd) != NULL) { 242*15061Sgarrison biblineno++; 24312910Sgarrison switch(line[0]) { 24412910Sgarrison 24512910Sgarrison case '#': break; 24612910Sgarrison 24712961Sgarrison case 'A': for (p = &line[1]; *p; p++) 248*15061Sgarrison 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'; 278*15061Sgarrison 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 313*15061Sgarrison 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 328*15061Sgarrison case 'X': capsmcap = true; /* this is now replace by AX */ 32912910Sgarrison break; 33012910Sgarrison 33112910Sgarrison default: fprintf(tfd,"%s\n",line); 332*15061Sgarrison while (fgets(line, LINELENGTH, fd) != NULL) 33312910Sgarrison fputs(line, tfd); 33412910Sgarrison return; 33512910Sgarrison } 336*15061Sgarrison 337*15061Sgarrison } 338*15061Sgarrison /* close up */ 339*15061Sgarrison fclose(fd); 34012910Sgarrison } 34112910Sgarrison 342*15061Sgarrison /* bibwarning - print out a warning message */ 343*15061Sgarrison bibwarning(msg, arg) 344*15061Sgarrison char *msg, *arg; 345*15061Sgarrison { 346*15061Sgarrison fprintf(stderr,"`%s', line %d: ", bibfname, biblineno); 347*15061Sgarrison fprintf(stderr, msg, arg); 348*15061Sgarrison } 349*15061Sgarrison 350*15061Sgarrison /* error - report unrecoverable error message */ 351*15061Sgarrison error(str) 352*15061Sgarrison char str[]; 353*15061Sgarrison { 354*15061Sgarrison bibwarning("%s\n", str); 355*15061Sgarrison exit(1); 356*15061Sgarrison } 357*15061Sgarrison 358*15061Sgarrison #ifdef READWRITE 359*15061Sgarrison /* 360*15061Sgarrison ** fixrfd( mode ) -- re-opens the rfd file to be read or write, 361*15061Sgarrison ** depending on the mode. Uses a static int to save the current mode 362*15061Sgarrison ** and avoid unnecessary re-openings. 363*15061Sgarrison */ 364*15061Sgarrison fixrfd( mode ) 365*15061Sgarrison register int mode; 366*15061Sgarrison { 367*15061Sgarrison static int cur_mode = WRITE; /* rfd open for writing initially */ 368*15061Sgarrison 369*15061Sgarrison if (mode != cur_mode) 370*15061Sgarrison { 371*15061Sgarrison rfd = freopen(reffile, ((mode == READ)? "r" : "a"), rfd); 372*15061Sgarrison cur_mode = mode; 373*15061Sgarrison if (rfd == NULL) 374*15061Sgarrison error("Hell! Couldn't re-open reference file"); 375*15061Sgarrison } 376*15061Sgarrison } 377*15061Sgarrison #endif 378*15061Sgarrison 379*15061Sgarrison 380*15061Sgarrison /* tfgets - fgets which trims off newline */ 381*15061Sgarrison char *tfgets(line, n, ptr) 382*15061Sgarrison char line[]; 383*15061Sgarrison int n; 384*15061Sgarrison FILE *ptr; 385*15061Sgarrison { char *p; 386*15061Sgarrison 387*15061Sgarrison p = fgets(line, n, ptr); 388*15061Sgarrison if (p == NULL) 389*15061Sgarrison return(NULL); 390*15061Sgarrison else 391*15061Sgarrison for (p = line; *p; p++) 392*15061Sgarrison if (*p == '\n') 393*15061Sgarrison *p = 0; 394*15061Sgarrison return(line); 395*15061Sgarrison } 396*15061Sgarrison 397*15061Sgarrison /* getwrd - place next word from in[i] into out */ 398*15061Sgarrison int getwrd(in, i, out) 399*15061Sgarrison char in[], out[]; 400*15061Sgarrison int i; 401*15061Sgarrison { int j; 402*15061Sgarrison 403*15061Sgarrison j = 0; 404*15061Sgarrison while (in[i] == ' ' || in[i] == '\n' || in[i] == '\t') 405*15061Sgarrison i++; 406*15061Sgarrison if (in[i]) 407*15061Sgarrison while (in[i] && in[i] != ' ' && in[i] != '\t' && in[i] != '\n') 408*15061Sgarrison out[j++] = in[i++]; 409*15061Sgarrison else 410*15061Sgarrison i = 0; /* signals end of in[i..] */ 411*15061Sgarrison out[j] = 0; 412*15061Sgarrison return (i); 413*15061Sgarrison } 414*15061Sgarrison 415*15061Sgarrison /* walloc - allocate enough space for a word */ 416*15061Sgarrison char *walloc(word) 417*15061Sgarrison char *word; 418*15061Sgarrison { char *i, *malloc(); 419*15061Sgarrison i = malloc(1 + strlen(word)); 420*15061Sgarrison if (i == NULL) 421*15061Sgarrison error("out of storage"); 422*15061Sgarrison strcpy(i, word); 423*15061Sgarrison return(i); 424*15061Sgarrison } 425*15061Sgarrison 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 470*15061Sgarrison /* rdref - read text for an already cited reference */ 471*15061Sgarrison rdref(i, ref) 472*15061Sgarrison long int i; 473*15061Sgarrison char ref[REFSIZE]; 474*15061Sgarrison { 475*15061Sgarrison ref[0] = 0; 476*15061Sgarrison #ifdef READWRITE 477*15061Sgarrison fixrfd( READ ); /* fix access mode of rfd, if nec. */ 478*15061Sgarrison #endif 479*15061Sgarrison fseek(rfd, i, 0); 480*15061Sgarrison fread(ref, 1, REFSIZE, rfd); 481*15061Sgarrison } 482*15061Sgarrison 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; 496*15061Sgarrison if (q != line) { 49712910Sgarrison q++; 498*15061Sgarrison for (; isspace(*f); f--); 499*15061Sgarrison f++; 500*15061Sgarrison } 50112910Sgarrison 50212910Sgarrison /* first name is start to f, last name is q to t */ 50312910Sgarrison 504*15061Sgarrison 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; 510*15061Sgarrison 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 543*15061Sgarrison /* rcomp - reference comparison routine for qsort utility */ 544*15061Sgarrison int rcomp(ap, bp) 545*15061Sgarrison long int *ap, *bp; 546*15061Sgarrison { char ref1[REFSIZE], ref2[REFSIZE], field1[MAXFIELD], field2[MAXFIELD]; 547*15061Sgarrison char *p, *q, *getfield(); 548*15061Sgarrison int neg, res; 549*15061Sgarrison int fields_found; 550*15061Sgarrison 551*15061Sgarrison rdref(*ap, ref1); 552*15061Sgarrison rdref(*bp, ref2); 553*15061Sgarrison for (p = sortstr; *p; p = q) { 554*15061Sgarrison if (*p == '-') { 555*15061Sgarrison p++; 556*15061Sgarrison neg = true; 557*15061Sgarrison } 558*15061Sgarrison else 559*15061Sgarrison neg = false; 560*15061Sgarrison q = getfield(p, field1, ref1); 561*15061Sgarrison fields_found = true; 562*15061Sgarrison if (q == 0) { 563*15061Sgarrison res = 1; 564*15061Sgarrison fields_found = false; 565*15061Sgarrison } else if (strcmp (field1, "") == 0) { /* field not found */ 566*15061Sgarrison if (*p == 'A') { 567*15061Sgarrison getfield("F", field1, ref1); 568*15061Sgarrison if (strcmp (field1, "") == 0) { 569*15061Sgarrison getfield("I", field1, ref1); 570*15061Sgarrison if (strcmp (field1, "") == 0) { 571*15061Sgarrison res = 1; 572*15061Sgarrison fields_found = false; 573*15061Sgarrison } 574*15061Sgarrison } 575*15061Sgarrison } else { 576*15061Sgarrison res = 1; 577*15061Sgarrison fields_found = false; 578*15061Sgarrison } 579*15061Sgarrison } 580*15061Sgarrison 581*15061Sgarrison if (getfield(p, field2, ref2) == 0) { 582*15061Sgarrison res = -1; 583*15061Sgarrison fields_found = false; 584*15061Sgarrison } else if (strcmp (field2, "") == 0) { /* field not found */ 585*15061Sgarrison if (*p == 'A') { 586*15061Sgarrison getfield("F", field2, ref2); 587*15061Sgarrison if (strcmp (field2, "") == 0) { 588*15061Sgarrison getfield("I", field2, ref2); 589*15061Sgarrison if (strcmp (field2, "") == 0) { 590*15061Sgarrison res = -1; 591*15061Sgarrison fields_found = false; 592*15061Sgarrison } 593*15061Sgarrison } 594*15061Sgarrison } else { 595*15061Sgarrison res = -1; 596*15061Sgarrison fields_found = false; 597*15061Sgarrison } 598*15061Sgarrison } 599*15061Sgarrison if (fields_found) { 600*15061Sgarrison if (*p == 'A') { 601*15061Sgarrison if (isupper(field1[0])) 602*15061Sgarrison field1[0] -= 'A' - 'a'; 603*15061Sgarrison if (isupper(field2[0])) 604*15061Sgarrison field2[0] -= 'A' - 'a'; 605*15061Sgarrison } 606*15061Sgarrison res = strcmp(field1, field2); 607*15061Sgarrison } 608*15061Sgarrison if (neg) 609*15061Sgarrison res = - res; 610*15061Sgarrison if (res != 0) 611*15061Sgarrison break; 612*15061Sgarrison } 613*15061Sgarrison if (res == 0) 614*15061Sgarrison if (ap < bp) 615*15061Sgarrison res = -1; 616*15061Sgarrison else 617*15061Sgarrison res = 1; 618*15061Sgarrison return(res); 619*15061Sgarrison } 620*15061Sgarrison 621*15061Sgarrison /* makecites - make citation strings */ 622*15061Sgarrison makecites(citestr) 623*15061Sgarrison char *citestr[]; 624*15061Sgarrison { char ref[REFSIZE], tempcite[100], *malloc(); 625*15061Sgarrison int i; 626*15061Sgarrison 627*15061Sgarrison for (i = 0; i <= numrefs; i++) { 628*15061Sgarrison rdref(refspos[i], ref); 629*15061Sgarrison bldcite(tempcite, i, ref); 630*15061Sgarrison citestr[i] = malloc(2 + strlen(tempcite)); /* leave room for disambig */ 631*15061Sgarrison if (citestr[i] == NULL) 632*15061Sgarrison error("out of storage"); 633*15061Sgarrison strcpy(citestr[i], tempcite); 634*15061Sgarrison } 635*15061Sgarrison } 636*15061Sgarrison 637*15061Sgarrison /* bldcite - build a single citation string */ 638*15061Sgarrison bldcite(cp, i, ref) 639*15061Sgarrison char *cp, ref[]; 640*15061Sgarrison int i; 641*15061Sgarrison { char *p, *q, c, *fp, field[REFSIZE], *getfield(), *aabet(), *astro(); 642*15061Sgarrison 643*15061Sgarrison getfield("F", field, ref); 644*15061Sgarrison if (field[0] != 0) 645*15061Sgarrison for (p = field; *p; p++) 646*15061Sgarrison *cp++ = *p; 647*15061Sgarrison else { 648*15061Sgarrison p = citetemplate; 649*15061Sgarrison field[0] = 0; 650*15061Sgarrison while (c = *p++) { 651*15061Sgarrison if (isalpha(c)) { /* field name */ 652*15061Sgarrison q = getfield(p-1, field, ref); 653*15061Sgarrison if (q != 0) { 654*15061Sgarrison p = q; 655*15061Sgarrison for (fp = field; *fp; ) 656*15061Sgarrison *cp++ = *fp++; 657*15061Sgarrison } 658*15061Sgarrison } 659*15061Sgarrison else if (c == '1') { /* numeric order */ 660*15061Sgarrison sprintf(field,"%d",1 + i); 661*15061Sgarrison for (fp = field; *fp; ) 662*15061Sgarrison *cp++ = *fp++; 663*15061Sgarrison } 664*15061Sgarrison else if (c == '2') /* alternate alphabetic */ 665*15061Sgarrison cp = aabet(cp, ref); 666*15061Sgarrison else if (c == '3') /* Astrophysical Journal style*/ 667*15061Sgarrison cp = astro(cp, ref); 668*15061Sgarrison /* else if (c == '4') here is how to add new styles */ 669*15061Sgarrison else if (c == '{') { /* other information */ 670*15061Sgarrison while (*p != '}') 671*15061Sgarrison if (*p == 0) 672*15061Sgarrison error("unexpected end of citation template"); 673*15061Sgarrison else 674*15061Sgarrison *cp++ = *p++; 675*15061Sgarrison p++; 676*15061Sgarrison } 677*15061Sgarrison else if (c == '<') { 678*15061Sgarrison while (*p != '>') { 679*15061Sgarrison if (*p == 0) 680*15061Sgarrison error("unexpected end of citation template"); 681*15061Sgarrison else 682*15061Sgarrison *cp++ = *p++; 683*15061Sgarrison } 684*15061Sgarrison p++; 685*15061Sgarrison } 686*15061Sgarrison else if (c != '@') 687*15061Sgarrison *cp++ = c; 688*15061Sgarrison } 689*15061Sgarrison } 690*15061Sgarrison *cp++ = 0; 691*15061Sgarrison } 692*15061Sgarrison 693*15061Sgarrison /* alternate alphabetic citation style - 694*15061Sgarrison if 1 author - first three letters of last name 695*15061Sgarrison if 2 authors - first two letters of first, followed by first letter of 696*15061Sgarrison seond 697*15061Sgarrison if 3 or more authors - first letter of first three authors */ 698*15061Sgarrison char *aabet(cp, ref) 699*15061Sgarrison char *cp, ref[]; 700*15061Sgarrison { char field[REFSIZE], temp[100], *np, *fp; 701*15061Sgarrison int j, getname(); 702*15061Sgarrison 703*15061Sgarrison if (getname(1, field, temp, ref)) { 704*15061Sgarrison np = cp; 705*15061Sgarrison fp = field; 706*15061Sgarrison for (j = 1; j <= 3; j++) 707*15061Sgarrison if (*fp != 0) 708*15061Sgarrison *cp++ = *fp++; 709*15061Sgarrison if (getname(2, field, temp, ref)) 710*15061Sgarrison np[2] = field[0]; 711*15061Sgarrison if (getname(3, field, temp, ref)) { 712*15061Sgarrison np[1] = np[2]; 713*15061Sgarrison np[2] = field[0]; 714*15061Sgarrison } 715*15061Sgarrison } 716*15061Sgarrison return(cp); 717*15061Sgarrison } 718*15061Sgarrison 719*15061Sgarrison /* Astrophysical Journal style 720*15061Sgarrison if 1 author - last name date 721*15061Sgarrison if 2 authors - last name and last name date 722*15061Sgarrison if 3 authors - last name, last name and last name date 723*15061Sgarrison if 4 or more authors - last name et al. date */ 724*15061Sgarrison char *astro(cp, ref) 725*15061Sgarrison char *cp, ref[]; 726*15061Sgarrison { char name1[100], name2[100], name3[100], temp[100], *fp; 727*15061Sgarrison int getname(); 728*15061Sgarrison 729*15061Sgarrison if (getname(1, name1, temp, ref)) { 730*15061Sgarrison for (fp = name1; *fp; ) 731*15061Sgarrison *cp++ = *fp++; 732*15061Sgarrison if (getname(4, name3, temp, ref)) { 733*15061Sgarrison for (fp = " et al."; *fp; ) 734*15061Sgarrison *cp++ = *fp++; 735*15061Sgarrison } 736*15061Sgarrison else if (getname(2, name2, temp, ref)) { 737*15061Sgarrison if (getname(3, name3, temp, ref)) { 738*15061Sgarrison for (fp = "\\*(c]"; *fp; ) 739*15061Sgarrison *cp++ = *fp++; 740*15061Sgarrison for (fp = name2; *fp; ) 741*15061Sgarrison *cp++ = *fp++; 742*15061Sgarrison for (fp = "\\*(m]"; *fp; ) 743*15061Sgarrison *cp++ = *fp++; 744*15061Sgarrison for (fp = name3; *fp; ) 745*15061Sgarrison *cp++ = *fp++; 746*15061Sgarrison } 747*15061Sgarrison else { 748*15061Sgarrison for (fp = "\\*(n]"; *fp; ) 749*15061Sgarrison *cp++ = *fp++; 750*15061Sgarrison for (fp = name2; *fp; ) 751*15061Sgarrison *cp++ = *fp++; 752*15061Sgarrison } 753*15061Sgarrison } 754*15061Sgarrison } 755*15061Sgarrison return(cp); 756*15061Sgarrison } 757*15061Sgarrison 758*15061Sgarrison /* getfield - get a single field from reference */ 759*15061Sgarrison char *getfield(ptr, field, ref) 760*15061Sgarrison char *ptr, field[], ref[]; 761*15061Sgarrison { char *p, *q, temp[100]; 762*15061Sgarrison int n, len, i, getname(); 763*15061Sgarrison 764*15061Sgarrison field[0] = 0; 765*15061Sgarrison if (*ptr == 'A') 766*15061Sgarrison getname(1, field, temp, ref); 767*15061Sgarrison else 768*15061Sgarrison for (p = ref; *p; p++) 769*15061Sgarrison if (*p == '%' && *(p+1) == *ptr) { 770*15061Sgarrison for (p = p + 2; *p == ' '; p++) 771*15061Sgarrison ; 772*15061Sgarrison for (q = field; (*p != '\n') && (*p != '\0'); ) 773*15061Sgarrison *q++ = *p++; 774*15061Sgarrison *q = 0; 775*15061Sgarrison break; 776*15061Sgarrison } 777*15061Sgarrison n = 0; 778*15061Sgarrison len = strlen(field); 779*15061Sgarrison if (*++ptr == '-') { 780*15061Sgarrison for (ptr++; isdigit(*ptr); ptr++) 781*15061Sgarrison n = 10 * n + (*ptr - '0'); 782*15061Sgarrison if (n > len) 783*15061Sgarrison n = 0; 784*15061Sgarrison else 785*15061Sgarrison n = len - n; 786*15061Sgarrison for (i = 0; field[i] = field[i+n]; i++) 787*15061Sgarrison ; 788*15061Sgarrison } 789*15061Sgarrison else if (isdigit(*ptr)) { 790*15061Sgarrison for (; isdigit(*ptr); ptr++) 791*15061Sgarrison n = 10 * n + (*ptr - '0'); 792*15061Sgarrison if (n > len) 793*15061Sgarrison n = len; 794*15061Sgarrison field[n] = 0; 795*15061Sgarrison } 796*15061Sgarrison 797*15061Sgarrison if (*ptr == 'u') { 798*15061Sgarrison ptr++; 799*15061Sgarrison for (p = field; *p; p++) 800*15061Sgarrison if (islower(*p)) 801*15061Sgarrison *p = (*p - 'a') + 'A'; 802*15061Sgarrison } 803*15061Sgarrison else if (*ptr == 'l') { 804*15061Sgarrison ptr++; 805*15061Sgarrison for (p = field; *p; p++) 806*15061Sgarrison if (isupper(*p)) 807*15061Sgarrison *p = (*p - 'A') + 'a'; 808*15061Sgarrison } 809*15061Sgarrison return(ptr); 810*15061Sgarrison } 811*15061Sgarrison 812*15061Sgarrison /* getname - get the nth name field from reference, breaking into 813*15061Sgarrison first and last names */ 814*15061Sgarrison int getname(n, last, first, ref) 815*15061Sgarrison int n; 816*15061Sgarrison char last[], first[], ref[]; 817*15061Sgarrison { char *p; 818*15061Sgarrison int m; 819*15061Sgarrison 820*15061Sgarrison m = n; 821*15061Sgarrison for (p = ref; *p; p++) 822*15061Sgarrison if (*p == '%' & *(p+1) == 'A') { 823*15061Sgarrison n--; 824*15061Sgarrison if (n == 0) { 825*15061Sgarrison for (p = p + 2; *p == ' '; p++) ; 826*15061Sgarrison breakname(p, first, last) ; 827*15061Sgarrison return(true); 828*15061Sgarrison } 829*15061Sgarrison } 830*15061Sgarrison 831*15061Sgarrison if (n == m) /* no authors, try editors */ 832*15061Sgarrison for (p = ref; *p; p++) 833*15061Sgarrison if (*p == '%' & *(p+1) == 'E') { 834*15061Sgarrison n--; 835*15061Sgarrison if (n == 0) { 836*15061Sgarrison for (p = p + 2; *p == ' '; p++) ; 837*15061Sgarrison breakname(p, first, last) ; 838*15061Sgarrison return(true); 839*15061Sgarrison } 840*15061Sgarrison } 841*15061Sgarrison 842*15061Sgarrison if (n == m) { /* no editors, either, try institution */ 843*15061Sgarrison first[0] = last[0] = '\0'; 844*15061Sgarrison getfield("I", last, ref); 845*15061Sgarrison if (last[0] != '\0') 846*15061Sgarrison return(true); 847*15061Sgarrison } 848*15061Sgarrison 849*15061Sgarrison return(false); 850*15061Sgarrison } 851*15061Sgarrison 852*15061Sgarrison /* disambiguate - compare adjacent citation strings, and if equal, add 853*15061Sgarrison single character disambiguators */ 854*15061Sgarrison disambiguate() 855*15061Sgarrison { int i, j; 856*15061Sgarrison char adstr[2]; 857*15061Sgarrison 858*15061Sgarrison for (i = 0; i < numrefs; i = j) { 859*15061Sgarrison j = i + 1; 860*15061Sgarrison if (strcmp(citestr[i], citestr[j])==0) { 861*15061Sgarrison adstr[0] = 'a'; adstr[1] = 0; 862*15061Sgarrison for (j = i+1; strcmp(citestr[i],citestr[j]) == 0; j++) { 863*15061Sgarrison adstr[0] = 'a' + (j-i); 864*15061Sgarrison strcat(citestr[j], adstr); 865*15061Sgarrison if (j == numrefs) 866*15061Sgarrison break; 867*15061Sgarrison } 868*15061Sgarrison adstr[0] = 'a'; 869*15061Sgarrison strcat(citestr[i], adstr); 870*15061Sgarrison } 871*15061Sgarrison } 872*15061Sgarrison } 873*15061Sgarrison 874*15061Sgarrison 87512910Sgarrison /* bldname - build a name field 87612910Sgarrison doing abbreviations, reversals, and caps/small caps 87712910Sgarrison */ 87812910Sgarrison bldname(first, last, name, reverse) 87912910Sgarrison char *first, *last, name[]; 88012910Sgarrison int reverse; 88112910Sgarrison { 88212910Sgarrison char newfirst[120], newlast[120], *p, *q, *f, *l, *scopy(); 88312910Sgarrison int flag; 88412910Sgarrison 88512910Sgarrison if (abbrev) { 88612910Sgarrison p = first; 88712910Sgarrison q = newfirst; 88812910Sgarrison flag = false; 88912910Sgarrison while (*p) { 89012910Sgarrison while (*p == ' ') 89112910Sgarrison p++; 89212910Sgarrison if (*p == 0) 89312910Sgarrison break; 89412910Sgarrison if (isupper(*p)) { 895*15061Sgarrison if (flag) /* between initial gap */ 89612910Sgarrison q = scopy(q, "\\*(a]"); 89712910Sgarrison flag = true; 89812910Sgarrison *q++ = *p; 899*15061Sgarrison q = scopy(q, "\\*(p]"); 90012910Sgarrison } 90112910Sgarrison if (*++p == '.') 90212910Sgarrison p++; 90312910Sgarrison else while (*p != 0 && ! isspace(*p)) 90412910Sgarrison p++; 90512910Sgarrison } 90612910Sgarrison *q = 0; 90712910Sgarrison f = newfirst; 90812910Sgarrison } 90912910Sgarrison else 91012910Sgarrison f = first; 91112910Sgarrison 91212910Sgarrison if (capsmcap) { 91312910Sgarrison p = last; 91412910Sgarrison q = newlast; 91512910Sgarrison flag = 0; /* 1 - printing cap, 2 - printing small */ 91612910Sgarrison while (*p) 91712910Sgarrison if (islower(*p)) { 91812910Sgarrison if (flag != 2) 91912910Sgarrison q = scopy(q, "\\s-2"); 92012910Sgarrison flag = 2; 92112910Sgarrison *q++ = (*p++ - 'a') + 'A'; 92212910Sgarrison } 92312910Sgarrison else { 92412910Sgarrison if (flag == 2) 92512910Sgarrison q = scopy(q,"\\s+2"); 92612910Sgarrison flag = 1; 92712910Sgarrison *q++ = *p++; 92812910Sgarrison } 92912910Sgarrison if (flag == 2) 93012910Sgarrison q = scopy(q, "\\s+2"); 93112910Sgarrison *q = 0; 93212910Sgarrison l = newlast; 93312910Sgarrison } 93412910Sgarrison else 93512910Sgarrison l = last; 93612910Sgarrison 937*15061Sgarrison if (f[0] == 0) 938*15061Sgarrison sprintf(name, "%s\n", l); 939*15061Sgarrison else if (reverse) 940*15061Sgarrison sprintf(name, "%s\\*(b]%s\n", l, f); 94112910Sgarrison else 94212910Sgarrison sprintf(name, "%s %s\n", f, l); 94312910Sgarrison } 94412910Sgarrison 94512910Sgarrison /* prtauth - print author or editor field */ 94612910Sgarrison prtauth(c, line, num, max, ofd, abbrev, capsmcap, numrev) 94712910Sgarrison char c, *line; 94812910Sgarrison int num, max, abbrev, capsmcap, numrev; 94912910Sgarrison FILE *ofd; 95012910Sgarrison { char first[LINELENGTH], last[LINELENGTH]; 95112910Sgarrison 95212910Sgarrison if (num <= numrev || abbrev || capsmcap) { 95312910Sgarrison breakname(line, first, last); 95412910Sgarrison bldname(first, last, line, num <= numrev); 95512910Sgarrison } 95612910Sgarrison if (num == 1) 95712910Sgarrison fprintf(ofd,".ds [%c %s", c, line); 95812910Sgarrison else if (num < max) 95912910Sgarrison fprintf(ofd,".as [%c \\*(c]%s", c, line); 96012910Sgarrison else if (max == 2) 96112910Sgarrison fprintf(ofd,".as [%c \\*(n]%s", c, line); 96212910Sgarrison else 96312910Sgarrison fprintf(ofd,".as [%c \\*(m]%s", c, line); 96412910Sgarrison if (num == max && index(trailstr, c)) 96512910Sgarrison fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]); 96612910Sgarrison } 96712910Sgarrison 96812910Sgarrison /* doline - actually print out a line of reference information */ 96912910Sgarrison doline(c, line, numauths, maxauths, numeds, maxeds, ofd) 97012910Sgarrison char c, *line; 97112910Sgarrison int numauths, maxauths, numeds, maxeds; 97212910Sgarrison FILE *ofd; 97312910Sgarrison { 97412910Sgarrison 97512910Sgarrison switch(c) { 97612910Sgarrison case 'A': 97712910Sgarrison prtauth(c, line, numauths, maxauths, ofd, abbrev, capsmcap, numrev); 97812910Sgarrison break; 97912910Sgarrison 98012910Sgarrison case 'E': 98112910Sgarrison prtauth(c, line, numeds, maxeds, ofd, edabbrev, edcapsmcap, ednumrev); 98212910Sgarrison if (numeds == maxeds) 98312910Sgarrison fprintf(ofd,".nr [E %d\n", maxeds); 98412910Sgarrison break; 98512910Sgarrison 98612910Sgarrison case 'P': 98712910Sgarrison if (index(line, '-')) 98812910Sgarrison fprintf(ofd,".nr [P 1\n"); 98912910Sgarrison else 99012910Sgarrison fprintf(ofd,".nr [P 0\n"); 99112910Sgarrison fprintf(ofd,".ds [P %s",line); 99212910Sgarrison if (index(trailstr, 'P')) 99312910Sgarrison fprintf(ofd,".ds ]P %c\n",line[strlen(line)-2]); 99412910Sgarrison break; 99512910Sgarrison 99612910Sgarrison case 'F': 99712910Sgarrison case 'K': break; 99812910Sgarrison 99912910Sgarrison default: 100012910Sgarrison fprintf(ofd,".ds [%c %s", c, line); 100112910Sgarrison if (index(trailstr, c)) 100212910Sgarrison fprintf(ofd,".ds ]%c %c\n", c, line[strlen(line)-2]); 100312910Sgarrison } 100412910Sgarrison } 100512910Sgarrison 1006*15061Sgarrison /* dumpref - dump reference number i */ 1007*15061Sgarrison dumpref(i, ofd) 1008*15061Sgarrison int i; 1009*15061Sgarrison FILE *ofd; 1010*15061Sgarrison { char ref[REFSIZE], *p, line[REFSIZE]; 1011*15061Sgarrison int numauths, maxauths, numeds, maxeds; 1012*15061Sgarrison 1013*15061Sgarrison rdref(refspos[i], ref); 1014*15061Sgarrison maxauths = maxeds = 0; 1015*15061Sgarrison numauths = numeds = 0; 1016*15061Sgarrison for (p = ref; *p; p++) 1017*15061Sgarrison if (*p == '%') 1018*15061Sgarrison if (*(p+1) == 'A') maxauths++; 1019*15061Sgarrison else if (*(p+1) == 'E') maxeds++; 1020*15061Sgarrison fprintf(ofd, ".[-\n"); 1021*15061Sgarrison fprintf(ofd, ".ds [F %s\n",citestr[i]); 1022*15061Sgarrison fseek(rfd, (long) refspos[i], 0); 1023*15061Sgarrison while (fgets(line, REFSIZE, rfd) != NULL) { 1024*15061Sgarrison if (line[0] == 0) break; 1025*15061Sgarrison else if (line[0] == '.') fprintf(ofd,"%s",line); 1026*15061Sgarrison else { 1027*15061Sgarrison if (line[0] == '%') { 1028*15061Sgarrison for (p = &line[2]; *p == ' '; p++); 1029*15061Sgarrison if (line[1] == 'A') numauths++; 1030*15061Sgarrison else if (line[1] == 'E') numeds++; 1031*15061Sgarrison 1032*15061Sgarrison doline(line[1], p, numauths, maxauths, numeds, maxeds, ofd); 1033*15061Sgarrison } 1034*15061Sgarrison } 1035*15061Sgarrison } 1036*15061Sgarrison fprintf(ofd,".][\n"); 1037*15061Sgarrison } 1038