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