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