strfile.c (201175) | strfile.c (203926) |
---|---|
1/*- 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. 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, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. | 1/*- 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. 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, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. |
16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors | 16 * 3. Neither the name of the University nor the names of its contributors |
21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL --- 12 unchanged lines hidden (view full) --- 41 The Regents of the University of California. All rights reserved.\n"; 42#endif /* not lint */ 43 44#ifndef lint 45static const char sccsid[] = "@(#)strfile.c 8.1 (Berkeley) 5/31/93"; 46#endif /* not lint */ 47#endif 48#include <sys/cdefs.h> | 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL --- 12 unchanged lines hidden (view full) --- 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41static const char sccsid[] = "@(#)strfile.c 8.1 (Berkeley) 5/31/93"; 42#endif /* not lint */ 43#endif 44#include <sys/cdefs.h> |
49__FBSDID("$FreeBSD: head/games/fortune/strfile/strfile.c 201175 2009-12-29 08:42:58Z ed $"); | 45__FBSDID("$FreeBSD: head/games/fortune/strfile/strfile.c 203926 2010-02-15 15:10:21Z uqs $"); |
50 | 46 |
51# include <sys/param.h> 52# include <sys/endian.h> 53# include <stdio.h> 54# include <stdlib.h> 55# include <ctype.h> 56# include <string.h> 57# include <time.h> 58# include <locale.h> 59# include <unistd.h> 60# include "strfile.h" | 47#include <sys/param.h> 48#include <sys/endian.h> 49#include <ctype.h> 50#include <locale.h> 51#include <stdbool.h> 52#include <stdio.h> 53#include <stdlib.h> 54#include <string.h> 55#include <time.h> 56#include <unistd.h> |
61 | 57 |
58#include "strfile.h" 59 |
|
62/* 63 * This program takes a file composed of strings separated by 64 * lines starting with two consecutive delimiting character (default 65 * character is '%') and creates another file which consists of a table 66 * describing the file (structure from "strfile.h"), a table of seek 67 * pointers to the start of the strings, and the strings, each terminated 68 * by a null byte. Usage: 69 * --- 8 unchanged lines hidden (view full) --- 78 * r - randomize the order of the strings 79 * x - set rotated bit 80 * 81 * Ken Arnold Sept. 7, 1978 -- 82 * 83 * Added ordering options. 84 */ 85 | 60/* 61 * This program takes a file composed of strings separated by 62 * lines starting with two consecutive delimiting character (default 63 * character is '%') and creates another file which consists of a table 64 * describing the file (structure from "strfile.h"), a table of seek 65 * pointers to the start of the strings, and the strings, each terminated 66 * by a null byte. Usage: 67 * --- 8 unchanged lines hidden (view full) --- 76 * r - randomize the order of the strings 77 * x - set rotated bit 78 * 79 * Ken Arnold Sept. 7, 1978 -- 80 * 81 * Added ordering options. 82 */ 83 |
86# define TRUE 1 87# define FALSE 0 | 84#define STORING_PTRS (Oflag || Rflag) 85#define CHUNKSIZE 512 |
88 | 86 |
89# define STORING_PTRS (Oflag || Rflag) 90# define CHUNKSIZE 512 91 92# define ALLOC(ptr,sz) { \ | 87#define ALLOC(ptr, sz) do { \ |
93 if (ptr == NULL) \ | 88 if (ptr == NULL) \ |
94 ptr = malloc(CHUNKSIZE * sizeof *ptr); \ | 89 ptr = malloc(CHUNKSIZE * sizeof(*ptr)); \ |
95 else if (((sz) + 1) % CHUNKSIZE == 0) \ | 90 else if (((sz) + 1) % CHUNKSIZE == 0) \ |
96 ptr = realloc(ptr, ((sz) + CHUNKSIZE) * sizeof *ptr); \ | 91 ptr = realloc(ptr, ((sz) + CHUNKSIZE) * sizeof(*ptr)); \ |
97 if (ptr == NULL) { \ 98 fprintf(stderr, "out of space\n"); \ 99 exit(1); \ 100 } \ | 92 if (ptr == NULL) { \ 93 fprintf(stderr, "out of space\n"); \ 94 exit(1); \ 95 } \ |
101 } | 96 } while (0) |
102 | 97 |
103#ifdef NO_VOID 104# define void char 105#endif 106 | |
107typedef struct { 108 int first; 109 off_t pos; 110} STR; 111 112static char *Infile = NULL, /* input file name */ 113 Outfile[MAXPATHLEN] = "", /* output file name */ 114 Delimch = '%'; /* delimiting character */ 115 | 98typedef struct { 99 int first; 100 off_t pos; 101} STR; 102 103static char *Infile = NULL, /* input file name */ 104 Outfile[MAXPATHLEN] = "", /* output file name */ 105 Delimch = '%'; /* delimiting character */ 106 |
116static int Cflag = FALSE; /* embedded comments */ 117static int Sflag = FALSE; /* silent run flag */ 118static int Oflag = FALSE; /* ordering flag */ 119static int Iflag = FALSE; /* ignore case flag */ 120static int Rflag = FALSE; /* randomize order flag */ 121static int Xflag = FALSE; /* set rotated bit */ | 107static int Cflag = false; /* embedded comments */ 108static int Sflag = false; /* silent run flag */ 109static int Oflag = false; /* ordering flag */ 110static int Iflag = false; /* ignore case flag */ 111static int Rflag = false; /* randomize order flag */ 112static int Xflag = false; /* set rotated bit */ |
122static uint32_t Num_pts = 0; /* number of pointers/strings */ 123 124static off_t *Seekpts; 125 126static FILE *Sort_1, *Sort_2; /* pointers for sorting */ 127 128static STRFILE Tbl; /* statistics table */ 129 130static STR *Firstch; /* first chars of each string */ 131 | 113static uint32_t Num_pts = 0; /* number of pointers/strings */ 114 115static off_t *Seekpts; 116 117static FILE *Sort_1, *Sort_2; /* pointers for sorting */ 118 119static STRFILE Tbl; /* statistics table */ 120 121static STR *Firstch; /* first chars of each string */ 122 |
132static void add_offset(FILE *, off_t); 133static int cmp_str(const void *, const void *); 134static int stable_collate_range_cmp(int, int); 135static void do_order(void); 136static void getargs(int, char **); 137static void randomize(void); 138static void usage(void); | 123static void add_offset(FILE *, off_t); 124static int cmp_str(const void *, const void *); 125static int stable_collate_range_cmp(int, int); 126static void do_order(void); 127static void getargs(int, char **); 128static void randomize(void); 129static void usage(void); |
139 140/* 141 * main: 142 * Drive the sucker. There are two main modes -- either we store 143 * the seek pointers, if the table is to be sorted or randomized, 144 * or we write the pointer directly to the file, if we are to stay 145 * in file order. If the former, we allocate and re-allocate in 146 * CHUNKSIZE blocks; if the latter, we just write each pointer, 147 * and then seek back to the beginning to write in the table. 148 */ 149int 150main(int ac, char *av[]) 151{ | 130 131/* 132 * main: 133 * Drive the sucker. There are two main modes -- either we store 134 * the seek pointers, if the table is to be sorted or randomized, 135 * or we write the pointer directly to the file, if we are to stay 136 * in file order. If the former, we allocate and re-allocate in 137 * CHUNKSIZE blocks; if the latter, we just write each pointer, 138 * and then seek back to the beginning to write in the table. 139 */ 140int 141main(int ac, char *av[]) 142{ |
152 char *sp, dc; 153 FILE *inf, *outf; 154 off_t last_off, pos, *p; 155 size_t length; 156 int first; 157 uint32_t cnt; 158 char *nsp; 159 STR *fp; 160 static char string[257]; | 143 char *sp, *nsp, dc; 144 FILE *inf, *outf; 145 off_t last_off, pos, *p; 146 size_t length; 147 int first; 148 uint32_t cnt; 149 STR *fp; 150 static char string[257]; |
161 | 151 |
162 (void) setlocale(LC_ALL, ""); | 152 setlocale(LC_ALL, ""); |
163 164 getargs(ac, av); /* evalute arguments */ 165 dc = Delimch; 166 if ((inf = fopen(Infile, "r")) == NULL) { 167 perror(Infile); 168 exit(1); 169 } 170 171 if ((outf = fopen(Outfile, "w")) == NULL) { 172 perror(Outfile); 173 exit(1); 174 } 175 if (!STORING_PTRS) | 153 154 getargs(ac, av); /* evalute arguments */ 155 dc = Delimch; 156 if ((inf = fopen(Infile, "r")) == NULL) { 157 perror(Infile); 158 exit(1); 159 } 160 161 if ((outf = fopen(Outfile, "w")) == NULL) { 162 perror(Outfile); 163 exit(1); 164 } 165 if (!STORING_PTRS) |
176 (void) fseek(outf, (long) sizeof Tbl, 0); | 166 fseek(outf, (long)sizeof(Tbl), SEEK_SET); |
177 178 /* 179 * Write the strings onto the file 180 */ 181 182 Tbl.str_longlen = 0; 183 Tbl.str_shortlen = 0xffffffff; 184 Tbl.str_delim = dc; --- 22 unchanged lines hidden (view full) --- 207 continue; 208 ALLOC(Firstch, Num_pts); 209 fp = &Firstch[Num_pts - 1]; 210 if (Iflag && isupper((unsigned char)*nsp)) 211 fp->first = tolower((unsigned char)*nsp); 212 else 213 fp->first = *nsp; 214 fp->pos = Seekpts[Num_pts - 1]; | 167 168 /* 169 * Write the strings onto the file 170 */ 171 172 Tbl.str_longlen = 0; 173 Tbl.str_shortlen = 0xffffffff; 174 Tbl.str_delim = dc; --- 22 unchanged lines hidden (view full) --- 197 continue; 198 ALLOC(Firstch, Num_pts); 199 fp = &Firstch[Num_pts - 1]; 200 if (Iflag && isupper((unsigned char)*nsp)) 201 fp->first = tolower((unsigned char)*nsp); 202 else 203 fp->first = *nsp; 204 fp->pos = Seekpts[Num_pts - 1]; |
215 first = FALSE; | 205 first = false; |
216 } 217 } while (sp != NULL); 218 219 /* 220 * write the tables in 221 */ 222 | 206 } 207 } while (sp != NULL); 208 209 /* 210 * write the tables in 211 */ 212 |
223 (void) fclose(inf); | 213 fclose(inf); |
224 Tbl.str_numstr = Num_pts - 1; 225 226 if (Cflag) 227 Tbl.str_flags |= STR_COMMENTS; 228 229 if (Oflag) 230 do_order(); 231 else if (Rflag) --- 15 unchanged lines hidden (view full) --- 247 } 248 249 rewind(outf); 250 Tbl.str_version = htobe32(Tbl.str_version); 251 Tbl.str_numstr = htobe32(Tbl.str_numstr); 252 Tbl.str_longlen = htobe32(Tbl.str_longlen); 253 Tbl.str_shortlen = htobe32(Tbl.str_shortlen); 254 Tbl.str_flags = htobe32(Tbl.str_flags); | 214 Tbl.str_numstr = Num_pts - 1; 215 216 if (Cflag) 217 Tbl.str_flags |= STR_COMMENTS; 218 219 if (Oflag) 220 do_order(); 221 else if (Rflag) --- 15 unchanged lines hidden (view full) --- 237 } 238 239 rewind(outf); 240 Tbl.str_version = htobe32(Tbl.str_version); 241 Tbl.str_numstr = htobe32(Tbl.str_numstr); 242 Tbl.str_longlen = htobe32(Tbl.str_longlen); 243 Tbl.str_shortlen = htobe32(Tbl.str_shortlen); 244 Tbl.str_flags = htobe32(Tbl.str_flags); |
255 (void) fwrite((char *) &Tbl, sizeof Tbl, 1, outf); | 245 fwrite((char *)&Tbl, sizeof(Tbl), 1, outf); |
256 if (STORING_PTRS) { 257 for (p = Seekpts, cnt = Num_pts; cnt--; ++p) 258 *p = htobe64(*p); | 246 if (STORING_PTRS) { 247 for (p = Seekpts, cnt = Num_pts; cnt--; ++p) 248 *p = htobe64(*p); |
259 (void) fwrite(Seekpts, sizeof *Seekpts, (size_t) Num_pts, outf); | 249 fwrite(Seekpts, sizeof(*Seekpts), (size_t)Num_pts, outf); |
260 } | 250 } |
261 (void) fclose(outf); | 251 fclose(outf); |
262 exit(0); 263} 264 265/* 266 * This routine evaluates arguments from the command line 267 */ 268void 269getargs(int argc, char **argv) 270{ | 252 exit(0); 253} 254 255/* 256 * This routine evaluates arguments from the command line 257 */ 258void 259getargs(int argc, char **argv) 260{ |
271 int ch; | 261 int ch; |
272 273 while ((ch = getopt(argc, argv, "Cc:iorsx")) != -1) 274 switch(ch) { 275 case 'C': /* embedded comments */ 276 Cflag++; 277 break; 278 case 'c': /* new delimiting char */ 279 Delimch = *optarg; --- 21 unchanged lines hidden (view full) --- 301 default: 302 usage(); 303 } 304 argv += optind; 305 306 if (*argv) { 307 Infile = *argv; 308 if (*++argv) | 262 263 while ((ch = getopt(argc, argv, "Cc:iorsx")) != -1) 264 switch(ch) { 265 case 'C': /* embedded comments */ 266 Cflag++; 267 break; 268 case 'c': /* new delimiting char */ 269 Delimch = *optarg; --- 21 unchanged lines hidden (view full) --- 291 default: 292 usage(); 293 } 294 argv += optind; 295 296 if (*argv) { 297 Infile = *argv; 298 if (*++argv) |
309 (void) strcpy(Outfile, *argv); | 299 strcpy(Outfile, *argv); |
310 } 311 if (!Infile) { 312 puts("No input file name"); 313 usage(); 314 } 315 if (*Outfile == '\0') { | 300 } 301 if (!Infile) { 302 puts("No input file name"); 303 usage(); 304 } 305 if (*Outfile == '\0') { |
316 (void) strcpy(Outfile, Infile); 317 (void) strcat(Outfile, ".dat"); | 306 strcpy(Outfile, Infile); 307 strcat(Outfile, ".dat"); |
318 } 319} 320 321void 322usage(void) 323{ | 308 } 309} 310 311void 312usage(void) 313{ |
324 (void) fprintf(stderr, | 314 fprintf(stderr, |
325 "strfile [-Ciorsx] [-c char] source_file [output_file]\n"); 326 exit(1); 327} 328 329/* 330 * add_offset: 331 * Add an offset to the list, or write it out, as appropriate. 332 */ 333void 334add_offset(FILE *fp, off_t off) 335{ 336 off_t beoff; 337 338 if (!STORING_PTRS) { 339 beoff = htobe64(off); | 315 "strfile [-Ciorsx] [-c char] source_file [output_file]\n"); 316 exit(1); 317} 318 319/* 320 * add_offset: 321 * Add an offset to the list, or write it out, as appropriate. 322 */ 323void 324add_offset(FILE *fp, off_t off) 325{ 326 off_t beoff; 327 328 if (!STORING_PTRS) { 329 beoff = htobe64(off); |
340 fwrite(&beoff, 1, sizeof beoff, fp); | 330 fwrite(&beoff, 1, sizeof(beoff), fp); |
341 } else { 342 ALLOC(Seekpts, Num_pts + 1); 343 Seekpts[Num_pts] = off; 344 } 345 Num_pts++; 346} 347 348/* 349 * do_order: 350 * Order the strings alphabetically (possibly ignoring case). 351 */ 352void 353do_order(void) 354{ 355 uint32_t i; | 331 } else { 332 ALLOC(Seekpts, Num_pts + 1); 333 Seekpts[Num_pts] = off; 334 } 335 Num_pts++; 336} 337 338/* 339 * do_order: 340 * Order the strings alphabetically (possibly ignoring case). 341 */ 342void 343do_order(void) 344{ 345 uint32_t i; |
356 off_t *lp; 357 STR *fp; | 346 off_t *lp; 347 STR *fp; |
358 359 Sort_1 = fopen(Infile, "r"); 360 Sort_2 = fopen(Infile, "r"); | 348 349 Sort_1 = fopen(Infile, "r"); 350 Sort_2 = fopen(Infile, "r"); |
361 qsort(Firstch, (size_t) Tbl.str_numstr, sizeof *Firstch, cmp_str); | 351 qsort(Firstch, (size_t)Tbl.str_numstr, sizeof(*Firstch), cmp_str); |
362 i = Tbl.str_numstr; 363 lp = Seekpts; 364 fp = Firstch; 365 while (i--) 366 *lp++ = fp++->pos; | 352 i = Tbl.str_numstr; 353 lp = Seekpts; 354 fp = Firstch; 355 while (i--) 356 *lp++ = fp++->pos; |
367 (void) fclose(Sort_1); 368 (void) fclose(Sort_2); | 357 fclose(Sort_1); 358 fclose(Sort_2); |
369 Tbl.str_flags |= STR_ORDERED; 370} 371 372static int 373stable_collate_range_cmp(int c1, int c2) 374{ 375 static char s1[2], s2[2]; 376 int ret; --- 7 unchanged lines hidden (view full) --- 384 385/* 386 * cmp_str: 387 * Compare two strings in the file 388 */ 389int 390cmp_str(const void *s1, const void *s2) 391{ | 359 Tbl.str_flags |= STR_ORDERED; 360} 361 362static int 363stable_collate_range_cmp(int c1, int c2) 364{ 365 static char s1[2], s2[2]; 366 int ret; --- 7 unchanged lines hidden (view full) --- 374 375/* 376 * cmp_str: 377 * Compare two strings in the file 378 */ 379int 380cmp_str(const void *s1, const void *s2) 381{ |
392 const STR *p1, *p2; 393 int c1, c2; 394 int n1, n2; 395 int r; | 382 const STR *p1, *p2; 383 int c1, c2, n1, n2, r; |
396 | 384 |
397# define SET_N(nf,ch) (nf = (ch == '\n')) 398# define IS_END(ch,nf) (ch == EOF || (ch == (unsigned char) Delimch && nf)) | 385#define SET_N(nf,ch) (nf = (ch == '\n')) 386#define IS_END(ch,nf) (ch == EOF || (ch == (unsigned char)Delimch && nf)) |
399 | 387 |
400 p1 = (const STR *) s1; 401 p2 = (const STR *) s2; 402 403 c1 = (unsigned char) p1->first; 404 c2 = (unsigned char) p2->first; | 388 p1 = (const STR *)s1; 389 p2 = (const STR *)s2; 390 391 c1 = (unsigned char)p1->first; 392 c2 = (unsigned char)p2->first; |
405 if ((r = stable_collate_range_cmp(c1, c2)) != 0) 406 return (r); 407 | 393 if ((r = stable_collate_range_cmp(c1, c2)) != 0) 394 return (r); 395 |
408 (void) fseeko(Sort_1, p1->pos, 0); 409 (void) fseeko(Sort_2, p2->pos, 0); | 396 fseeko(Sort_1, p1->pos, SEEK_SET); 397 fseeko(Sort_2, p2->pos, SEEK_SET); |
410 | 398 |
411 n1 = FALSE; 412 n2 = FALSE; | 399 n1 = false; 400 n2 = false; |
413 while (!isalnum(c1 = getc(Sort_1)) && c1 != '\0' && c1 != EOF) 414 SET_N(n1, c1); 415 while (!isalnum(c2 = getc(Sort_2)) && c2 != '\0' && c2 != EOF) 416 SET_N(n2, c2); 417 418 while (!IS_END(c1, n1) && !IS_END(c2, n2)) { 419 if (Iflag) { 420 if (isupper(c1)) --- 7 unchanged lines hidden (view full) --- 428 SET_N(n2, c2); 429 c1 = getc(Sort_1); 430 c2 = getc(Sort_2); 431 } 432 if (IS_END(c1, n1)) 433 c1 = 0; 434 if (IS_END(c2, n2)) 435 c2 = 0; | 401 while (!isalnum(c1 = getc(Sort_1)) && c1 != '\0' && c1 != EOF) 402 SET_N(n1, c1); 403 while (!isalnum(c2 = getc(Sort_2)) && c2 != '\0' && c2 != EOF) 404 SET_N(n2, c2); 405 406 while (!IS_END(c1, n1) && !IS_END(c2, n2)) { 407 if (Iflag) { 408 if (isupper(c1)) --- 7 unchanged lines hidden (view full) --- 416 SET_N(n2, c2); 417 c1 = getc(Sort_1); 418 c2 = getc(Sort_2); 419 } 420 if (IS_END(c1, n1)) 421 c1 = 0; 422 if (IS_END(c2, n2)) 423 c2 = 0; |
424 |
|
436 return (stable_collate_range_cmp(c1, c2)); 437} 438 439/* 440 * randomize: 441 * Randomize the order of the string table. We must be careful 442 * not to randomize across delimiter boundaries. All 443 * randomization is done within each block. 444 */ 445void 446randomize(void) 447{ 448 uint32_t cnt, i; | 425 return (stable_collate_range_cmp(c1, c2)); 426} 427 428/* 429 * randomize: 430 * Randomize the order of the string table. We must be careful 431 * not to randomize across delimiter boundaries. All 432 * randomization is done within each block. 433 */ 434void 435randomize(void) 436{ 437 uint32_t cnt, i; |
449 off_t tmp; 450 off_t *sp; | 438 off_t tmp; 439 off_t *sp; |
451 452#if __FreeBSD_version < 800041 453 srandomdev(); 454#endif 455 456 Tbl.str_flags |= STR_RANDOM; 457 cnt = Tbl.str_numstr; 458 --- 15 unchanged lines hidden --- | 440 441#if __FreeBSD_version < 800041 442 srandomdev(); 443#endif 444 445 Tbl.str_flags |= STR_RANDOM; 446 cnt = Tbl.str_numstr; 447 --- 15 unchanged lines hidden --- |