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