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