Commit | Line | Data |
---|---|---|
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 | ||
30 | char *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 | ||
44 | short sflag = 0; /* silent run flag */ | |
45 | ||
46 | long ftell(), *calloc(); | |
47 | ||
48 | STRFILE tbl; /* statistics table */ | |
49 | ||
50 | main(ac, av) | |
51 | int ac; | |
52 | char *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 | */ | |
145 | getargs(ac, av) | |
146 | int ac; | |
147 | char *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 | } |