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