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