1 static char *sccsid = "@(#)input.c 1.11 (Berkeley) 84/12/11"; 2 #include <stdio.h> 3 #include <ctype.h> 4 #include "error.h" 5 6 int wordc; /* how long the current error message is */ 7 char **wordv; /* the actual error message */ 8 9 int nerrors; 10 int language; 11 12 Errorclass onelong(); 13 Errorclass cpp(); 14 Errorclass pccccom(); /* Portable C Compiler C Compiler */ 15 Errorclass richieccom(); /* Richie Compiler for 11 */ 16 Errorclass lint0(); 17 Errorclass lint1(); 18 Errorclass lint2(); 19 Errorclass lint3(); 20 Errorclass make(); 21 Errorclass f77(); 22 Errorclass pi(); 23 Errorclass ri(); 24 Errorclass troff(); 25 Errorclass mod2(); 26 /* 27 * Eat all of the lines in the input file, attempting to categorize 28 * them by their various flavors 29 */ 30 static char inbuffer[BUFSIZ]; 31 32 eaterrors(r_errorc, r_errorv) 33 int *r_errorc; 34 Eptr **r_errorv; 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; 48 if ( wordc > 0 && 49 ((( errorclass = onelong() ) != C_UNKNOWN) 50 || (( errorclass = cpp() ) != C_UNKNOWN) 51 || (( errorclass = pccccom() ) != C_UNKNOWN) 52 || (( errorclass = richieccom() ) != C_UNKNOWN) 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) 59 || ((errorclass = pi() ) != C_UNKNOWN) 60 || (( errorclass = ri() )!= C_UNKNOWN) 61 || (( errorclass = mod2() )!= C_UNKNOWN) 62 || (( errorclass = troff() )!= C_UNKNOWN)) 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 */ 78 erroradd(errorlength, errorv, errorclass, errorsubclass) 79 int errorlength; 80 char **errorv; 81 Errorclass errorclass; 82 Errorclass errorsubclass; 83 { 84 reg Eptr newerror; 85 reg char *cp; 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){ 99 newerror = (Eptr)Calloc(1, sizeof(Edesc)); 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 123 Errorclass 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; 135 if (strcmp(wordv[1], "Stop.") == 0){ 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]; 149 (void)substitute(currentfilename, ':', '\0'); 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 169 Errorclass 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 191 Errorclass pccccom() 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*/ 212 wordc--; 213 currentfilename = wordv[1]; 214 language = INCC; 215 return(C_TRUE); 216 } 217 return(C_UNKNOWN); 218 } /* end of ccom */ 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 */ 228 Errorclass richieccom() 229 { 230 reg char *cp; 231 reg char **nwordv; 232 char *file; 233 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 } 254 255 Errorclass lint0() 256 { 257 reg char **nwordv; 258 char *line, *file; 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 285 Errorclass 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 */ 297 if (wordc > 1 && strcmp(wordv[wordc-1], "::") == 0){ 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; 306 if (wordc > 2 307 && (persperdexplode(wordv[wordc], &line2, &file2)) 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 322 Errorclass 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 350 char *Lint31[4] = {"returns", "value", "which", "is"}; 351 char *Lint32[6] = {"value", "is", "used,", "but", "none", "returned"}; 352 Errorclass 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 */ 365 char *F77_fatal[3] = {"Compiler", "error", "line"}; 366 char *F77_error[3] = {"Error", "on", "line"}; 367 char *F77_warning[3] = {"Warning", "on", "line"}; 368 char *F77_no_ass[3] = {"Error.","No","assembly."}; 369 f77() 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 380 * Error. No assembly. 381 */ 382 if (wordc == 3 && wordvcmp(wordv+1, 3, F77_no_ass) == 0) { 383 wordc = 0; 384 return(C_SYNC); 385 } 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 406 char *Make_Croak[3] = {"***", "Error", "code"}; 407 char *Make_NotRemade[5] = {"not", "remade", "because", "of", "errors"}; 408 Errorclass 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 } 420 Errorclass ri() 421 { 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 455 Errorclass catchall() 456 { 457 /* 458 * Catches random things. 459 */ 460 language = INUNKNOWN; 461 return(C_NONSPEC); 462 } /* end of catch all*/ 463 464 Errorclass 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 } 488 Errorclass mod2() 489 { 490 if ( (strcmp(wordv[1], "!!!") == 0) 491 && (lastchar(wordv[2]) == ',') /* file name */ 492 && (strcmp(wordv[3], "line") == 0) 493 && (isdigit(firstchar(wordv[4]))) /* line number */ 494 && (lastchar(wordv[4]) == ':') /* line number */ 495 ){ 496 clob_last(wordv[2], '\0'); /* drop last , on file name */ 497 clob_last(wordv[4], '\0'); /* drop last : on line number */ 498 wordv[3] = wordv[2]; /* file name on top of "line" */ 499 wordv += 2; 500 wordc -= 2; 501 currentfilename = wordv[1]; 502 language = INMOD2; 503 return(C_TRUE); 504 } 505 return(C_UNKNOWN); 506 } 507