Annotation of 42BSD/usr.bin/refer/sortbib.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char *sccsid = "@(#)sortbib.c   4.1 (Berkeley) 5/6/83";
                      3: #endif
                      4: 
                      5: #include <stdio.h>
                      6: #include <signal.h>
                      7: #define BUF BUFSIZ
                      8: #define MXFILES 16
                      9: 
                     10: char *tempfile;                        /* temporary file for sorting keys */
                     11: char *keystr = "AD";           /* default sorting on author and date */
                     12: int multauth = 0;              /* by default sort on senior author only */
                     13: int oneauth;                   /* has there been author in the record? */
                     14: 
                     15: main(argc, argv)       /* sortbib: sort bibliographic database in place */
                     16: int argc;
                     17: char *argv[];
                     18: {
                     19:        FILE *fp[MXFILES], *tfp, *fopen();
                     20:        int i, onintr();
                     21:        char *mktemp();
                     22: 
                     23:        if (argc == 1)          /* can't use stdin for seeking anyway */
                     24:        {
                     25:                puts("Usage:  sortbib [-sKEYS] database [...]");
                     26:                puts("\t-s: sort by fields in KEYS (default is AD)");
                     27:                exit(1);
                     28:        }
                     29:        if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 's')
                     30:        {
                     31:                keystr = argv[1]+2;
                     32:                eval(keystr);           /* evaluate A+ for multiple authors */
                     33:                argv++; argc--;
                     34:        }
                     35:        if (argc > MXFILES+1)   /* too many open file streams */
                     36:        {
                     37:                fprintf(stderr,
                     38:                "sortbib: More than %d databases specified\n", MXFILES);
                     39:                exit(1);
                     40:        }
                     41:        for (i = 1; i < argc; i++)              /* open files in arg list */
                     42:                if ((fp[i-1] = fopen(argv[i], "r")) == NULL)
                     43:                        error(argv[i]);
                     44:        tempfile = "/tmp/SbibXXXXX";            /* tempfile for sorting keys */
                     45:        mktemp(tempfile);
                     46:        if (signal(SIGINT,SIG_IGN) != SIG_IGN)  /* remove if interrupted */
                     47:                signal(SIGINT, onintr);
                     48:        if ((tfp = fopen(tempfile, "w")) == NULL)
                     49:                error(tempfile);
                     50:        for (i = 0; i < argc-1; i++)            /* read keys from bib files */
                     51:                sortbib(fp[i], tfp, i);
                     52:        fclose(tfp);
                     53:        deliver(fp, tfp);       /* do disk seeks and read from biblio files */
                     54:        unlink(tempfile);
                     55:        exit(0);
                     56: }
                     57: 
                     58: int rsmode = 0;                /* record separator: 1 = null line, 2 = bracket */
                     59: 
                     60: sortbib(fp, tfp, i)    /* read records, prepare list for sorting */
                     61: FILE *fp, *tfp;
                     62: int i;
                     63: {
                     64:        long offset, lastoffset = 0, ftell();   /* byte offsets in file */
                     65:        int length, newrec, recno = 0;          /* reclen, new rec'd?, number */
                     66:        char line[BUF], fld[4][BUF];            /* one line, the sort fields */
                     67: 
                     68:        /* measure byte offset, then get new line */
                     69:        while (offset = ftell(fp), fgets(line, BUF, fp))
                     70:        {
                     71:                if (recno == 0)         /* accept record w/o initial newline */
                     72:                        newrec = 1;
                     73:                if (line[0] == '\n')    /* accept null line record separator */
                     74:                {
                     75:                        if (!rsmode)
                     76:                                rsmode = 1;     /* null line mode */
                     77:                        if (rsmode == 1)
                     78:                                newrec = 1;
                     79:                }
                     80:                if (line[0] == '.' && line[1] == '[')   /* also accept .[ .] */
                     81:                {
                     82:                        if (!rsmode)
                     83:                                rsmode = 2;     /* bracket pair mode */
                     84:                        if (rsmode == 2)
                     85:                                newrec = 1;
                     86:                }
                     87:                if (newrec)             /* by whatever means above */
                     88:                {
                     89:                        newrec = 0;
                     90:                        length = offset - lastoffset;   /* measure rec len */
                     91:                        if (length > BUF*8)
                     92:                        {
                     93:                                fprintf(stderr,
                     94:                                "sortbib: record %d longer than %d (%d)\n",
                     95:                                        recno, BUF*8, length);
                     96:                                exit(1);
                     97:                        }
                     98:                        if (recno++)                    /* info for sorting */
                     99:                        {
                    100:                                fprintf(tfp, "%d %D %d : %s %s %s %s\n",
                    101:                                        i, lastoffset, length,
                    102:                                        fld[0], fld[1], fld[2], fld[3]);
                    103:                                if (ferror(tfp))
                    104:                                        error(tempfile);
                    105:                        }
                    106:                        *fld[0] = *fld[1] = *fld[2] = *fld[3] = NULL;
                    107:                        oneauth = 0;            /* reset number of authors */
                    108:                        lastoffset = offset;    /* save for next time */
                    109:                }
                    110:                if (line[0] == '%')     /* parse out fields to be sorted */
                    111:                        parse(line, fld);
                    112:        }
                    113:        offset = ftell(fp);             /* measure byte offset at EOF */
                    114:        length = offset - lastoffset;   /* measure final record length */
                    115:        if (length > BUF*8)
                    116:        {
                    117:                fprintf(stderr, "sortbib: record %d longer than %d (%d)\n",
                    118:                        recno, BUF*8, length);
                    119:                exit(1);
                    120:        }
                    121:        if (line[0] != '\n')            /* ignore null line just before EOF */
                    122:        {
                    123:                fprintf(tfp, "%d %D %d : %s %s %s %s\n",
                    124:                        i, lastoffset, length,
                    125:                        fld[0], fld[1], fld[2], fld[3]);
                    126:                if (ferror(tfp))
                    127:                        error(tempfile);        /* disk error in /tmp */
                    128:        }
                    129: }
                    130: 
                    131: deliver(fp, tfp)       /* deliver sorted entries out of database(s) */
                    132: FILE *fp[], *tfp;
                    133: {
                    134:        char str[BUF], buff[BUF*8];     /* for tempfile & databases */
                    135:        char cmd[80], *sprintf();       /* for using system sort command */
                    136:        long int offset;
                    137:        int i, length;
                    138: 
                    139:        /* when sorting, ignore case distinctions; tab char is ':' */
                    140:        sprintf(cmd, "sort -ft: +1 %s -o %s", tempfile, tempfile);
                    141:        if (system(cmd) == 127)
                    142:                error("sortbib");
                    143:        tfp = fopen(tempfile, "r");
                    144:        while (fgets(str, sizeof(str), tfp))
                    145:        {
                    146:                /* get file pointer, record offset, and length */
                    147:                if (sscanf(str, "%d %D %d :", &i, &offset, &length) != 3)
                    148:                        error("sortbib: sorting error");
                    149:                /* seek to proper disk location in proper file */
                    150:                if (fseek(fp[i], offset, 0) == -1)
                    151:                        error("sortbib");
                    152:                /* read exactly one record from bibliography */
                    153:                if (fread(buff, sizeof(*buff), length, fp[i]) == 0)
                    154:                        error("sortbib");
                    155:                /* add newline between unseparated records */
                    156:                if (buff[0] != '\n' && rsmode == 1)
                    157:                        putchar('\n');
                    158:                /* write record buffer to standard output */
                    159:                if (fwrite(buff, sizeof(*buff), length, stdout) == 0)
                    160:                        error("sortbib");
                    161:        }
                    162: }
                    163: 
                    164: parse(line, fld)       /* get fields out of line, prepare for sorting */
                    165: char line[];
                    166: char fld[][BUF];
                    167: {
                    168:        char wd[8][BUF/4], *strcat();
                    169:        int n, i, j;
                    170: 
                    171:        for (i = 0; i < 8; i++)         /* zap out old strings */
                    172:                *wd[i] = NULL;
                    173:        n = sscanf(line, "%s %s %s %s %s %s %s %s",
                    174:                wd[0], wd[1], wd[2], wd[3], wd[4], wd[5], wd[6], wd[7]);
                    175:        for (i = 0; i < 4; i++)
                    176:        {
                    177:                if (wd[0][1] == keystr[i])
                    178:                {
                    179:                        if (wd[0][1] == 'A')
                    180:                        {
                    181:                                if (oneauth && !multauth)       /* no repeat */
                    182:                                        break;
                    183:                                else if (oneauth)               /* mult auths */
                    184:                                        strcat(fld[i], "~~");
                    185:                                if (!endcomma(wd[n-2]))         /* surname */
                    186:                                        strcat(fld[i], wd[n-1]);
                    187:                                else {                          /* jr. or ed. */
                    188:                                        strcat(fld[i], wd[n-2]);
                    189:                                        n--;
                    190:                                }
                    191:                                strcat(fld[i], " ");
                    192:                                for (j = 1; j < n-1; j++)
                    193:                                        strcat(fld[i], wd[j]);
                    194:                                oneauth = 1;
                    195:                        }
                    196:                        else if (wd[0][1] == 'D')
                    197:                        {
                    198:                                strcat(fld[i], wd[n-1]);        /* year */
                    199:                                if (n > 2)
                    200:                                        strcat(fld[i], wd[1]);  /* month */
                    201:                        }
                    202:                        else if (wd[0][1] == 'T' || wd[0][1] == 'J')
                    203:                        {
                    204:                                j = 1;
                    205:                                if (article(wd[1]))     /* skip article */
                    206:                                        j++;
                    207:                                for (; j < n; j++)
                    208:                                        strcat(fld[i], wd[j]);
                    209:                        }
                    210:                        else  /* any other field */
                    211:                                for (j = 1; j < n; j++)
                    212:                                        strcat(fld[i], wd[j]);
                    213:                }
                    214:                /* %Q quorporate or queer author - unreversed %A */
                    215:                else if (wd[0][1] == 'Q' && keystr[i] == 'A')
                    216:                        for (j = 1; j < n; j++)
                    217:                                strcat(fld[i], wd[j]);
                    218:        }
                    219: }
                    220: 
                    221: article(str)           /* see if string contains an article */
                    222: char *str;
                    223: {
                    224:        if (strcmp("The", str) == 0)    /* English */
                    225:                return(1);
                    226:        if (strcmp("A", str) == 0)
                    227:                return(1);
                    228:        if (strcmp("An", str) == 0)
                    229:                return(1);
                    230:        if (strcmp("Le", str) == 0)     /* French */
                    231:                return(1);
                    232:        if (strcmp("La", str) == 0)
                    233:                return(1);
                    234:        if (strcmp("Der", str) == 0)    /* German */
                    235:                return(1);
                    236:        if (strcmp("Die", str) == 0)
                    237:                return(1);
                    238:        if (strcmp("Das", str) == 0)
                    239:                return(1);
                    240:        if (strcmp("El", str) == 0)     /* Spanish */
                    241:                return(1);
                    242:        if (strcmp("Den", str) == 0)    /* Scandinavian */
                    243:                return(1);
                    244:        return(0);
                    245: }
                    246: 
                    247: eval(keystr)           /* evaluate key string for A+ marking */
                    248: char keystr[];
                    249: {
                    250:        int i, j;
                    251: 
                    252:        for (i = 0, j = 0; keystr[i]; i++, j++)
                    253:        {
                    254:                if (keystr[i] == '+')
                    255:                {
                    256:                        multauth = 1;
                    257:                        i++;
                    258:                }
                    259:                keystr[j] = keystr[i];
                    260:        }
                    261:        keystr[j] = NULL;
                    262: }
                    263: 
                    264: error(s)               /* exit in case of various system errors */
                    265: char *s;
                    266: {
                    267:        perror(s);
                    268:        exit(1);
                    269: }
                    270: 
                    271: onintr()               /* remove tempfile in case of interrupt */
                    272: {
                    273:        fprintf(stderr, "\nInterrupt\n");
                    274:        unlink(tempfile);
                    275:        exit(1);
                    276: }
                    277: 
                    278: endcomma(str)
                    279: char *str;
                    280: {
                    281:        int n;
                    282: 
                    283:        n = strlen(str) - 1;
                    284:        if (str[n] == ',')
                    285:        {
                    286:                str[n] = NULL;
                    287:                return(1);
                    288:        }
                    289:        return(0);
                    290: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.