BSD 4 development
[unix-history] / usr / src / games / fortune / strfile.c
CommitLineData
38ae4d69
BJ
1# include <stdio.h>
2# include "strfile.h"
3
4/*
5 * This program takes a file composed of strings seperated by
6 * lines starting with two consecutive delimiting character (default
7 * character is '%') and creates another file which consists of a table
8 * describing the file (structure from "strfile.h"), a table of seek
9 * pointers to the start of the strings, and the strings, each terinated
10 * by a null byte. Usage:
11 *
12 * % strfile [ - ] [ -cC ] [ -sv ] sourcefile [ datafile ]
13 *
14 * - - Give a usage summary useful for jogging the memory
15 * c - Change delimiting character from '%' to 'C'
16 * s - Silent. Give no summary of data processed at the end of
17 * the run.
18 * v - Verbose. Give summary of data processed. (Default)
19 *
20 * Ken Arnold Sept. 7, 1978
21 *
22 * Added method to indicate dividers. A "%-" will cause the address
23 * to be added to the structure in one of the pointer elements.
24 */
25
26# define reg register
27
28# define DELIM_CH '-'
29
30char *infile = 0, /* input file name */
31 outfile[100] = "", /* output file name */
32 delimch = '%', /* delimiting character */
33 *usage[] = { /* usage summary */
34 "usage: strfile [ - ] [ -cC ] [ -sv ] inputfile [ datafile ]",
35 " - - Give this usage summary",
36 " c - Replace delimiting character with 'C'",
37 " s - Silent. Give no summary",
38 " v - Verbose. Give summary. (default)",
39 " Default \"datafile\" is inputfile.dat",
40 0
41 },
42 *fgets();
43
44short sflag = 0; /* silent run flag */
45
46long ftell(), *calloc();
47
48STRFILE tbl; /* statistics table */
49
50main(ac, av)
51int ac;
52char *av[]; {
53
54 reg char *sp, dc;
55 reg long *lp;
56 char string[257];
57 int curseek, /* number of strings */
58 delim; /* current delimiter number */
59 long *seekpts,li; /* table of seek pointers */
60 FILE *inf, *outf;
61
62 getargs(ac, av); /* evalute arguments */
63
64 /*
65 * initial counting of input file
66 */
67
68 dc = delimch;
69 if ((inf = fopen(infile, "r")) == NULL) {
70 perror(infile);
71 exit(-1);
72 }
73 for (curseek = 0; (sp = fgets(string, 256, inf)) != NULL; )
74 if (*sp++ == dc && (*sp == dc || *sp == DELIM_CH))
75 curseek++;
76 curseek++;
77
78 /*
79 * save space at begginning of file for tables
80 */
81
82 if ((outf = fopen(outfile, "w")) == NULL) {
83 perror(outfile);
84 exit(-1);
85 }
86 if ((seekpts = calloc(sizeof *seekpts, curseek)) == NULL) {
87 perror("calloc");
88 exit(-1);
89 }
90 fwrite(&tbl, sizeof tbl, 1, outf);
91 fwrite(seekpts, sizeof *seekpts, curseek, outf);
92 *seekpts = ftell(outf);
93 fseek(inf, (long) 0, 0); /* goto start of input */
94
95 /*
96 * write the strings onto the file
97 */
98
99 tbl.str_longlen = -1;
100 tbl.str_shortlen = 0077777;
101 lp = seekpts;
102 do {
103 sp = fgets(string, 256, inf);
104 if (sp == NULL
105 || (*sp == dc && (sp[1] == dc || sp[1] == DELIM_CH))) {
106 putc('\0', outf);
107 lp++;
108 if (sp != NULL)
109 *lp = ftell(outf);
110 li = ftell(outf) - lp[-1] - 1;
111 if (tbl.str_longlen < li)
112 tbl.str_longlen = li;
113 if (tbl.str_shortlen > li)
114 tbl.str_shortlen = li;
115 if (sp[1] == DELIM_CH && delim < MAXDELIMS)
116 tbl.str_delims[delim++] = lp - seekpts;
117 }
118 else
119 fputs(sp, outf);
120 } while (sp != NULL);
121
122 /*
123 * write the tables in
124 */
125
126 fclose(inf);
127 tbl.str_numstr = curseek;
128 fseek(outf, (long) 0, 0);
129 fwrite(&tbl, sizeof tbl, 1, outf);
130 fwrite(seekpts, sizeof *seekpts, curseek, outf);
131 fclose(outf);
132 if (!sflag) {
133 printf("\"%s\" converted to \"%s\"\n", infile, outfile);
134 if (curseek == 1)
135 puts("There was 1 string");
136 else
137 printf("There were %d strings\n", curseek);
138 printf("Longest string: %d byte%s", tbl.str_longlen, tbl.str_longlen == 1 ? "\n" : "s\n");
139 printf("Shortest string: %d byte%s", tbl.str_shortlen, tbl.str_shortlen == 1 ? "\n" : "s\n");
140 }
141}
142/*
143 * This routine evaluates arguments from the command line
144 */
145getargs(ac, av)
146int ac;
147char *av[]; {
148
149 reg char **argv, *sp;
150 reg int i;
151 int bad, j;
152
153 bad = 0;
154 argv = &av[0];
155 for (i = 1; i < ac; i++)
156 if (*argv[i] == '-')
157 if (argv[i][1]) for (sp = &argv[i][1]; *sp; sp++)
158 switch (*sp) {
159 case 'c': /* new delimiting char */
160 if ((delimch = *++sp) == '\0') {
161 --sp;
162 delimch = *argv[++i];
163 }
164 if (delimch <= 0 || delimch > '~' || delimch == DELIM_CH) {
165 printf("bad delimiting character: \\%o\n", delimch);
166 bad++;
167 }
168 break;
169 case 's': /* silent */
170 sflag++;
171 break;
172 case 'v': /* verbose */
173 sflag = 0;
174 break;
175 default: /* unknown flag */
176 bad++;
177 printf("bad flag: '%c'\n", *sp);
178 break;
179 }
180 else {
181 for (j = 0; usage[j]; j++)
182 puts(usage[j]);
183 exit(0);
184 }
185 else if (infile)
186 strcpy(outfile, argv[i]);
187 else
188 infile = argv[i];
189 if (!infile) {
190 bad++;
191 puts("No input file name");
192 }
193 if (*outfile == '\0' && !bad) {
194 strcpy(outfile, infile);
195 strcat(outfile, ".dat");
196 }
197 if (bad) {
198 puts("use \"strfile -\" to get usage");
199 exit(-1);
200 }
201}