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