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