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