16ae1554aSColin Percival /*-
26ae1554aSColin Percival * Copyright (c) 1989, 1993
36ae1554aSColin Percival * The Regents of the University of California. All rights reserved.
46ae1554aSColin Percival *
56ae1554aSColin Percival * This code is derived from software contributed to Berkeley by
66ae1554aSColin Percival * Ken Arnold.
76ae1554aSColin Percival *
86ae1554aSColin Percival * Redistribution and use in source and binary forms, with or without
96ae1554aSColin Percival * modification, are permitted provided that the following conditions
106ae1554aSColin Percival * are met:
116ae1554aSColin Percival * 1. Redistributions of source code must retain the above copyright
126ae1554aSColin Percival * notice, this list of conditions and the following disclaimer.
136ae1554aSColin Percival * 2. Redistributions in binary form must reproduce the above copyright
146ae1554aSColin Percival * notice, this list of conditions and the following disclaimer in the
156ae1554aSColin Percival * documentation and/or other materials provided with the distribution.
166ae1554aSColin Percival * 3. Neither the name of the University nor the names of its contributors
176ae1554aSColin Percival * may be used to endorse or promote products derived from this software
186ae1554aSColin Percival * without specific prior written permission.
196ae1554aSColin Percival *
206ae1554aSColin Percival * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
216ae1554aSColin Percival * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226ae1554aSColin Percival * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236ae1554aSColin Percival * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
246ae1554aSColin Percival * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256ae1554aSColin Percival * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266ae1554aSColin Percival * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276ae1554aSColin Percival * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286ae1554aSColin Percival * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296ae1554aSColin Percival * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306ae1554aSColin Percival * SUCH DAMAGE.
316ae1554aSColin Percival */
326ae1554aSColin Percival
336ae1554aSColin Percival #include <sys/param.h>
346ae1554aSColin Percival #include <sys/endian.h>
356ae1554aSColin Percival #include <ctype.h>
366ae1554aSColin Percival #include <locale.h>
376ae1554aSColin Percival #include <stdbool.h>
386ae1554aSColin Percival #include <stdio.h>
396ae1554aSColin Percival #include <stdlib.h>
406ae1554aSColin Percival #include <string.h>
416ae1554aSColin Percival #include <time.h>
426ae1554aSColin Percival #include <unistd.h>
436ae1554aSColin Percival
446ae1554aSColin Percival #include "strfile.h"
456ae1554aSColin Percival
466ae1554aSColin Percival /*
476ae1554aSColin Percival * This program takes a file composed of strings separated by
486ae1554aSColin Percival * lines starting with two consecutive delimiting character (default
496ae1554aSColin Percival * character is '%') and creates another file which consists of a table
506ae1554aSColin Percival * describing the file (structure from "strfile.h"), a table of seek
516ae1554aSColin Percival * pointers to the start of the strings, and the strings, each terminated
526ae1554aSColin Percival * by a null byte. Usage:
536ae1554aSColin Percival *
546ae1554aSColin Percival * % strfile [-iorsx] [ -cC ] sourcefile [ datafile ]
556ae1554aSColin Percival *
566ae1554aSColin Percival * C - Allow comments marked by a double delimiter at line's beginning
576ae1554aSColin Percival * c - Change delimiting character from '%' to 'C'
586ae1554aSColin Percival * s - Silent. Give no summary of data processed at the end of
596ae1554aSColin Percival * the run.
606ae1554aSColin Percival * o - order the strings in alphabetic order
616ae1554aSColin Percival * i - if ordering, ignore case
626ae1554aSColin Percival * r - randomize the order of the strings
636ae1554aSColin Percival * x - set rotated bit
646ae1554aSColin Percival *
656ae1554aSColin Percival * Ken Arnold Sept. 7, 1978 --
666ae1554aSColin Percival *
676ae1554aSColin Percival * Added ordering options.
686ae1554aSColin Percival */
696ae1554aSColin Percival
706ae1554aSColin Percival #define STORING_PTRS (Oflag || Rflag)
716ae1554aSColin Percival #define CHUNKSIZE 512
726ae1554aSColin Percival
736ae1554aSColin Percival #define ALLOC(ptr, sz) do { \
746ae1554aSColin Percival if (ptr == NULL) \
756ae1554aSColin Percival ptr = malloc(CHUNKSIZE * sizeof(*ptr)); \
766ae1554aSColin Percival else if (((sz) + 1) % CHUNKSIZE == 0) \
776ae1554aSColin Percival ptr = realloc(ptr, ((sz) + CHUNKSIZE) * sizeof(*ptr)); \
786ae1554aSColin Percival if (ptr == NULL) { \
796ae1554aSColin Percival fprintf(stderr, "out of space\n"); \
806ae1554aSColin Percival exit(1); \
816ae1554aSColin Percival } \
826ae1554aSColin Percival } while (0)
836ae1554aSColin Percival
846ae1554aSColin Percival typedef struct {
856ae1554aSColin Percival int first;
866ae1554aSColin Percival off_t pos;
876ae1554aSColin Percival } STR;
886ae1554aSColin Percival
896ae1554aSColin Percival static char *Infile = NULL, /* input file name */
906ae1554aSColin Percival Outfile[MAXPATHLEN] = "", /* output file name */
916ae1554aSColin Percival Delimch = '%'; /* delimiting character */
926ae1554aSColin Percival
936ae1554aSColin Percival static int Cflag = false; /* embedded comments */
946ae1554aSColin Percival static int Sflag = false; /* silent run flag */
956ae1554aSColin Percival static int Oflag = false; /* ordering flag */
966ae1554aSColin Percival static int Iflag = false; /* ignore case flag */
976ae1554aSColin Percival static int Rflag = false; /* randomize order flag */
986ae1554aSColin Percival static int Xflag = false; /* set rotated bit */
996ae1554aSColin Percival static uint32_t Num_pts = 0; /* number of pointers/strings */
1006ae1554aSColin Percival
1016ae1554aSColin Percival static off_t *Seekpts;
1026ae1554aSColin Percival
1036ae1554aSColin Percival static FILE *Sort_1, *Sort_2; /* pointers for sorting */
1046ae1554aSColin Percival
1056ae1554aSColin Percival static STRFILE Tbl; /* statistics table */
1066ae1554aSColin Percival
1076ae1554aSColin Percival static STR *Firstch; /* first chars of each string */
1086ae1554aSColin Percival
1096ae1554aSColin Percival static void add_offset(FILE *, off_t);
1106ae1554aSColin Percival static int cmp_str(const void *, const void *);
1116ae1554aSColin Percival static int stable_collate_range_cmp(int, int);
1126ae1554aSColin Percival static void do_order(void);
1136ae1554aSColin Percival static void getargs(int, char **);
1146ae1554aSColin Percival static void randomize(void);
115*a1b6427aSAlfonso Gregory static void usage(void) __dead2;
1166ae1554aSColin Percival
1176ae1554aSColin Percival /*
1186ae1554aSColin Percival * main:
1196ae1554aSColin Percival * Drive the sucker. There are two main modes -- either we store
1206ae1554aSColin Percival * the seek pointers, if the table is to be sorted or randomized,
1216ae1554aSColin Percival * or we write the pointer directly to the file, if we are to stay
1226ae1554aSColin Percival * in file order. If the former, we allocate and re-allocate in
1236ae1554aSColin Percival * CHUNKSIZE blocks; if the latter, we just write each pointer,
1246ae1554aSColin Percival * and then seek back to the beginning to write in the table.
1256ae1554aSColin Percival */
1266ae1554aSColin Percival int
main(int ac,char * av[])1276ae1554aSColin Percival main(int ac, char *av[])
1286ae1554aSColin Percival {
1296ae1554aSColin Percival char *sp, *nsp, dc;
1306ae1554aSColin Percival FILE *inf, *outf;
1316ae1554aSColin Percival off_t last_off, pos, *p;
1326ae1554aSColin Percival size_t length;
1336ae1554aSColin Percival int first;
1346ae1554aSColin Percival uint32_t cnt;
1356ae1554aSColin Percival STR *fp;
1366ae1554aSColin Percival static char string[257];
1376ae1554aSColin Percival
1386ae1554aSColin Percival setlocale(LC_ALL, "");
1396ae1554aSColin Percival
1406ae1554aSColin Percival getargs(ac, av); /* evalute arguments */
1416ae1554aSColin Percival dc = Delimch;
1426ae1554aSColin Percival if ((inf = fopen(Infile, "r")) == NULL) {
1436ae1554aSColin Percival perror(Infile);
1446ae1554aSColin Percival exit(1);
1456ae1554aSColin Percival }
1466ae1554aSColin Percival
1476ae1554aSColin Percival if ((outf = fopen(Outfile, "w")) == NULL) {
1486ae1554aSColin Percival perror(Outfile);
1496ae1554aSColin Percival exit(1);
1506ae1554aSColin Percival }
1516ae1554aSColin Percival if (!STORING_PTRS)
1526ae1554aSColin Percival fseek(outf, (long)sizeof(Tbl), SEEK_SET);
1536ae1554aSColin Percival
1546ae1554aSColin Percival /*
1556ae1554aSColin Percival * Write the strings onto the file
1566ae1554aSColin Percival */
1576ae1554aSColin Percival
1586ae1554aSColin Percival Tbl.str_longlen = 0;
1596ae1554aSColin Percival Tbl.str_shortlen = 0xffffffff;
1606ae1554aSColin Percival Tbl.str_delim = dc;
1616ae1554aSColin Percival Tbl.str_version = VERSION;
1626ae1554aSColin Percival first = Oflag;
1636ae1554aSColin Percival add_offset(outf, ftello(inf));
1646ae1554aSColin Percival last_off = 0;
1656ae1554aSColin Percival do {
1666ae1554aSColin Percival sp = fgets(string, 256, inf);
1676ae1554aSColin Percival if (sp == NULL || (sp[0] == dc && sp[1] == '\n')) {
1686ae1554aSColin Percival pos = ftello(inf);
1696ae1554aSColin Percival length = (size_t)(pos - last_off) -
1706ae1554aSColin Percival (sp != NULL ? strlen(sp) : 0);
1716ae1554aSColin Percival last_off = pos;
1726ae1554aSColin Percival if (length == 0)
1736ae1554aSColin Percival continue;
1746ae1554aSColin Percival add_offset(outf, pos);
1756ae1554aSColin Percival if ((size_t)Tbl.str_longlen < length)
1766ae1554aSColin Percival Tbl.str_longlen = length;
1776ae1554aSColin Percival if ((size_t)Tbl.str_shortlen > length)
1786ae1554aSColin Percival Tbl.str_shortlen = length;
1796ae1554aSColin Percival first = Oflag;
1806ae1554aSColin Percival }
1816ae1554aSColin Percival else if (first) {
1826ae1554aSColin Percival for (nsp = sp; !isalnum((unsigned char)*nsp); nsp++)
1836ae1554aSColin Percival continue;
1846ae1554aSColin Percival ALLOC(Firstch, Num_pts);
1856ae1554aSColin Percival fp = &Firstch[Num_pts - 1];
1866ae1554aSColin Percival if (Iflag && isupper((unsigned char)*nsp))
1876ae1554aSColin Percival fp->first = tolower((unsigned char)*nsp);
1886ae1554aSColin Percival else
1896ae1554aSColin Percival fp->first = *nsp;
1906ae1554aSColin Percival fp->pos = Seekpts[Num_pts - 1];
1916ae1554aSColin Percival first = false;
1926ae1554aSColin Percival }
1936ae1554aSColin Percival } while (sp != NULL);
1946ae1554aSColin Percival
1956ae1554aSColin Percival /*
1966ae1554aSColin Percival * write the tables in
1976ae1554aSColin Percival */
1986ae1554aSColin Percival
1996ae1554aSColin Percival fclose(inf);
2006ae1554aSColin Percival Tbl.str_numstr = Num_pts - 1;
2016ae1554aSColin Percival
2026ae1554aSColin Percival if (Cflag)
2036ae1554aSColin Percival Tbl.str_flags |= STR_COMMENTS;
2046ae1554aSColin Percival
2056ae1554aSColin Percival if (Oflag)
2066ae1554aSColin Percival do_order();
2076ae1554aSColin Percival else if (Rflag)
2086ae1554aSColin Percival randomize();
2096ae1554aSColin Percival
2106ae1554aSColin Percival if (Xflag)
2116ae1554aSColin Percival Tbl.str_flags |= STR_ROTATED;
2126ae1554aSColin Percival
2136ae1554aSColin Percival if (!Sflag) {
2146ae1554aSColin Percival printf("\"%s\" created\n", Outfile);
2156ae1554aSColin Percival if (Num_pts == 2)
2166ae1554aSColin Percival puts("There was 1 string");
2176ae1554aSColin Percival else
2186ae1554aSColin Percival printf("There were %u strings\n", Num_pts - 1);
2196ae1554aSColin Percival printf("Longest string: %u byte%s\n", Tbl.str_longlen,
2206ae1554aSColin Percival Tbl.str_longlen == 1 ? "" : "s");
2216ae1554aSColin Percival printf("Shortest string: %u byte%s\n", Tbl.str_shortlen,
2226ae1554aSColin Percival Tbl.str_shortlen == 1 ? "" : "s");
2236ae1554aSColin Percival }
2246ae1554aSColin Percival
2256ae1554aSColin Percival rewind(outf);
2266ae1554aSColin Percival Tbl.str_version = htobe32(Tbl.str_version);
2276ae1554aSColin Percival Tbl.str_numstr = htobe32(Tbl.str_numstr);
2286ae1554aSColin Percival Tbl.str_longlen = htobe32(Tbl.str_longlen);
2296ae1554aSColin Percival Tbl.str_shortlen = htobe32(Tbl.str_shortlen);
2306ae1554aSColin Percival Tbl.str_flags = htobe32(Tbl.str_flags);
2316ae1554aSColin Percival fwrite((char *)&Tbl, sizeof(Tbl), 1, outf);
2326ae1554aSColin Percival if (STORING_PTRS) {
2336ae1554aSColin Percival for (p = Seekpts, cnt = Num_pts; cnt--; ++p)
2346ae1554aSColin Percival *p = htobe64(*p);
2356ae1554aSColin Percival fwrite(Seekpts, sizeof(*Seekpts), (size_t)Num_pts, outf);
2366ae1554aSColin Percival }
2376ae1554aSColin Percival fclose(outf);
2386ae1554aSColin Percival exit(0);
2396ae1554aSColin Percival }
2406ae1554aSColin Percival
2416ae1554aSColin Percival /*
2426ae1554aSColin Percival * This routine evaluates arguments from the command line
2436ae1554aSColin Percival */
2446ae1554aSColin Percival void
getargs(int argc,char ** argv)2456ae1554aSColin Percival getargs(int argc, char **argv)
2466ae1554aSColin Percival {
2476ae1554aSColin Percival int ch;
2486ae1554aSColin Percival
2496ae1554aSColin Percival while ((ch = getopt(argc, argv, "Cc:iorsx")) != -1)
2506ae1554aSColin Percival switch(ch) {
2516ae1554aSColin Percival case 'C': /* embedded comments */
2526ae1554aSColin Percival Cflag++;
2536ae1554aSColin Percival break;
2546ae1554aSColin Percival case 'c': /* new delimiting char */
2556ae1554aSColin Percival Delimch = *optarg;
2566ae1554aSColin Percival if (!isascii(Delimch)) {
2576ae1554aSColin Percival printf("bad delimiting character: '\\%o\n'",
2586ae1554aSColin Percival (unsigned char)Delimch);
2596ae1554aSColin Percival }
2606ae1554aSColin Percival break;
2616ae1554aSColin Percival case 'i': /* ignore case in ordering */
2626ae1554aSColin Percival Iflag++;
2636ae1554aSColin Percival break;
2646ae1554aSColin Percival case 'o': /* order strings */
2656ae1554aSColin Percival Oflag++;
2666ae1554aSColin Percival break;
2676ae1554aSColin Percival case 'r': /* randomize pointers */
2686ae1554aSColin Percival Rflag++;
2696ae1554aSColin Percival break;
2706ae1554aSColin Percival case 's': /* silent */
2716ae1554aSColin Percival Sflag++;
2726ae1554aSColin Percival break;
2736ae1554aSColin Percival case 'x': /* set the rotated bit */
2746ae1554aSColin Percival Xflag++;
2756ae1554aSColin Percival break;
2766ae1554aSColin Percival case '?':
2776ae1554aSColin Percival default:
2786ae1554aSColin Percival usage();
2796ae1554aSColin Percival }
2806ae1554aSColin Percival argv += optind;
2816ae1554aSColin Percival
2826ae1554aSColin Percival if (*argv) {
2836ae1554aSColin Percival Infile = *argv;
284777c9f5aSMark Johnston if (*++argv) {
285777c9f5aSMark Johnston if (strlcpy(Outfile, *argv, sizeof(Outfile)) >=
286777c9f5aSMark Johnston sizeof(Outfile)) {
287777c9f5aSMark Johnston fprintf(stderr,
288777c9f5aSMark Johnston "output_file path is too long\n");
289777c9f5aSMark Johnston exit(1);
290777c9f5aSMark Johnston }
291777c9f5aSMark Johnston }
2926ae1554aSColin Percival }
2936ae1554aSColin Percival if (!Infile) {
2946ae1554aSColin Percival puts("No input file name");
2956ae1554aSColin Percival usage();
2966ae1554aSColin Percival }
2976ae1554aSColin Percival if (*Outfile == '\0') {
298777c9f5aSMark Johnston if ((size_t)snprintf(Outfile, sizeof(Outfile), "%s.dat",
299777c9f5aSMark Johnston Infile) >= sizeof(Outfile)) {
300777c9f5aSMark Johnston fprintf(stderr,
301777c9f5aSMark Johnston "generated output_file path is too long\n");
302777c9f5aSMark Johnston exit(1);
303777c9f5aSMark Johnston }
3046ae1554aSColin Percival }
3056ae1554aSColin Percival }
3066ae1554aSColin Percival
3076ae1554aSColin Percival void
usage(void)3086ae1554aSColin Percival usage(void)
3096ae1554aSColin Percival {
3106ae1554aSColin Percival fprintf(stderr,
3116ae1554aSColin Percival "strfile [-Ciorsx] [-c char] source_file [output_file]\n");
3126ae1554aSColin Percival exit(1);
3136ae1554aSColin Percival }
3146ae1554aSColin Percival
3156ae1554aSColin Percival /*
3166ae1554aSColin Percival * add_offset:
3176ae1554aSColin Percival * Add an offset to the list, or write it out, as appropriate.
3186ae1554aSColin Percival */
3196ae1554aSColin Percival void
add_offset(FILE * fp,off_t off)3206ae1554aSColin Percival add_offset(FILE *fp, off_t off)
3216ae1554aSColin Percival {
3226ae1554aSColin Percival off_t beoff;
3236ae1554aSColin Percival
3246ae1554aSColin Percival if (!STORING_PTRS) {
3256ae1554aSColin Percival beoff = htobe64(off);
3266ae1554aSColin Percival fwrite(&beoff, 1, sizeof(beoff), fp);
3276ae1554aSColin Percival } else {
3286ae1554aSColin Percival ALLOC(Seekpts, Num_pts + 1);
3296ae1554aSColin Percival Seekpts[Num_pts] = off;
3306ae1554aSColin Percival }
3316ae1554aSColin Percival Num_pts++;
3326ae1554aSColin Percival }
3336ae1554aSColin Percival
3346ae1554aSColin Percival /*
3356ae1554aSColin Percival * do_order:
3366ae1554aSColin Percival * Order the strings alphabetically (possibly ignoring case).
3376ae1554aSColin Percival */
3386ae1554aSColin Percival void
do_order(void)3396ae1554aSColin Percival do_order(void)
3406ae1554aSColin Percival {
3416ae1554aSColin Percival uint32_t i;
3426ae1554aSColin Percival off_t *lp;
3436ae1554aSColin Percival STR *fp;
3446ae1554aSColin Percival
3456ae1554aSColin Percival Sort_1 = fopen(Infile, "r");
3466ae1554aSColin Percival Sort_2 = fopen(Infile, "r");
3476ae1554aSColin Percival qsort(Firstch, (size_t)Tbl.str_numstr, sizeof(*Firstch), cmp_str);
3486ae1554aSColin Percival i = Tbl.str_numstr;
3496ae1554aSColin Percival lp = Seekpts;
3506ae1554aSColin Percival fp = Firstch;
3516ae1554aSColin Percival while (i--)
3526ae1554aSColin Percival *lp++ = fp++->pos;
3536ae1554aSColin Percival fclose(Sort_1);
3546ae1554aSColin Percival fclose(Sort_2);
3556ae1554aSColin Percival Tbl.str_flags |= STR_ORDERED;
3566ae1554aSColin Percival }
3576ae1554aSColin Percival
3586ae1554aSColin Percival static int
stable_collate_range_cmp(int c1,int c2)3596ae1554aSColin Percival stable_collate_range_cmp(int c1, int c2)
3606ae1554aSColin Percival {
3616ae1554aSColin Percival static char s1[2], s2[2];
3626ae1554aSColin Percival int ret;
3636ae1554aSColin Percival
3646ae1554aSColin Percival s1[0] = c1;
3656ae1554aSColin Percival s2[0] = c2;
3666ae1554aSColin Percival if ((ret = strcoll(s1, s2)) != 0)
3676ae1554aSColin Percival return (ret);
3686ae1554aSColin Percival return (c1 - c2);
3696ae1554aSColin Percival }
3706ae1554aSColin Percival
3716ae1554aSColin Percival /*
3726ae1554aSColin Percival * cmp_str:
3736ae1554aSColin Percival * Compare two strings in the file
3746ae1554aSColin Percival */
3756ae1554aSColin Percival int
cmp_str(const void * s1,const void * s2)3766ae1554aSColin Percival cmp_str(const void *s1, const void *s2)
3776ae1554aSColin Percival {
3786ae1554aSColin Percival const STR *p1, *p2;
3796ae1554aSColin Percival int c1, c2, n1, n2, r;
3806ae1554aSColin Percival
3816ae1554aSColin Percival #define SET_N(nf,ch) (nf = (ch == '\n'))
3826ae1554aSColin Percival #define IS_END(ch,nf) (ch == EOF || (ch == (unsigned char)Delimch && nf))
3836ae1554aSColin Percival
3846ae1554aSColin Percival p1 = (const STR *)s1;
3856ae1554aSColin Percival p2 = (const STR *)s2;
3866ae1554aSColin Percival
3876ae1554aSColin Percival c1 = (unsigned char)p1->first;
3886ae1554aSColin Percival c2 = (unsigned char)p2->first;
3896ae1554aSColin Percival if ((r = stable_collate_range_cmp(c1, c2)) != 0)
3906ae1554aSColin Percival return (r);
3916ae1554aSColin Percival
3926ae1554aSColin Percival fseeko(Sort_1, p1->pos, SEEK_SET);
3936ae1554aSColin Percival fseeko(Sort_2, p2->pos, SEEK_SET);
3946ae1554aSColin Percival
3956ae1554aSColin Percival n1 = false;
3966ae1554aSColin Percival n2 = false;
3976ae1554aSColin Percival while (!isalnum(c1 = getc(Sort_1)) && c1 != '\0' && c1 != EOF)
3986ae1554aSColin Percival SET_N(n1, c1);
3996ae1554aSColin Percival while (!isalnum(c2 = getc(Sort_2)) && c2 != '\0' && c2 != EOF)
4006ae1554aSColin Percival SET_N(n2, c2);
4016ae1554aSColin Percival
4026ae1554aSColin Percival while (!IS_END(c1, n1) && !IS_END(c2, n2)) {
4036ae1554aSColin Percival if (Iflag) {
4046ae1554aSColin Percival if (isupper(c1))
4056ae1554aSColin Percival c1 = tolower(c1);
4066ae1554aSColin Percival if (isupper(c2))
4076ae1554aSColin Percival c2 = tolower(c2);
4086ae1554aSColin Percival }
4096ae1554aSColin Percival if ((r = stable_collate_range_cmp(c1, c2)) != 0)
4106ae1554aSColin Percival return (r);
4116ae1554aSColin Percival SET_N(n1, c1);
4126ae1554aSColin Percival SET_N(n2, c2);
4136ae1554aSColin Percival c1 = getc(Sort_1);
4146ae1554aSColin Percival c2 = getc(Sort_2);
4156ae1554aSColin Percival }
4166ae1554aSColin Percival if (IS_END(c1, n1))
4176ae1554aSColin Percival c1 = 0;
4186ae1554aSColin Percival if (IS_END(c2, n2))
4196ae1554aSColin Percival c2 = 0;
4206ae1554aSColin Percival
4216ae1554aSColin Percival return (stable_collate_range_cmp(c1, c2));
4226ae1554aSColin Percival }
4236ae1554aSColin Percival
4246ae1554aSColin Percival /*
4256ae1554aSColin Percival * randomize:
4266ae1554aSColin Percival * Randomize the order of the string table. We must be careful
4276ae1554aSColin Percival * not to randomize across delimiter boundaries. All
4286ae1554aSColin Percival * randomization is done within each block.
4296ae1554aSColin Percival */
4306ae1554aSColin Percival void
randomize(void)4316ae1554aSColin Percival randomize(void)
4326ae1554aSColin Percival {
4336ae1554aSColin Percival uint32_t cnt, i;
4346ae1554aSColin Percival off_t tmp;
4356ae1554aSColin Percival off_t *sp;
4366ae1554aSColin Percival
4376ae1554aSColin Percival Tbl.str_flags |= STR_RANDOM;
4386ae1554aSColin Percival cnt = Tbl.str_numstr;
4396ae1554aSColin Percival
4406ae1554aSColin Percival /*
4416ae1554aSColin Percival * move things around randomly
4426ae1554aSColin Percival */
4436ae1554aSColin Percival
4446ae1554aSColin Percival for (sp = Seekpts; cnt > 0; cnt--, sp++) {
4456ae1554aSColin Percival i = arc4random_uniform(cnt);
4466ae1554aSColin Percival tmp = sp[0];
4476ae1554aSColin Percival sp[0] = sp[i];
4486ae1554aSColin Percival sp[i] = tmp;
4496ae1554aSColin Percival }
4506ae1554aSColin Percival }
451