Annotation of 43BSDReno/usr.bin/refer/sortbib/sortbib.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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