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: }