1: /*********************************************************
2: * MAXL.C: Analyze line lengths to help slim down
3: * code listings for publications such as CUJ
4: * Written by Leor Zolman, 12/89, 2/91
5: * What it does:
6: * Scans the input file, keeping track of the number of
7: * lines of each varying length encountered.
8: * Displays first instance of each of the n longest
9: * line lengths encountered, along with frequency.
10: * Hard tab interpretation may be set to any value.
11: *
12: * Usage: maxl [-t#] [-d%] [-f$] filename
13: * # = soft tab setting (defaults to 4)
14: * % = how many different lengths to display (def. 3)
15: * $ = flag lines longer than this length (def. 79)
16: * Compile:
17: * Borland C:
18: * bcc maxl.c
19: * Xenix C:
20: * cc maxl.c -o maxl
21: *********************************************************/
22:
23:
24: #include <stdio.h>
25:
26: #define MAXLINE 300 /* longest allowable line */
27: #define DEFAULT_TAB 4 /* default soft tab setting */
28: #define DIFF_SIZES 3 /* # of diff. sizes to show */
29: #define DEF_FLAG 79 /* flag lines longer than...*/
30:
31: void putrule(int); /* draw a horizontal line */
32: void putline(char *, int);
33:
34: struct line {
35: int first; /* line # of first instance */
36: char *text; /* the text of 1st instance */
37: int how_many; /* # of lines that length */
38: } lines[MAXLINE]; /* one for each length */
39:
40: int tabstop = DEFAULT_TAB;
41: int diffsizes = DIFF_SIZES;
42: int flaglen = DEF_FLAG;
43:
44: void main(argc, argv)
45: int argc;
46: char **argv;
47: {
48: int v_col; /* virtual column number */
49: int lineno; /* line number of current line */
50: char lbuf[MAXLINE]; /* input line buffer */
51: char c, *lp;
52: FILE *fp;
53: int i, j;
54:
55: for (i = 1; i <argc; i++)
56: if (argv[i][0] == '-')
57: {
58: switch (tolower(argv [i] [1]))
59: {
60: case 't': tabstop = atoi(&argv[i][2]);
61: break;
62:
63: case 'd': diffsizes = atoi(&argv[i][2]);
64: break;
65:
66: case 'f': flaglen = atoi(&argv[i][2]);
67: break;
68:
69: default: printf("Unknown option: '%s'\n",
70: argv[i]);
71: exit(0);
72: }
73: for (j = i; j < argc - 1; j++)
74: argv[j] = argv[j + 1];
75: argc--;
76: i--;
77: }
78:
79: if (argc != 2)
80: {
81: fprintf(stderr,
82: "Usage: %s [-t#] [-d#] [f#] file\n", argv[0]);
83: fprintf(stderr,
84: "-t#: Set hard tab value\n");
85: fprintf(stderr,
86: "-d#: Set number of different lengths to show\n");
87: fprintf(stderr,
88: "-f#: Flag lines longer than # characters\n");
89: exit(1);
9O: }
91:
92: if ((fp= fopen(argv[1], "r")) == NULL)
93: exit(printf("Can't open %s for input.\n", argv[1]));
94:
95: for (i = 0; i <= MAXLINE; i++)
96: lines[i].how_many = 0; /* none found yet */
97: lineno = 1;
98:
99: while (fgets(lbuf, MAXLINE, fp) != NULL)
100: {
101: v_col = 1; /* track virtual column # */
102: for (lp = lbuf; c= *lp; lp++)
103: {
104: if (c == '\n') /* newline is end of line */
105: break;
106:
107: if (c == '\t') /* tab is interpreted as a */
108: while (v_col++ % tabstop) /* # of spaces */
109: ;
110: else if (c == '\r') /* CR sans newline is a */
111: { /* special twisted case */
112: fprintf(stderr,
113: "WARNING: CR before newline in line %d\n",
114: lineno);
115: v_col = 1; /* back to the left margin */
116: }
117: else
118: v_col++; /* all printing chars */
119: }
120: v_col-; /* adjust to ending col. # */
121: if (v_col >= flaglen)
122: fprintf(stderr,
123: "\aLine #%d: %d columns exceeds maximum (%d)\n",
124: lineno, v_col , flaglen);
125: /* bump counter for length */
126: if (!lines[v_col].how_many++) /* first time for */
127: { /* this length? if so... */
128: lines[v_col].first = lineno; /* save line #, */
129: if ((lines[v_col].text = /* & save text */
130: char *) malloc(strlen(lbuf) + 1)) == NULL)
131: {
132: fprintf(stderr,
133: "Out of memory in line %d\n", lineno);
134: exit(1);
135: }
136: strcpy(lines[v_col].text, lbuf);
137: }
138: lineno++;
139: }
140:
141: printf("\n");
142: j = 0; /* # of diff. lengths shown */
143: for (i = MAXLINE -1; i > 0; i--) /* display results */
144: {
145: if (!lines[i].how_many)
146: continue;
147: printf("Length: %d First instance: line #%d",
148: i, lines[i].first);
149: printf(" Quantity: %d\n", lines[i].how_many);
150: putline(lines[i].text, i);
151: if (++j == diffsizes)
152: break;
153: printf("\n");
154: }
155: fclose(fp);
156: }
157:
158:
159: /*
160: * putline(): Display a line of text, with rule line
161: * before and after
162: */
163:
164: void putline(line, length)
165: char *line;
166: int length;
167: {
168: char *lp, c;
169: int v_col;
170:
171: putrule(length);
172: for (lp = line, v_col = 1; c = *lp; lp++)
173: switch (c)
174: {
175: case '\t': /* translate tabs to spaces */
176: do
177: putchar(' ');
178: while (v_col++ % tabstop);
179: break;
180: default:
181: putchar(c);
182: v_col++;
183: }
184: putrule(length);
185: }
186:
187:
188: /*
189: * putrule(): display a horizontal line so trailing
190: * whitespace is detectable
191: */
192:
193: void putrule(ncols)
194: int ncols;
195: {
196: int i;
197:
198: for (i = 0; i < ncols; i++)
199: putchar('=');
200: putchar('\n');
201: }
/* End of File */