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