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