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