# 2.11BSD#431 - /usr/src/usr.bin/refer/sortbib.c

##### Functions

    article           X
    deliver           X
    endcomma          X
    error             X
    eval              X
    main              X
    onintr            X
    parse             X
    sortbib           X

##### Variables

    keystr            X
    multauth          X
    oneauth           X
    rsmode            X
    tempfile          X

##### Macros

    BUF               X
    MXFILES           X

       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: }

#### Defined functions

article defined in line 221; used 1 times

- in line 205

deliver defined in line 131; used 1 times

- in line 53

endcomma defined in line 278; used 1 times

- in line 185

error defined in line 264; used 9 times

- in line 43, 49, 104, 127, 142, 148-154(3), 160

eval defined in line 247; used 1 times

- in line 32

main defined in line 15; never used
onintr defined in line 271; used 2 times

- in line 20, 47

parse defined in line 164; used 1 times

- in line 111

sortbib defined in line 60; used 1 times

- in line 51

#### Defined variables

keystr defined in line 11; used 11 times

- in line 31-32(2), 177, 215, 247-261(7)

multauth defined in line 12; used 2 times

- in line 181, 256

oneauth defined in line 13; used 4 times

- in line 107, 181-183(2), 194

rsmode defined in line 58; used 7 times

- in line 75-84(6), 156

sccsid defined in line 2; never used
tempfile defined in line 10; used 11 times

- in line 44-54(5), 104, 127, 140-143(3), 274

#### Defined macros

BUF defined in line 7; used 11 times

- in line 66-69(3), 91-95(2), 115-118(2), 134(2), 166-168(2)

MXFILES defined in line 8; used 3 times

- in line 19, 35-38(2)

Last modified: 1987-02-17 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1033 |