1 static char *sccsid = "@(#)input.c 1.8 (Berkeley) 83/06/14"; 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 /* 26 * Eat all of the lines in the input file, attempting to categorize 27 * them by their various flavors 28 */ 29 static char inbuffer[BUFSIZ]; 30 31 eaterrors(r_errorc, r_errorv) 32 int *r_errorc; 33 Eptr **r_errorv; 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; 47 if ( 0 48 || (( errorclass = onelong() ) != C_UNKNOWN) 49 || (( errorclass = cpp() ) != C_UNKNOWN) 50 || (( errorclass = pccccom() ) != C_UNKNOWN) 51 || (( errorclass = richieccom() ) != C_UNKNOWN) 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) 58 || ((errorclass = pi() ) != C_UNKNOWN) 59 || (( errorclass = ri() )!= C_UNKNOWN) 60 || (( errorclass = troff() )!= C_UNKNOWN) 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 */ 76 erroradd(errorlength, errorv, errorclass, errorsubclass) 77 int errorlength; 78 char **errorv; 79 Errorclass errorclass; 80 Errorclass errorsubclass; 81 { 82 reg Eptr newerror; 83 reg char *cp; 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){ 97 newerror = (Eptr)Calloc(1, sizeof(Edesc)); 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 121 Errorclass 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; 133 if (strcmp(wordv[2], "Stop.") == 0){ 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]; 147 (void)substitute(currentfilename, ':', '\0'); 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 167 Errorclass 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 189 Errorclass pccccom() 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*/ 210 currentfilename = wordv[1]; 211 language = INCC; 212 return(C_TRUE); 213 } 214 return(C_UNKNOWN); 215 } /* end of ccom */ 216 /* 217 * Do the error message from the Richie C Compiler for the PDP11, 218 * which has this source: 219 * 220 * if (filename[0]) 221 * fprintf(stderr, "%s:", filename); 222 * fprintf(stderr, "%d: ", line); 223 * 224 */ 225 Errorclass richieccom() 226 { 227 reg char *cp; 228 reg char **nwordv; 229 char *file; 230 231 if (lastchar(wordv[1]) == ':'){ 232 cp = wordv[1] + strlen(wordv[1]) - 1; 233 while (isdigit(*--cp)) 234 continue; 235 if (*cp == ':'){ 236 clob_last(wordv[1], '\0'); /* last : */ 237 *cp = '\0'; /* first : */ 238 file = wordv[1]; 239 nwordv = wordvsplice(1, wordc, wordv+1); 240 nwordv[0] = file; 241 nwordv[1] = cp + 1; 242 wordc += 1; 243 wordv = nwordv - 1; 244 language = INCC; 245 currentfilename = wordv[1]; 246 return(C_TRUE); 247 } 248 } 249 return(C_UNKNOWN); 250 } 251 252 Errorclass lint0() 253 { 254 reg char **nwordv; 255 char *line, *file; 256 /* 257 * Attempt a match for the new lint style normal compiler 258 * error messages, of the form 259 * 260 * printf("%s(%d): %s\n", filename, linenumber, message); 261 */ 262 if (wordc >= 2){ 263 if ( (lastchar(wordv[1]) == ':') 264 && (next_lastchar(wordv[1]) == ')') 265 ) { 266 clob_last(wordv[1], '\0'); /* colon */ 267 if (persperdexplode(wordv[1], &line, &file)){ 268 nwordv = wordvsplice(1, wordc, wordv+1); 269 nwordv[0] = file; /* file name */ 270 nwordv[1] = line; /* line number */ 271 wordc += 1; 272 wordv = nwordv - 1; 273 language = INLINT; 274 return(C_TRUE); 275 } 276 wordv[1][strlen(wordv[1])] = ':'; 277 } 278 } 279 return (C_UNKNOWN); 280 } 281 282 Errorclass lint1() 283 { 284 char *line1, *line2; 285 char *file1, *file2; 286 char **nwordv1, **nwordv2; 287 288 /* 289 * Now, attempt a match for the various errors that lint 290 * can complain about. 291 * 292 * Look first for type 1 lint errors 293 */ 294 if (wordc > 1 && strcmp(wordv[wordc-1], "::") == 0){ 295 /* 296 * %.7s, arg. %d used inconsistently %s(%d) :: %s(%d) 297 * %.7s value used inconsistently %s(%d) :: %s(%d) 298 * %.7s multiply declared %s(%d) :: %s(%d) 299 * %.7s value declared inconsistently %s(%d) :: %s(%d) 300 * %.7s function value type must be declared before use %s(%d) :: %s(%d) 301 */ 302 language = INLINT; 303 if (wordc > 2 304 && (persperdexplode(wordv[wordc], &line2, &file2)) 305 && (persperdexplode(wordv[wordc-2], &line1, &file1)) ){ 306 nwordv1 = wordvsplice(2, wordc, wordv+1); 307 nwordv2 = wordvsplice(2, wordc, wordv+1); 308 nwordv1[0] = file1; nwordv1[1] = line1; 309 erroradd(wordc+2, nwordv1, C_TRUE, C_DUPL); /* takes 0 based*/ 310 nwordv2[0] = file2; nwordv2[1] = line2; 311 wordc = wordc + 2; 312 wordv = nwordv2 - 1; /* 1 based */ 313 return(C_TRUE); 314 } 315 } 316 return(C_UNKNOWN); 317 } /* end of lint 1*/ 318 319 Errorclass lint2() 320 { 321 char *file; 322 char *line; 323 char **nwordv; 324 /* 325 * Look for type 2 lint errors 326 * 327 * %.7s used( %s(%d) ), but not defined 328 * %.7s defined( %s(%d) ), but never used 329 * %.7s declared( %s(%d) ), but never used or defined 330 * 331 * bufp defined( "./metric.h"(10) ), but never used 332 */ 333 if ( (lastchar(wordv[2]) == '(' /* ')' */ ) 334 && (strcmp(wordv[4], "),") == 0) ){ 335 language = INLINT; 336 if (persperdexplode(wordv[3], &line, &file)){ 337 nwordv = wordvsplice(2, wordc, wordv+1); 338 nwordv[0] = file; nwordv[1] = line; 339 wordc = wordc + 2; 340 wordv = nwordv - 1; /* 1 based */ 341 return(C_TRUE); 342 } 343 } 344 return(C_UNKNOWN); 345 } /* end of lint 2*/ 346 347 char *Lint31[4] = {"returns", "value", "which", "is"}; 348 char *Lint32[6] = {"value", "is", "used,", "but", "none", "returned"}; 349 Errorclass lint3() 350 { 351 if ( (wordvcmp(wordv+2, 4, Lint31) == 0) 352 || (wordvcmp(wordv+2, 6, Lint32) == 0) ){ 353 language = INLINT; 354 return(C_NONSPEC); 355 } 356 return(C_UNKNOWN); 357 } 358 359 /* 360 * Special word vectors for use by F77 recognition 361 */ 362 char *F77_fatal[3] = {"Compiler", "error", "line"}; 363 char *F77_error[3] = {"Error", "on", "line"}; 364 char *F77_warning[3] = {"Warning", "on", "line"}; 365 f77() 366 { 367 char **nwordv; 368 /* 369 * look for f77 errors: 370 * Error messages from /usr/src/cmd/f77/error.c, with 371 * these printf formats: 372 * 373 * Compiler error line %d of %s: %s 374 * Error on line %d of %s: %s 375 * Warning on line %d of %s: %s 376 */ 377 if (wordc < 6) 378 return(C_UNKNOWN); 379 if ( (lastchar(wordv[6]) == ':') 380 &&( 381 (wordvcmp(wordv+1, 3, F77_fatal) == 0) 382 || (wordvcmp(wordv+1, 3, F77_error) == 0) 383 || (wordvcmp(wordv+1, 3, F77_warning) == 0) ) 384 ){ 385 language = INF77; 386 nwordv = wordvsplice(2, wordc, wordv+1); 387 nwordv[0] = wordv[6]; 388 clob_last(nwordv[0],'\0'); 389 nwordv[1] = wordv[4]; 390 wordc += 2; 391 wordv = nwordv - 1; /* 1 based */ 392 return(C_TRUE); 393 } 394 return(C_UNKNOWN); 395 } /* end of f77 */ 396 397 char *Make_Croak[3] = {"***", "Error", "code"}; 398 char *Make_NotRemade[5] = {"not", "remade", "because", "of", "errors"}; 399 Errorclass make() 400 { 401 if (wordvcmp(wordv+1, 3, Make_Croak) == 0){ 402 language = INMAKE; 403 return(C_SYNC); 404 } 405 if (wordvcmp(wordv+2, 5, Make_NotRemade) == 0){ 406 language = INMAKE; 407 return(C_SYNC); 408 } 409 return(C_UNKNOWN); 410 } 411 Errorclass ri() 412 { 413 /* 414 * Match an error message produced by ri; here is the 415 * procedure yanked from the distributed version of ri 416 * April 24, 1980. 417 * 418 * serror(str, x1, x2, x3) 419 * char str[]; 420 * char *x1, *x2, *x3; 421 * { 422 * extern int yylineno; 423 * 424 * putc('"', stdout); 425 * fputs(srcfile, stdout); 426 * putc('"', stdout); 427 * fprintf(stdout, " %d: ", yylineno); 428 * fprintf(stdout, str, x1, x2, x3); 429 * fprintf(stdout, "\n"); 430 * synerrs++; 431 * } 432 */ 433 if ( (firstchar(wordv[1]) == '"') 434 &&(lastchar(wordv[1]) == '"') 435 &&(lastchar(wordv[2]) == ':') 436 &&(isdigit(firstchar(wordv[2]))) ){ 437 clob_last(wordv[1], '\0'); /* drop the last " */ 438 wordv[1]++; /* skip over the first " */ 439 clob_last(wordv[2], '\0'); 440 language = INRI; 441 return(C_TRUE); 442 } 443 return(C_UNKNOWN); 444 } 445 446 Errorclass catchall() 447 { 448 /* 449 * Catches random things. 450 */ 451 language = INUNKNOWN; 452 return(C_NONSPEC); 453 } /* end of catch all*/ 454 455 Errorclass troff() 456 { 457 /* 458 * troff source error message, from eqn, bib, tbl... 459 * Just like pcc ccom, except uses `' 460 */ 461 if ( (firstchar(wordv[1]) == '`') 462 && (lastchar(wordv[1]) == ',') 463 && (next_lastchar(wordv[1]) == '\'') 464 && (strcmp(wordv[2],"line") == 0) 465 && (isdigit(firstchar(wordv[3]))) 466 && (lastchar(wordv[3]) == ':') ){ 467 clob_last(wordv[1], '\0'); /* drop last , */ 468 clob_last(wordv[1], '\0'); /* drop last " */ 469 wordv[1]++; /* drop first " */ 470 clob_last(wordv[3], '\0'); /* drop : on line number */ 471 wordv[2] = wordv[1]; /* overwrite "line" */ 472 wordv++; /*compensate*/ 473 currentfilename = wordv[1]; 474 language = INTROFF; 475 return(C_TRUE); 476 } 477 return(C_UNKNOWN); 478 } 479