Listing 1

  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 */