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