BSD 4 release
[unix-history] / usr / src / games / fortune / strfile.c
# include <stdio.h>
# include "strfile.h"
/*
* This program takes a file composed of strings seperated by
* lines starting with two consecutive delimiting character (default
* character is '%') and creates another file which consists of a table
* describing the file (structure from "strfile.h"), a table of seek
* pointers to the start of the strings, and the strings, each terinated
* by a null byte. Usage:
*
* % strfile [ - ] [ -cC ] [ -sv ] sourcefile [ datafile ]
*
* - - Give a usage summary useful for jogging the memory
* c - Change delimiting character from '%' to 'C'
* s - Silent. Give no summary of data processed at the end of
* the run.
* v - Verbose. Give summary of data processed. (Default)
*
* Ken Arnold Sept. 7, 1978
*
* Added method to indicate dividers. A "%-" will cause the address
* to be added to the structure in one of the pointer elements.
*/
# define reg register
# define DELIM_CH '-'
char *infile = 0, /* input file name */
outfile[100] = "", /* output file name */
delimch = '%', /* delimiting character */
*usage[] = { /* usage summary */
"usage: strfile [ - ] [ -cC ] [ -sv ] inputfile [ datafile ]",
" - - Give this usage summary",
" c - Replace delimiting character with 'C'",
" s - Silent. Give no summary",
" v - Verbose. Give summary. (default)",
" Default \"datafile\" is inputfile.dat",
0
},
*fgets();
short sflag = 0; /* silent run flag */
long ftell(), *calloc();
STRFILE tbl; /* statistics table */
main(ac, av)
int ac;
char *av[]; {
reg char *sp, dc;
reg long *lp;
char string[257];
int curseek, /* number of strings */
delim; /* current delimiter number */
long *seekpts,li; /* table of seek pointers */
FILE *inf, *outf;
getargs(ac, av); /* evalute arguments */
/*
* initial counting of input file
*/
dc = delimch;
if ((inf = fopen(infile, "r")) == NULL) {
perror(infile);
exit(-1);
}
for (curseek = 0; (sp = fgets(string, 256, inf)) != NULL; )
if (*sp++ == dc && (*sp == dc || *sp == DELIM_CH))
curseek++;
curseek++;
/*
* save space at begginning of file for tables
*/
if ((outf = fopen(outfile, "w")) == NULL) {
perror(outfile);
exit(-1);
}
if ((seekpts = calloc(sizeof *seekpts, curseek)) == NULL) {
perror("calloc");
exit(-1);
}
fwrite(&tbl, sizeof tbl, 1, outf);
fwrite(seekpts, sizeof *seekpts, curseek, outf);
*seekpts = ftell(outf);
fseek(inf, (long) 0, 0); /* goto start of input */
/*
* write the strings onto the file
*/
tbl.str_longlen = -1;
tbl.str_shortlen = 0077777;
lp = seekpts;
do {
sp = fgets(string, 256, inf);
if (sp == NULL
|| (*sp == dc && (sp[1] == dc || sp[1] == DELIM_CH))) {
putc('\0', outf);
lp++;
if (sp != NULL)
*lp = ftell(outf);
li = ftell(outf) - lp[-1] - 1;
if (tbl.str_longlen < li)
tbl.str_longlen = li;
if (tbl.str_shortlen > li)
tbl.str_shortlen = li;
if (sp[1] == DELIM_CH && delim < MAXDELIMS)
tbl.str_delims[delim++] = lp - seekpts;
}
else
fputs(sp, outf);
} while (sp != NULL);
/*
* write the tables in
*/
fclose(inf);
tbl.str_numstr = curseek;
fseek(outf, (long) 0, 0);
fwrite(&tbl, sizeof tbl, 1, outf);
fwrite(seekpts, sizeof *seekpts, curseek, outf);
fclose(outf);
if (!sflag) {
printf("\"%s\" converted to \"%s\"\n", infile, outfile);
if (curseek == 1)
puts("There was 1 string");
else
printf("There were %d strings\n", curseek);
printf("Longest string: %d byte%s", tbl.str_longlen, tbl.str_longlen == 1 ? "\n" : "s\n");
printf("Shortest string: %d byte%s", tbl.str_shortlen, tbl.str_shortlen == 1 ? "\n" : "s\n");
}
}
/*
* This routine evaluates arguments from the command line
*/
getargs(ac, av)
int ac;
char *av[]; {
reg char **argv, *sp;
reg int i;
int bad, j;
bad = 0;
argv = &av[0];
for (i = 1; i < ac; i++)
if (*argv[i] == '-')
if (argv[i][1]) for (sp = &argv[i][1]; *sp; sp++)
switch (*sp) {
case 'c': /* new delimiting char */
if ((delimch = *++sp) == '\0') {
--sp;
delimch = *argv[++i];
}
if (delimch <= 0 || delimch > '~' || delimch == DELIM_CH) {
printf("bad delimiting character: \\%o\n", delimch);
bad++;
}
break;
case 's': /* silent */
sflag++;
break;
case 'v': /* verbose */
sflag = 0;
break;
default: /* unknown flag */
bad++;
printf("bad flag: '%c'\n", *sp);
break;
}
else {
for (j = 0; usage[j]; j++)
puts(usage[j]);
exit(0);
}
else if (infile)
strcpy(outfile, argv[i]);
else
infile = argv[i];
if (!infile) {
bad++;
puts("No input file name");
}
if (*outfile == '\0' && !bad) {
strcpy(outfile, infile);
strcat(outfile, ".dat");
}
if (bad) {
puts("use \"strfile -\" to get usage");
exit(-1);
}
}