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