1 /*
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11
12 #include <stdio.h>
13 #include <ctype.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include "error.h"
17
18 int wordc; /* how long the current error message is */
19 char **wordv; /* the actual error message */
20
21 int nerrors;
22 int language;
23
24 Errorclass onelong();
25 Errorclass cpp();
26 Errorclass pccccom(); /* Portable C Compiler C Compiler */
27 Errorclass richieccom(); /* Richie Compiler for 11 */
28 Errorclass lint0();
29 Errorclass lint1();
30 Errorclass lint2();
31 Errorclass lint3();
32 Errorclass make();
33 Errorclass f77();
34 Errorclass pi();
35 Errorclass ri();
36 Errorclass troff();
37 Errorclass mod2();
38 /*
39 * Eat all of the lines in the input file, attempting to categorize
40 * them by their various flavors
41 */
42 static char inbuffer[BUFSIZ];
43
eaterrors(r_errorc,r_errorv)44 eaterrors(r_errorc, r_errorv)
45 int *r_errorc;
46 Eptr **r_errorv;
47 {
48 extern boolean piflag;
49 Errorclass errorclass = C_SYNC;
50
51 for (;;){
52 if (fgets(inbuffer, BUFSIZ, errorfile) == NULL)
53 break;
54 wordvbuild(inbuffer, &wordc, &wordv);
55 /*
56 * for convience, convert wordv to be 1 based, instead
57 * of 0 based.
58 */
59 wordv -= 1;
60 if ( wordc > 0 &&
61 ((( errorclass = onelong() ) != C_UNKNOWN)
62 || (( errorclass = cpp() ) != C_UNKNOWN)
63 || (( errorclass = pccccom() ) != C_UNKNOWN)
64 || (( errorclass = richieccom() ) != C_UNKNOWN)
65 || (( errorclass = lint0() ) != C_UNKNOWN)
66 || (( errorclass = lint1() ) != C_UNKNOWN)
67 || (( errorclass = lint2() ) != C_UNKNOWN)
68 || (( errorclass = lint3() ) != C_UNKNOWN)
69 || (( errorclass = make() ) != C_UNKNOWN)
70 || (( errorclass = f77() ) != C_UNKNOWN)
71 || ((errorclass = pi() ) != C_UNKNOWN)
72 || (( errorclass = ri() )!= C_UNKNOWN)
73 || (( errorclass = mod2() )!= C_UNKNOWN)
74 || (( errorclass = troff() )!= C_UNKNOWN))
75 ) ;
76 else
77 errorclass = catchall();
78 if (wordc)
79 erroradd(wordc, wordv+1, errorclass, C_UNKNOWN);
80 }
81 #ifdef FULLDEBUG
82 printf("%d errorentrys\n", nerrors);
83 #endif
84 arrayify(r_errorc, r_errorv, er_head);
85 }
86
87 /*
88 * create a new error entry, given a zero based array and count
89 */
erroradd(errorlength,errorv,errorclass,errorsubclass)90 erroradd(errorlength, errorv, errorclass, errorsubclass)
91 int errorlength;
92 char **errorv;
93 Errorclass errorclass;
94 Errorclass errorsubclass;
95 {
96 reg Eptr newerror;
97 reg char *cp;
98
99 if (errorclass == C_TRUE){
100 /* check canonicalization of the second argument*/
101 for(cp = errorv[1]; *cp && isdigit(*cp); cp++)
102 continue;
103 errorclass = (*cp == '\0') ? C_TRUE : C_NONSPEC;
104 #ifdef FULLDEBUG
105 if (errorclass != C_TRUE)
106 printf("The 2nd word, \"%s\" is not a number.\n",
107 errorv[1]);
108 #endif
109 }
110 if (errorlength > 0){
111 newerror = (Eptr)Calloc(1, sizeof(Edesc));
112 newerror->error_language = language; /* language is global */
113 newerror->error_text = errorv;
114 newerror->error_lgtext = errorlength;
115 if (errorclass == C_TRUE)
116 newerror->error_line = atoi(errorv[1]);
117 newerror->error_e_class = errorclass;
118 newerror->error_s_class = errorsubclass;
119 switch(newerror->error_e_class = discardit(newerror)){
120 case C_SYNC: nsyncerrors++; break;
121 case C_DISCARD: ndiscard++; break;
122 case C_NULLED: nnulled++; break;
123 case C_NONSPEC: nnonspec++; break;
124 case C_THISFILE: nthisfile++; break;
125 case C_TRUE: ntrue++; break;
126 case C_UNKNOWN: nunknown++; break;
127 case C_IGNORE: nignore++; break;
128 }
129 newerror->error_next = er_head;
130 er_head = newerror;
131 newerror->error_no = nerrors++;
132 } /* length > 0 */
133 }
134
onelong()135 Errorclass onelong()
136 {
137 char **nwordv;
138 if ( (wordc == 1) && (language != INLD) ){
139 /*
140 * We have either:
141 * a) file name from cc
142 * b) Assembler telling world that it is complaining
143 * c) Noise from make ("Stop.")
144 * c) Random noise
145 */
146 wordc = 0;
147 if (strcmp(wordv[1], "Stop.") == 0){
148 language = INMAKE; return(C_SYNC);
149 }
150 if (strcmp(wordv[1], "Assembler:") == 0){
151 /* assembler always alerts us to what happened*/
152 language = INAS; return(C_SYNC);
153 } else
154 if (strcmp(wordv[1], "Undefined:") == 0){
155 /* loader complains about unknown symbols*/
156 language = INLD; return(C_SYNC);
157 }
158 if (lastchar(wordv[1]) == ':'){
159 /* cc tells us what file we are in */
160 currentfilename = wordv[1];
161 (void)substitute(currentfilename, ':', '\0');
162 language = INCC; return(C_SYNC);
163 }
164 } else
165 if ( (wordc == 1) && (language == INLD) ){
166 nwordv = (char **)Calloc(4, sizeof(char *));
167 nwordv[0] = "ld:";
168 nwordv[1] = wordv[1];
169 nwordv[2] = "is";
170 nwordv[3] = "undefined.";
171 wordc = 4;
172 wordv = nwordv - 1;
173 return(C_NONSPEC);
174 } else
175 if (wordc == 1){
176 return(C_SYNC);
177 }
178 return(C_UNKNOWN);
179 } /* end of one long */
180
cpp()181 Errorclass cpp()
182 {
183 /*
184 * Now attempt a cpp error message match
185 * Examples:
186 * ./morse.h: 23: undefined control
187 * morsesend.c: 229: MAGNIBBL: argument mismatch
188 * morsesend.c: 237: MAGNIBBL: argument mismatch
189 * test1.c: 6: undefined control
190 */
191 if ( (language != INLD) /* loader errors have almost same fmt*/
192 && (lastchar(wordv[1]) == ':')
193 && (isdigit(firstchar(wordv[2])))
194 && (lastchar(wordv[2]) == ':') ){
195 language = INCPP;
196 clob_last(wordv[1], '\0');
197 clob_last(wordv[2], '\0');
198 return(C_TRUE);
199 }
200 return(C_UNKNOWN);
201 } /*end of cpp*/
202
pccccom()203 Errorclass pccccom()
204 {
205 /*
206 * Now attempt a ccom error message match:
207 * Examples:
208 * "morsesend.c", line 237: operands of & have incompatible types
209 * "test.c", line 7: warning: old-fashioned initialization: use =
210 * "subdir.d/foo2.h", line 1: illegal initialization
211 */
212 if ( (firstchar(wordv[1]) == '"')
213 && (lastchar(wordv[1]) == ',')
214 && (next_lastchar(wordv[1]) == '"')
215 && (strcmp(wordv[2],"line") == 0)
216 && (isdigit(firstchar(wordv[3])))
217 && (lastchar(wordv[3]) == ':') ){
218 clob_last(wordv[1], '\0'); /* drop last , */
219 clob_last(wordv[1], '\0'); /* drop last " */
220 wordv[1]++; /* drop first " */
221 clob_last(wordv[3], '\0'); /* drop : on line number */
222 wordv[2] = wordv[1]; /* overwrite "line" */
223 wordv++; /*compensate*/
224 wordc--;
225 currentfilename = wordv[1];
226 language = INCC;
227 return(C_TRUE);
228 }
229 return(C_UNKNOWN);
230 } /* end of ccom */
231 /*
232 * Do the error message from the Richie C Compiler for the PDP11,
233 * which has this source:
234 *
235 * if (filename[0])
236 * fprintf(stderr, "%s:", filename);
237 * fprintf(stderr, "%d: ", line);
238 *
239 */
richieccom()240 Errorclass richieccom()
241 {
242 reg char *cp;
243 reg char **nwordv;
244 char *file;
245
246 if (lastchar(wordv[1]) == ':'){
247 cp = wordv[1] + strlen(wordv[1]) - 1;
248 while (isdigit(*--cp))
249 continue;
250 if (*cp == ':'){
251 clob_last(wordv[1], '\0'); /* last : */
252 *cp = '\0'; /* first : */
253 file = wordv[1];
254 nwordv = wordvsplice(1, wordc, wordv+1);
255 nwordv[0] = file;
256 nwordv[1] = cp + 1;
257 wordc += 1;
258 wordv = nwordv - 1;
259 language = INCC;
260 currentfilename = wordv[1];
261 return(C_TRUE);
262 }
263 }
264 return(C_UNKNOWN);
265 }
266
lint0()267 Errorclass lint0()
268 {
269 reg char **nwordv;
270 char *line, *file;
271 /*
272 * Attempt a match for the new lint style normal compiler
273 * error messages, of the form
274 *
275 * printf("%s(%d): %s\n", filename, linenumber, message);
276 */
277 if (wordc >= 2){
278 if ( (lastchar(wordv[1]) == ':')
279 && (next_lastchar(wordv[1]) == ')')
280 ) {
281 clob_last(wordv[1], '\0'); /* colon */
282 if (persperdexplode(wordv[1], &line, &file)){
283 nwordv = wordvsplice(1, wordc, wordv+1);
284 nwordv[0] = file; /* file name */
285 nwordv[1] = line; /* line number */
286 wordc += 1;
287 wordv = nwordv - 1;
288 language = INLINT;
289 return(C_TRUE);
290 }
291 wordv[1][strlen(wordv[1])] = ':';
292 }
293 }
294 return (C_UNKNOWN);
295 }
296
lint1()297 Errorclass lint1()
298 {
299 char *line1, *line2;
300 char *file1, *file2;
301 char **nwordv1, **nwordv2;
302
303 /*
304 * Now, attempt a match for the various errors that lint
305 * can complain about.
306 *
307 * Look first for type 1 lint errors
308 */
309 if (wordc > 1 && strcmp(wordv[wordc-1], "::") == 0){
310 /*
311 * %.7s, arg. %d used inconsistently %s(%d) :: %s(%d)
312 * %.7s value used inconsistently %s(%d) :: %s(%d)
313 * %.7s multiply declared %s(%d) :: %s(%d)
314 * %.7s value declared inconsistently %s(%d) :: %s(%d)
315 * %.7s function value type must be declared before use %s(%d) :: %s(%d)
316 */
317 language = INLINT;
318 if (wordc > 2
319 && (persperdexplode(wordv[wordc], &line2, &file2))
320 && (persperdexplode(wordv[wordc-2], &line1, &file1)) ){
321 nwordv1 = wordvsplice(2, wordc, wordv+1);
322 nwordv2 = wordvsplice(2, wordc, wordv+1);
323 nwordv1[0] = file1; nwordv1[1] = line1;
324 erroradd(wordc+2, nwordv1, C_TRUE, C_DUPL); /* takes 0 based*/
325 nwordv2[0] = file2; nwordv2[1] = line2;
326 wordc = wordc + 2;
327 wordv = nwordv2 - 1; /* 1 based */
328 return(C_TRUE);
329 }
330 }
331 return(C_UNKNOWN);
332 } /* end of lint 1*/
333
lint2()334 Errorclass lint2()
335 {
336 char *file;
337 char *line;
338 char **nwordv;
339 /*
340 * Look for type 2 lint errors
341 *
342 * %.7s used( %s(%d) ), but not defined
343 * %.7s defined( %s(%d) ), but never used
344 * %.7s declared( %s(%d) ), but never used or defined
345 *
346 * bufp defined( "./metric.h"(10) ), but never used
347 */
348 if ( (lastchar(wordv[2]) == '(' /* ')' */ )
349 && (strcmp(wordv[4], "),") == 0) ){
350 language = INLINT;
351 if (persperdexplode(wordv[3], &line, &file)){
352 nwordv = wordvsplice(2, wordc, wordv+1);
353 nwordv[0] = file; nwordv[1] = line;
354 wordc = wordc + 2;
355 wordv = nwordv - 1; /* 1 based */
356 return(C_TRUE);
357 }
358 }
359 return(C_UNKNOWN);
360 } /* end of lint 2*/
361
362 char *Lint31[4] = {"returns", "value", "which", "is"};
363 char *Lint32[6] = {"value", "is", "used,", "but", "none", "returned"};
lint3()364 Errorclass lint3()
365 {
366 if ( (wordvcmp(wordv+2, 4, Lint31) == 0)
367 || (wordvcmp(wordv+2, 6, Lint32) == 0) ){
368 language = INLINT;
369 return(C_NONSPEC);
370 }
371 return(C_UNKNOWN);
372 }
373
374 /*
375 * Special word vectors for use by F77 recognition
376 */
377 char *F77_fatal[3] = {"Compiler", "error", "line"};
378 char *F77_error[3] = {"Error", "on", "line"};
379 char *F77_warning[3] = {"Warning", "on", "line"};
380 char *F77_no_ass[3] = {"Error.","No","assembly."};
f77()381 f77()
382 {
383 char **nwordv;
384 /*
385 * look for f77 errors:
386 * Error messages from /usr/src/cmd/f77/error.c, with
387 * these printf formats:
388 *
389 * Compiler error line %d of %s: %s
390 * Error on line %d of %s: %s
391 * Warning on line %d of %s: %s
392 * Error. No assembly.
393 */
394 if (wordc == 3 && wordvcmp(wordv+1, 3, F77_no_ass) == 0) {
395 wordc = 0;
396 return(C_SYNC);
397 }
398 if (wordc < 6)
399 return(C_UNKNOWN);
400 if ( (lastchar(wordv[6]) == ':')
401 &&(
402 (wordvcmp(wordv+1, 3, F77_fatal) == 0)
403 || (wordvcmp(wordv+1, 3, F77_error) == 0)
404 || (wordvcmp(wordv+1, 3, F77_warning) == 0) )
405 ){
406 language = INF77;
407 nwordv = wordvsplice(2, wordc, wordv+1);
408 nwordv[0] = wordv[6];
409 clob_last(nwordv[0],'\0');
410 nwordv[1] = wordv[4];
411 wordc += 2;
412 wordv = nwordv - 1; /* 1 based */
413 return(C_TRUE);
414 }
415 return(C_UNKNOWN);
416 } /* end of f77 */
417
418 char *Make_Croak[3] = {"***", "Error", "code"};
419 char *Make_NotRemade[5] = {"not", "remade", "because", "of", "errors"};
make()420 Errorclass make()
421 {
422 if (wordvcmp(wordv+1, 3, Make_Croak) == 0){
423 language = INMAKE;
424 return(C_SYNC);
425 }
426 if (wordvcmp(wordv+2, 5, Make_NotRemade) == 0){
427 language = INMAKE;
428 return(C_SYNC);
429 }
430 return(C_UNKNOWN);
431 }
ri()432 Errorclass ri()
433 {
434 /*
435 * Match an error message produced by ri; here is the
436 * procedure yanked from the distributed version of ri
437 * April 24, 1980.
438 *
439 * serror(str, x1, x2, x3)
440 * char str[];
441 * char *x1, *x2, *x3;
442 * {
443 * extern int yylineno;
444 *
445 * putc('"', stdout);
446 * fputs(srcfile, stdout);
447 * putc('"', stdout);
448 * fprintf(stdout, " %d: ", yylineno);
449 * fprintf(stdout, str, x1, x2, x3);
450 * fprintf(stdout, "\n");
451 * synerrs++;
452 * }
453 */
454 if ( (firstchar(wordv[1]) == '"')
455 &&(lastchar(wordv[1]) == '"')
456 &&(lastchar(wordv[2]) == ':')
457 &&(isdigit(firstchar(wordv[2]))) ){
458 clob_last(wordv[1], '\0'); /* drop the last " */
459 wordv[1]++; /* skip over the first " */
460 clob_last(wordv[2], '\0');
461 language = INRI;
462 return(C_TRUE);
463 }
464 return(C_UNKNOWN);
465 }
466
catchall()467 Errorclass catchall()
468 {
469 /*
470 * Catches random things.
471 */
472 language = INUNKNOWN;
473 return(C_NONSPEC);
474 } /* end of catch all*/
475
troff()476 Errorclass troff()
477 {
478 /*
479 * troff source error message, from eqn, bib, tbl...
480 * Just like pcc ccom, except uses `'
481 */
482 if ( (firstchar(wordv[1]) == '`')
483 && (lastchar(wordv[1]) == ',')
484 && (next_lastchar(wordv[1]) == '\'')
485 && (strcmp(wordv[2],"line") == 0)
486 && (isdigit(firstchar(wordv[3])))
487 && (lastchar(wordv[3]) == ':') ){
488 clob_last(wordv[1], '\0'); /* drop last , */
489 clob_last(wordv[1], '\0'); /* drop last " */
490 wordv[1]++; /* drop first " */
491 clob_last(wordv[3], '\0'); /* drop : on line number */
492 wordv[2] = wordv[1]; /* overwrite "line" */
493 wordv++; /*compensate*/
494 currentfilename = wordv[1];
495 language = INTROFF;
496 return(C_TRUE);
497 }
498 return(C_UNKNOWN);
499 }
mod2()500 Errorclass mod2()
501 {
502 /*
503 * for decwrl modula2 compiler (powell)
504 */
505 if ( ( (strcmp(wordv[1], "!!!") == 0) /* early version */
506 ||(strcmp(wordv[1], "File") == 0)) /* later version */
507 && (lastchar(wordv[2]) == ',') /* file name */
508 && (strcmp(wordv[3], "line") == 0)
509 && (isdigit(firstchar(wordv[4]))) /* line number */
510 && (lastchar(wordv[4]) == ':') /* line number */
511 ){
512 clob_last(wordv[2], '\0'); /* drop last , on file name */
513 clob_last(wordv[4], '\0'); /* drop last : on line number */
514 wordv[3] = wordv[2]; /* file name on top of "line" */
515 wordv += 2;
516 wordc -= 2;
517 currentfilename = wordv[1];
518 language = INMOD2;
519 return(C_TRUE);
520 }
521 return(C_UNKNOWN);
522 }
523