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