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