4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #pragma ident "%Z%%M% %I% %E% SMI"
36 int wordc
; /* how long the current error message is */
37 char **wordv
; /* the actual error message */
42 Errorclass
onelong(void);
44 Errorclass
pccccom(void); /* Portable C Compiler C Compiler */
45 Errorclass
richieccom(void); /* Richie Compiler for 11 */
46 Errorclass
lint0(void);
47 Errorclass
lint1(void);
48 Errorclass
lint2(void);
49 Errorclass
lint3(void);
50 Errorclass
make(void);
54 Errorclass
troff(void);
55 Errorclass
mod2(void);
56 Errorclass
sunf77(void);
58 static Errorclass
catchall(void);
61 * Eat all of the lines in the input file, attempting to categorize
62 * them by their various flavors
64 static char inbuffer
[BUFSIZ
];
67 eaterrors(int *r_errorc
, Eptr
**r_errorv
)
69 Errorclass errorclass
= C_SYNC
;
72 if (fgets(inbuffer
, BUFSIZ
, errorfile
) == NULL
)
74 wordvbuild(inbuffer
, &wordc
, &wordv
);
76 * for convenience, convert wordv to be 1 based, instead
81 * check for sunf77 errors has to be done before
82 * pccccom to be able to distingush between the two
85 (((errorclass
= onelong()) != C_UNKNOWN
) ||
86 ((errorclass
= cpp()) != C_UNKNOWN
) ||
87 ((errorclass
= sunf77()) != C_UNKNOWN
) ||
88 ((errorclass
= pccccom()) != C_UNKNOWN
) ||
89 ((errorclass
= richieccom()) != C_UNKNOWN
) ||
90 ((errorclass
= lint0()) != C_UNKNOWN
) ||
91 ((errorclass
= lint1()) != C_UNKNOWN
) ||
92 ((errorclass
= lint2()) != C_UNKNOWN
) ||
93 ((errorclass
= lint3()) != C_UNKNOWN
) ||
94 ((errorclass
= make()) != C_UNKNOWN
) ||
95 ((errorclass
= f77()) != C_UNKNOWN
) ||
96 ((errorclass
= pi()) != C_UNKNOWN
) ||
97 ((errorclass
= ri()) != C_UNKNOWN
) ||
98 ((errorclass
= troff()) != C_UNKNOWN
) ||
99 ((errorclass
= mod2()) != C_UNKNOWN
) ||
100 ((errorclass
= troff()) != C_UNKNOWN
))) {
103 errorclass
= catchall();
106 erroradd(wordc
, wordv
+1, errorclass
, C_UNKNOWN
);
109 printf("%d errorentrys\n", nerrors
);
111 arrayify(r_errorc
, r_errorv
, er_head
);
115 * create a new error entry, given a zero based array and count
118 erroradd(int errorlength
, char **errorv
, Errorclass errorclass
,
119 Errorclass errorsubclass
)
124 if (errorclass
== C_TRUE
) {
125 /* check canonicalization of the second argument */
126 for (cp
= errorv
[1]; *cp
&& isdigit(*cp
); cp
++)
128 errorclass
= (*cp
== '\0') ? C_TRUE
: C_NONSPEC
;
130 if (errorclass
!= C_TRUE
)
131 printf("The 2nd word, \"%s\" is not a number.\n",
135 if (errorlength
> 0) {
136 newerror
= Calloc(1, sizeof (Edesc
));
137 newerror
->error_language
= language
; /* language is global */
138 newerror
->error_text
= errorv
;
139 newerror
->error_lgtext
= errorlength
;
140 if (errorclass
== C_TRUE
)
141 newerror
->error_line
= atoi(errorv
[1]);
142 newerror
->error_e_class
= errorclass
;
143 newerror
->error_s_class
= errorsubclass
;
144 switch (newerror
->error_e_class
= discardit(newerror
)) {
145 case C_SYNC
: nsyncerrors
++; break;
146 case C_DISCARD
: ndiscard
++; break;
147 case C_NULLED
: nnulled
++; break;
148 case C_NONSPEC
: nnonspec
++; break;
149 case C_THISFILE
: nthisfile
++; break;
150 case C_TRUE
: ntrue
++; break;
151 case C_UNKNOWN
: nunknown
++; break;
152 case C_IGNORE
: nignore
++; break;
154 newerror
->error_next
= er_head
;
156 newerror
->error_no
= nerrors
++;
164 if ((wordc
== 1) && (language
!= INLD
)) {
167 * a) file name from cc
168 * b) Assembler telling world that it is complaining
169 * c) Noise from make ("Stop.")
173 if (wordv
[1] != NULL
&& strcmp(wordv
[1], "Stop.") == 0) {
177 if (wordv
[1] != NULL
) {
178 if (strcmp(wordv
[1], "Assembler:") == 0) {
180 * assembler always alerts us to
185 } else if (strcmp(wordv
[1], "Undefined:") == 0) {
186 /* loader complains about unknown symbols */
191 if (lastchar(wordv
[1]) == ':') {
192 /* cc tells us what file we are in */
193 /* Sunf77 tells us what subroutine we are in */
194 currentfilename
= wordv
[1];
195 (void) substitute(currentfilename
, ':', '\0');
199 } else if ((wordc
== 1) && (language
== INLD
)) {
200 nwordv
= Calloc(4, sizeof (char *));
202 nwordv
[1] = wordv
[1];
204 nwordv
[3] = "undefined.";
208 } else if (wordc
== 1) {
210 * any other single word messages are
211 * considered synchronizing
215 /* Sunf77 may derive 2-word synchronizing messages ending with a `:' */
216 if ((wordc
== 2) && (lastchar(wordv
[2]) == ':')) {
222 } /* end of one long */
228 * Now attempt a cpp error message match
230 * ./morse.h: 23: undefined control
231 * morsesend.c: 229: MAGNIBBL: argument mismatch
232 * morsesend.c: 237: MAGNIBBL: argument mismatch
233 * test1.c: 6: undefined control
235 if ((language
!= INLD
) && /* loader errors have almost same fmt */
236 (lastchar(wordv
[1]) == ':') &&
237 (isdigit(firstchar(wordv
[2]))) &&
238 (lastchar(wordv
[2]) == ':')) {
240 clob_last(wordv
[1], '\0');
241 clob_last(wordv
[2], '\0');
251 * Now attempt a ccom error message match:
253 * "morsesend.c", line 237: operands of & have incompatible types
254 * "test.c", line 7: warning: old-fashioned initialization: use =
255 * "subdir.d/foo2.h", line 1: illegal initialization
257 if ((firstchar(wordv
[1]) == '"') &&
258 (lastchar(wordv
[1]) == ',') &&
259 (next_lastchar(wordv
[1]) == '"') &&
260 (strcmp(wordv
[2], "line") == 0) &&
261 (isdigit(firstchar(wordv
[3]))) &&
262 (lastchar(wordv
[3]) == ':')) {
263 clob_last(wordv
[1], '\0'); /* drop last , */
264 clob_last(wordv
[1], '\0'); /* drop last " */
265 wordv
[1]++; /* drop first " */
266 clob_last(wordv
[3], '\0'); /* drop : on line number */
267 wordv
[2] = wordv
[1]; /* overwrite "line" */
268 wordv
++; /* compensate */
270 currentfilename
= wordv
[1];
278 * Do the error message from the Richie C Compiler for the PDP11,
279 * which has this source:
282 * fprintf(stderr, "%s:", filename);
283 * fprintf(stderr, "%d: ", line);
293 if (lastchar(wordv
[1]) == ':') {
294 cp
= wordv
[1] + strlen(wordv
[1]) - 1;
295 while (isdigit(*--cp
))
298 clob_last(wordv
[1], '\0'); /* last : */
299 *cp
= '\0'; /* first : */
301 nwordv
= wordvsplice(1, wordc
, wordv
+1);
307 currentfilename
= wordv
[1];
320 * Attempt a match for the new lint style normal compiler
321 * error messages, of the form
323 * printf("%s(%d): %s\n", filename, linenumber, message);
326 if ((lastchar(wordv
[1]) == ':') &&
327 (next_lastchar(wordv
[1]) == ')')) {
328 clob_last(wordv
[1], '\0'); /* colon */
329 if (persperdexplode(wordv
[1], &line
, &file
)) {
330 nwordv
= wordvsplice(1, wordc
, wordv
+1);
331 nwordv
[0] = file
; /* file name */
332 nwordv
[1] = line
; /* line number */
338 wordv
[1][strlen(wordv
[1])] = ':';
349 char **nwordv1
, **nwordv2
;
352 * Now, attempt a match for the various errors that lint
353 * can complain about.
355 * Look first for type 1 lint errors
357 if (wordc
> 1 && strcmp(wordv
[wordc
-1], "::") == 0) {
359 * %.7s, arg. %d used inconsistently %s(%d) :: %s(%d)
360 * %.7s value used inconsistently %s(%d) :: %s(%d)
361 * %.7s multiply declared %s(%d) :: %s(%d)
362 * %.7s value declared inconsistently %s(%d) :: %s(%d)
363 * %.7s function value type must be declared before use %s(%d) :: %s(%d)
367 (persperdexplode(wordv
[wordc
], &line2
, &file2
)) &&
368 (persperdexplode(wordv
[wordc
-2], &line1
, &file1
))) {
369 nwordv1
= wordvsplice(2, wordc
, wordv
+1);
370 nwordv2
= wordvsplice(2, wordc
, wordv
+1);
371 nwordv1
[0] = file1
; nwordv1
[1] = line1
;
373 erroradd(wordc
+2, nwordv1
, C_TRUE
, C_DUPL
);
374 nwordv2
[0] = file2
; nwordv2
[1] = line2
;
376 wordv
= nwordv2
- 1; /* 1 based */
390 * Look for type 2 lint errors
392 * %.7s used( %s(%d) ), but not defined
393 * %.7s defined( %s(%d) ), but never used
394 * %.7s declared( %s(%d) ), but never used or defined
396 * bufp defined( "./metric.h"(10) ), but never used
398 if ((lastchar(wordv
[2]) == '(' /* ')' */) &&
399 (strcmp(wordv
[4], "),") == 0)) {
401 if (persperdexplode(wordv
[3], &line
, &file
)) {
402 nwordv
= wordvsplice(2, wordc
, wordv
+1);
403 nwordv
[0] = file
; nwordv
[1] = line
;
405 wordv
= nwordv
- 1; /* 1 based */
412 char *Lint31
[4] = {"returns", "value", "which", "is"};
413 char *Lint32
[6] = {"value", "is", "used,", "but", "none", "returned"};
418 if ((wordvcmp(wordv
+2, 4, Lint31
) == 0) ||
419 (wordvcmp(wordv
+2, 6, Lint32
) == 0)) {
427 * Special word vectors for use by F77 recognition
429 char *F77_fatal
[3] = {"Compiler", "error", "line"};
430 char *F77_error
[3] = {"Error", "on", "line"};
431 char *F77_warning
[3] = {"Warning", "on", "line"};
432 char *F77_no_ass
[3] = {"Error.", "No", "assembly."};
439 * look for f77 errors:
440 * Error messages from /usr/src/cmd/f77/error.c, with
441 * these printf formats:
443 * Compiler error line %d of %s: %s
444 * Error on line %d of %s: %s
445 * Warning on line %d of %s: %s
446 * Error. No assembly.
448 if (wordc
== 3 && wordvcmp(wordv
+1, 3, F77_no_ass
) == 0) {
454 if ((lastchar(wordv
[6]) == ':') &&
455 ((wordvcmp(wordv
+1, 3, F77_fatal
) == 0) ||
456 (wordvcmp(wordv
+1, 3, F77_error
) == 0) ||
457 (wordvcmp(wordv
+1, 3, F77_warning
) == 0))) {
459 nwordv
= wordvsplice(2, wordc
, wordv
+1);
460 nwordv
[0] = wordv
[6];
461 clob_last(nwordv
[0], '\0');
462 nwordv
[1] = wordv
[4];
464 wordv
= nwordv
- 1; /* 1 based */
470 char *Make_Croak
[3] = {"***", "Error", "code"};
471 char *Make_NotRemade
[5] = {"not", "remade", "because", "of", "errors"};
476 if (wordvcmp(wordv
+1, 3, Make_Croak
) == 0) {
480 if (wordvcmp(wordv
+2, 5, Make_NotRemade
) == 0) {
491 * Match an error message produced by ri; here is the
492 * procedure yanked from the distributed version of ri
495 * serror(str, x1, x2, x3)
497 * char *x1, *x2, *x3;
499 * extern int yylineno;
502 * fputs(srcfile, stdout);
504 * fprintf(stdout, " %d: ", yylineno);
505 * fprintf(stdout, str, x1, x2, x3);
506 * fprintf(stdout, "\n");
510 if ((firstchar(wordv
[1]) == '"') &&
511 (lastchar(wordv
[1]) == '"') &&
512 (lastchar(wordv
[2]) == ':') &&
513 (isdigit(firstchar(wordv
[2])))) {
514 clob_last(wordv
[1], '\0'); /* drop the last " */
515 wordv
[1]++; /* skip over the first " */
516 clob_last(wordv
[2], '\0');
527 * Catches random things.
529 language
= INUNKNOWN
;
537 * troff source error message, from eqn, bib, tbl...
538 * Just like pcc ccom, except uses `'
540 if ((firstchar(wordv
[1]) == '`') &&
541 (lastchar(wordv
[1]) == ',') &&
542 (next_lastchar(wordv
[1]) == '\'') &&
543 (strcmp(wordv
[2], "line") == 0) &&
544 (isdigit(firstchar(wordv
[3]))) &&
545 (lastchar(wordv
[3]) == ':')) {
546 clob_last(wordv
[1], '\0'); /* drop last , */
547 clob_last(wordv
[1], '\0'); /* drop last " */
548 wordv
[1]++; /* drop first " */
549 clob_last(wordv
[3], '\0'); /* drop : on line number */
550 wordv
[2] = wordv
[1]; /* overwrite "line" */
551 wordv
++; /* compensate */
552 currentfilename
= wordv
[1];
563 * for decwrl modula2 compiler (powell)
565 if (((strcmp(wordv
[1], "!!!") == 0) || /* early version */
566 (strcmp(wordv
[1], "File") == 0)) && /* later version */
567 (lastchar(wordv
[2]) == ',') && /* file name */
568 (strcmp(wordv
[3], "line") == 0) &&
569 (isdigit(firstchar(wordv
[4]))) && /* line number */
570 (lastchar(wordv
[4]) == ':')) { /* line number */
571 clob_last(wordv
[2], '\0'); /* drop last , on file name */
572 clob_last(wordv
[4], '\0'); /* drop last : on line number */
573 wordv
[3] = wordv
[2]; /* file name on top of "line" */
576 currentfilename
= wordv
[1];
587 * Finally attempt a Sun f77 error message match:
589 * "bar.f", line 237: Error: no label on format statement
590 * "test.f", line 7: ANSI extension: Hollerith constant
591 * "dir/foo.h", line 1: Warning: missing END statement
593 if ((firstchar(wordv
[1]) == '"') &&
594 (lastchar(wordv
[1]) == ',') &&
595 (next_lastchar(wordv
[1]) == '"') &&
596 (strcmp(wordv
[2], "line") == 0) &&
597 (isdigit(firstchar(wordv
[3]))) &&
598 (lastchar(wordv
[3]) == ':') &&
599 ((strcmp(wordv
[4], "Error:") == 0) ||
600 (strcmp(wordv
[4], "Warning:") == 0) ||
601 ((strcmp(wordv
[4], "ANSI") == 0) &&
602 (strcmp(wordv
[5], "extension:") == 0)))) {
603 clob_last(wordv
[1], '\0'); /* drop last , */
604 clob_last(wordv
[1], '\0'); /* drop last " */
605 wordv
[1]++; /* drop first " */
606 clob_last(wordv
[3], '\0'); /* drop : on line number */
607 wordv
[2] = wordv
[1]; /* overwrite "line" */
608 wordv
++; /* compensate */
610 currentfilename
= wordv
[1];
615 } /* end of Sun f77 */