Annotation of 43BSDReno/games/fortune/strfile.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1989 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Ken Arnold.
                      7:  *
                      8:  * Redistribution and use in source and binary forms are permitted
                      9:  * provided that the above copyright notice and this paragraph are
                     10:  * duplicated in all such forms and that any documentation,
                     11:  * advertising materials, and other materials related to such
                     12:  * distribution and use acknowledge that the software was developed
                     13:  * by the University of California, Berkeley.  The name of the
                     14:  * University may not be used to endorse or promote products derived
                     15:  * from this software without specific prior written permission.
                     16:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     19:  */
                     20: 
                     21: #ifndef lint
                     22: char copyright[] =
                     23: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
                     24:  All rights reserved.\n";
                     25: #endif /* not lint */
                     26: 
                     27: #ifndef lint
                     28: static char sccsid[] = "@(#)strfile.c  5.11 (Berkeley) 12/15/89";
                     29: #endif /* not lint */
                     30: 
                     31: # include      <machine/endian.h>
                     32: # include      <sys/param.h>
                     33: # include      <stdio.h>
                     34: # include      <ctype.h>
                     35: # include      "strfile.h"
                     36: 
                     37: # ifndef MAXPATHLEN
                     38: # define       MAXPATHLEN      1024
                     39: # endif        /* MAXPATHLEN */
                     40: 
                     41: /*
                     42:  *     This program takes a file composed of strings seperated by
                     43:  * lines starting with two consecutive delimiting character (default
                     44:  * character is '%') and creates another file which consists of a table
                     45:  * describing the file (structure from "strfile.h"), a table of seek
                     46:  * pointers to the start of the strings, and the strings, each terminated
                     47:  * by a null byte.  Usage:
                     48:  *
                     49:  *     % strfile [-iorsx] [ -cC ] sourcefile [ datafile ]
                     50:  *
                     51:  *     c - Change delimiting character from '%' to 'C'
                     52:  *     s - Silent.  Give no summary of data processed at the end of
                     53:  *         the run.
                     54:  *     o - order the strings in alphabetic order
                     55:  *     i - if ordering, ignore case 
                     56:  *     r - randomize the order of the strings
                     57:  *     x - set rotated bit
                     58:  *
                     59:  *             Ken Arnold      Sept. 7, 1978 --
                     60:  *
                     61:  *     Added ordering options.
                     62:  */
                     63: 
                     64: # define       TRUE    1
                     65: # define       FALSE   0
                     66: 
                     67: # define       STORING_PTRS    (Oflag || Rflag)
                     68: # define       CHUNKSIZE       512
                     69: 
                     70: #ifdef lint
                     71: # define       ALWAYS  atoi("1")
                     72: #else
                     73: # define       ALWAYS  1
                     74: #endif
                     75: # define       ALLOC(ptr,sz)   if (ALWAYS) { \
                     76:                        if (ptr == NULL) \
                     77:                                ptr = malloc((unsigned int) (CHUNKSIZE * sizeof *ptr)); \
                     78:                        else if (((sz) + 1) % CHUNKSIZE == 0) \
                     79:                                ptr = realloc((void *) ptr, ((unsigned int) ((sz) + CHUNKSIZE) * sizeof *ptr)); \
                     80:                        if (ptr == NULL) { \
                     81:                                fprintf(stderr, "out of space\n"); \
                     82:                                exit(1); \
                     83:                        } \
                     84:                } else
                     85: 
                     86: #ifdef NO_VOID
                     87: # define       void    char
                     88: #endif
                     89: 
                     90: typedef struct {
                     91:        char    first;
                     92:        off_t   pos;
                     93: } STR;
                     94: 
                     95: char   *Infile         = NULL,         /* input file name */
                     96:        Outfile[MAXPATHLEN] = "",       /* output file name */
                     97:        Delimch         = '%';          /* delimiting character */
                     98: 
                     99: int    Sflag           = FALSE;        /* silent run flag */
                    100: int    Oflag           = FALSE;        /* ordering flag */
                    101: int    Iflag           = FALSE;        /* ignore case flag */
                    102: int    Rflag           = FALSE;        /* randomize order flag */
                    103: int    Xflag           = FALSE;        /* set rotated bit */
                    104: long   Num_pts         = 0;            /* number of pointers/strings */
                    105: 
                    106: off_t  *Seekpts;
                    107: 
                    108: FILE   *Sort_1, *Sort_2;               /* pointers for sorting */
                    109: 
                    110: STRFILE        Tbl;                            /* statistics table */
                    111: 
                    112: STR    *Firstch;                       /* first chars of each string */
                    113: 
                    114: char   *fgets(), *strcpy(), *strcat();
                    115: 
                    116: void   *malloc(), *realloc();
                    117: 
                    118: /*
                    119:  * main:
                    120:  *     Drive the sucker.  There are two main modes -- either we store
                    121:  *     the seek pointers, if the table is to be sorted or randomized,
                    122:  *     or we write the pointer directly to the file, if we are to stay
                    123:  *     in file order.  If the former, we allocate and re-allocate in
                    124:  *     CHUNKSIZE blocks; if the latter, we just write each pointer,
                    125:  *     and then seek back to the beginning to write in the table.
                    126:  */
                    127: main(ac, av)
                    128: int    ac;
                    129: char   **av;
                    130: {
                    131:        register char           *sp, dc;
                    132:        register FILE           *inf, *outf;
                    133:        register off_t          last_off, length, pos, *p;
                    134:        register int            first, cnt;
                    135:        register char           *nsp;
                    136:        register STR            *fp;
                    137:        static char             string[257];
                    138: 
                    139:        getargs(ac, av);                /* evalute arguments */
                    140:        dc = Delimch;
                    141:        if ((inf = fopen(Infile, "r")) == NULL) {
                    142:                perror(Infile);
                    143:                exit(1);
                    144:        }
                    145: 
                    146:        if ((outf = fopen(Outfile, "w")) == NULL) {
                    147:                perror(Outfile);
                    148:                exit(1);
                    149:        }
                    150:        if (!STORING_PTRS)
                    151:                (void) fseek(outf, sizeof Tbl, 0);
                    152: 
                    153:        /*
                    154:         * Write the strings onto the file
                    155:         */
                    156: 
                    157:        Tbl.str_longlen = 0;
                    158:        Tbl.str_shortlen = (unsigned int) 0xffffffff;
                    159:        Tbl.str_delim = dc;
                    160:        Tbl.str_version = VERSION;
                    161:        first = Oflag;
                    162:        add_offset(outf, ftell(inf));
                    163:        last_off = 0;
                    164:        do {
                    165:                sp = fgets(string, 256, inf);
                    166:                if (sp == NULL || sp[0] == dc && sp[1] == '\n') {
                    167:                        pos = ftell(inf);
                    168:                        length = pos - last_off - (sp ? strlen(sp) : 0);
                    169:                        last_off = pos;
                    170:                        if (!length)
                    171:                                continue;
                    172:                        add_offset(outf, pos);
                    173:                        if (Tbl.str_longlen < length)
                    174:                                Tbl.str_longlen = length;
                    175:                        if (Tbl.str_shortlen > length)
                    176:                                Tbl.str_shortlen = length;
                    177:                        first = Oflag;
                    178:                }
                    179:                else if (first) {
                    180:                        for (nsp = sp; !isalnum(*nsp); nsp++)
                    181:                                continue;
                    182:                        ALLOC(Firstch, Num_pts);
                    183:                        fp = &Firstch[Num_pts - 1];
                    184:                        if (Iflag && isupper(*nsp))
                    185:                                fp->first = tolower(*nsp);
                    186:                        else
                    187:                                fp->first = *nsp;
                    188:                        fp->pos = Seekpts[Num_pts - 1];
                    189:                        first = FALSE;
                    190:                }
                    191:        } while (sp != NULL);
                    192: 
                    193:        /*
                    194:         * write the tables in
                    195:         */
                    196: 
                    197:        (void) fclose(inf);
                    198: 
                    199:        if (Oflag)
                    200:                do_order();
                    201:        else if (Rflag)
                    202:                randomize();
                    203: 
                    204:        if (Xflag)
                    205:                Tbl.str_flags |= STR_ROTATED;
                    206: 
                    207:        if (!Sflag) {
                    208:                printf("\"%s\" created\n", Outfile);
                    209:                if (Num_pts == 2)
                    210:                        puts("There was 1 string");
                    211:                else
                    212:                        printf("There were %d strings\n", Num_pts - 1);
                    213:                printf("Longest string: %lu byte%s\n", Tbl.str_longlen,
                    214:                       Tbl.str_longlen == 1 ? "" : "s");
                    215:                printf("Shortest string: %lu byte%s\n", Tbl.str_shortlen,
                    216:                       Tbl.str_shortlen == 1 ? "" : "s");
                    217:        }
                    218: 
                    219:        (void) fseek(outf, (off_t) 0, 0);
                    220:        Tbl.str_version = htonl(Tbl.str_version);
                    221:        Tbl.str_numstr = htonl(Num_pts - 1);
                    222:        Tbl.str_longlen = htonl(Tbl.str_longlen);
                    223:        Tbl.str_shortlen = htonl(Tbl.str_shortlen);
                    224:        Tbl.str_flags = htonl(Tbl.str_flags);
                    225:        (void) fwrite((char *) &Tbl, sizeof Tbl, 1, outf);
                    226:        if (STORING_PTRS) {
                    227:                for (p = Seekpts, cnt = Num_pts; cnt--; ++p)
                    228:                        *p = htonl(*p);
                    229:                (void) fwrite((char *) Seekpts, sizeof *Seekpts, (int) Num_pts, outf);
                    230:        }
                    231:        (void) fclose(outf);
                    232:        exit(0);
                    233: }
                    234: 
                    235: /*
                    236:  *     This routine evaluates arguments from the command line
                    237:  */
                    238: getargs(argc, argv)
                    239: int    argc;
                    240: char   **argv;
                    241: {
                    242:        extern char     *optarg;
                    243:        extern int      optind;
                    244:        int     ch;
                    245: 
                    246:        while ((ch = getopt(argc, argv, "c:iorsx")) != EOF)
                    247:                switch(ch) {
                    248:                case 'c':                       /* new delimiting char */
                    249:                        Delimch = *optarg;
                    250:                        if (!isascii(Delimch)) {
                    251:                                printf("bad delimiting character: '\\%o\n'",
                    252:                                       Delimch);
                    253:                        }
                    254:                        break;
                    255:                case 'i':                       /* ignore case in ordering */
                    256:                        Iflag++;
                    257:                        break;
                    258:                case 'o':                       /* order strings */
                    259:                        Oflag++;
                    260:                        break;
                    261:                case 'r':                       /* randomize pointers */
                    262:                        Rflag++;
                    263:                        break;
                    264:                case 's':                       /* silent */
                    265:                        Sflag++;
                    266:                        break;
                    267:                case 'x':                       /* set the rotated bit */
                    268:                        Xflag++;
                    269:                        break;
                    270:                case '?':
                    271:                default:
                    272:                        usage();
                    273:                }
                    274:        argv += optind;
                    275: 
                    276:        if (*argv) {
                    277:                Infile = *argv;
                    278:                if (*++argv)
                    279:                        (void) strcpy(Outfile, *argv);
                    280:        }
                    281:        if (!Infile) {
                    282:                puts("No input file name");
                    283:                usage();
                    284:        }
                    285:        if (*Outfile == '\0') {
                    286:                (void) strcpy(Outfile, Infile);
                    287:                (void) strcat(Outfile, ".dat");
                    288:        }
                    289: }
                    290: 
                    291: usage()
                    292: {
                    293:        (void) fprintf(stderr,
                    294:            "strfile [-iorsx] [-c char] sourcefile [datafile]\n");
                    295:        exit(1);
                    296: }
                    297: 
                    298: /*
                    299:  * add_offset:
                    300:  *     Add an offset to the list, or write it out, as appropriate.
                    301:  */
                    302: add_offset(fp, off)
                    303: FILE   *fp;
                    304: off_t  off;
                    305: {
                    306:        off_t net;
                    307: 
                    308:        if (!STORING_PTRS) {
                    309:                net = htonl(off);
                    310:                fwrite(&net, 1, sizeof net, fp);
                    311:        } else {
                    312:                ALLOC(Seekpts, Num_pts + 1);
                    313:                Seekpts[Num_pts] = off;
                    314:        }
                    315:        Num_pts++;
                    316: }
                    317: 
                    318: /*
                    319:  * do_order:
                    320:  *     Order the strings alphabetically (possibly ignoring case).
                    321:  */
                    322: do_order()
                    323: {
                    324:        register int    i;
                    325:        register off_t  *lp;
                    326:        register STR    *fp;
                    327:        extern int      cmp_str();
                    328: 
                    329:        Sort_1 = fopen(Infile, "r");
                    330:        Sort_2 = fopen(Infile, "r");
                    331:        qsort((char *) Firstch, (int) Tbl.str_numstr, sizeof *Firstch, cmp_str);
                    332:        i = Tbl.str_numstr;
                    333:        lp = Seekpts;
                    334:        fp = Firstch;
                    335:        while (i--)
                    336:                *lp++ = fp++->pos;
                    337:        (void) fclose(Sort_1);
                    338:        (void) fclose(Sort_2);
                    339:        Tbl.str_flags |= STR_ORDERED;
                    340: }
                    341: 
                    342: /*
                    343:  * cmp_str:
                    344:  *     Compare two strings in the file
                    345:  */
                    346: char *
                    347: unctrl(c)
                    348: char c;
                    349: {
                    350:        static char     buf[3];
                    351: 
                    352:        if (isprint(c)) {
                    353:                buf[0] = c;
                    354:                buf[1] = '\0';
                    355:        }
                    356:        else if (c == 0177) {
                    357:                buf[0] = '^';
                    358:                buf[1] = '?';
                    359:        }
                    360:        else {
                    361:                buf[0] = '^';
                    362:                buf[1] = c + 'A' - 1;
                    363:        }
                    364:        return buf;
                    365: }
                    366: 
                    367: cmp_str(p1, p2)
                    368: STR    *p1, *p2;
                    369: {
                    370:        register int    c1, c2;
                    371:        register int    n1, n2;
                    372: 
                    373: # define       SET_N(nf,ch)    (nf = (ch == '\n'))
                    374: # define       IS_END(ch,nf)   (ch == Delimch && nf)
                    375: 
                    376:        c1 = p1->first;
                    377:        c2 = p2->first;
                    378:        if (c1 != c2)
                    379:                return c1 - c2;
                    380: 
                    381:        (void) fseek(Sort_1, p1->pos, 0);
                    382:        (void) fseek(Sort_2, p2->pos, 0);
                    383: 
                    384:        n1 = FALSE;
                    385:        n2 = FALSE;
                    386:        while (!isalnum(c1 = getc(Sort_1)) && c1 != '\0')
                    387:                SET_N(n1, c1);
                    388:        while (!isalnum(c2 = getc(Sort_2)) && c2 != '\0')
                    389:                SET_N(n2, c2);
                    390: 
                    391:        while (!IS_END(c1, n1) && !IS_END(c2, n2)) {
                    392:                if (Iflag) {
                    393:                        if (isupper(c1))
                    394:                                c1 = tolower(c1);
                    395:                        if (isupper(c2))
                    396:                                c2 = tolower(c2);
                    397:                }
                    398:                if (c1 != c2)
                    399:                        return c1 - c2;
                    400:                SET_N(n1, c1);
                    401:                SET_N(n2, c2);
                    402:                c1 = getc(Sort_1);
                    403:                c2 = getc(Sort_2);
                    404:        }
                    405:        if (IS_END(c1, n1))
                    406:                c1 = 0;
                    407:        if (IS_END(c2, n2))
                    408:                c2 = 0;
                    409:        return c1 - c2;
                    410: }
                    411: 
                    412: /*
                    413:  * randomize:
                    414:  *     Randomize the order of the string table.  We must be careful
                    415:  *     not to randomize across delimiter boundaries.  All
                    416:  *     randomization is done within each block.
                    417:  */
                    418: randomize()
                    419: {
                    420:        register int    cnt, i;
                    421:        register off_t  tmp;
                    422:        register off_t  *sp;
                    423:        extern time_t   time();
                    424: 
                    425:        srandom((int)(time((time_t *) NULL) + getpid()));
                    426: 
                    427:        Tbl.str_flags |= STR_RANDOM;
                    428:        cnt = Tbl.str_numstr;
                    429: 
                    430:        /*
                    431:         * move things around randomly
                    432:         */
                    433: 
                    434:        for (sp = Seekpts; cnt > 0; cnt--, sp++) {
                    435:                i = random() % cnt;
                    436:                tmp = sp[0];
                    437:                sp[0] = sp[i];
                    438:                sp[i] = tmp;
                    439:        }
                    440: }

unix.superglobalmegacorp.com

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