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