* 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
* % 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
* 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.
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",
short sflag
= 0; /* silent run flag */
STRFILE tbl
; /* statistics table */
int curseek
, /* number of strings */
delim
; /* current delimiter number */
long *seekpts
,li
; /* table of seek pointers */
getargs(ac
, av
); /* evalute arguments */
* initial counting of input file
if ((inf
= fopen(infile
, "r")) == NULL
) {
for (curseek
= 0; (sp
= fgets(string
, 256, inf
)) != NULL
; )
if (*sp
++ == dc
&& (*sp
== dc
|| *sp
== DELIM_CH
))
* save space at begginning of file for tables
if ((outf
= fopen(outfile
, "w")) == NULL
) {
if ((seekpts
= calloc(sizeof *seekpts
, curseek
)) == NULL
) {
fwrite(&tbl
, sizeof tbl
, 1, outf
);
fwrite(seekpts
, sizeof *seekpts
, curseek
, outf
);
fseek(inf
, (long) 0, 0); /* goto start of input */
* write the strings onto the file
tbl
.str_shortlen
= 0077777;
sp
= fgets(string
, 256, inf
);
|| (*sp
== dc
&& (sp
[1] == dc
|| sp
[1] == DELIM_CH
))) {
li
= ftell(outf
) - lp
[-1] - 1;
if (tbl
.str_longlen
< li
)
if (tbl
.str_shortlen
> li
)
if (sp
[1] == DELIM_CH
&& delim
< MAXDELIMS
)
tbl
.str_delims
[delim
++] = lp
- seekpts
;
tbl
.str_numstr
= curseek
;
fseek(outf
, (long) 0, 0);
fwrite(&tbl
, sizeof tbl
, 1, outf
);
fwrite(seekpts
, sizeof *seekpts
, curseek
, outf
);
printf("\"%s\" converted to \"%s\"\n", infile
, outfile
);
puts("There was 1 string");
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
if (argv
[i
][1]) for (sp
= &argv
[i
][1]; *sp
; sp
++)
case 'c': /* new delimiting char */
if ((delimch
= *++sp
) == '\0') {
if (delimch
<= 0 || delimch
> '~' || delimch
== DELIM_CH
) {
printf("bad delimiting character: \\%o\n", delimch
);
default: /* unknown flag */
printf("bad flag: '%c'\n", *sp
);
for (j
= 0; usage
[j
]; j
++)
strcpy(outfile
, argv
[i
]);
puts("No input file name");
if (*outfile
== '\0' && !bad
) {
puts("use \"strfile -\" to get usage");