1*17499Srrh static char *sccsid = "@(#)input.c 1.11 (Berkeley) 84/12/11"; 21456Sroot #include <stdio.h> 31456Sroot #include <ctype.h> 41456Sroot #include "error.h" 51456Sroot 61456Sroot int wordc; /* how long the current error message is */ 71456Sroot char **wordv; /* the actual error message */ 81456Sroot 91456Sroot int nerrors; 101456Sroot int language; 111456Sroot 121456Sroot Errorclass onelong(); 131456Sroot Errorclass cpp(); 142798Swnj Errorclass pccccom(); /* Portable C Compiler C Compiler */ 152798Swnj Errorclass richieccom(); /* Richie Compiler for 11 */ 161456Sroot Errorclass lint0(); 171456Sroot Errorclass lint1(); 181456Sroot Errorclass lint2(); 191456Sroot Errorclass lint3(); 201456Sroot Errorclass make(); 211456Sroot Errorclass f77(); 221456Sroot Errorclass pi(); 231456Sroot Errorclass ri(); 2413106Srrh Errorclass troff(); 25*17499Srrh Errorclass mod2(); 261456Sroot /* 271456Sroot * Eat all of the lines in the input file, attempting to categorize 281456Sroot * them by their various flavors 291456Sroot */ 301456Sroot static char inbuffer[BUFSIZ]; 311456Sroot 321456Sroot eaterrors(r_errorc, r_errorv) 331456Sroot int *r_errorc; 345592Srrh Eptr **r_errorv; 351456Sroot { 361456Sroot extern boolean piflag; 371456Sroot Errorclass errorclass = C_SYNC; 381456Sroot 391456Sroot for (;;){ 401456Sroot if (fgets(inbuffer, BUFSIZ, errorfile) == NULL) 411456Sroot break; 421456Sroot wordvbuild(inbuffer, &wordc, &wordv); 431456Sroot /* 441456Sroot * for convience, convert wordv to be 1 based, instead 451456Sroot * of 0 based. 461456Sroot */ 471456Sroot wordv -= 1; 4816460Sedward if ( wordc > 0 && 4916460Sedward ((( errorclass = onelong() ) != C_UNKNOWN) 501456Sroot || (( errorclass = cpp() ) != C_UNKNOWN) 512798Swnj || (( errorclass = pccccom() ) != C_UNKNOWN) 522798Swnj || (( errorclass = richieccom() ) != C_UNKNOWN) 531456Sroot || (( errorclass = lint0() ) != C_UNKNOWN) 541456Sroot || (( errorclass = lint1() ) != C_UNKNOWN) 551456Sroot || (( errorclass = lint2() ) != C_UNKNOWN) 561456Sroot || (( errorclass = lint3() ) != C_UNKNOWN) 571456Sroot || (( errorclass = make() ) != C_UNKNOWN) 581456Sroot || (( errorclass = f77() ) != C_UNKNOWN) 591456Sroot || ((errorclass = pi() ) != C_UNKNOWN) 601456Sroot || (( errorclass = ri() )!= C_UNKNOWN) 61*17499Srrh || (( errorclass = mod2() )!= C_UNKNOWN) 6216460Sedward || (( errorclass = troff() )!= C_UNKNOWN)) 631456Sroot ) ; 641456Sroot else 651456Sroot errorclass = catchall(); 661456Sroot if (wordc) 671456Sroot erroradd(wordc, wordv+1, errorclass, C_UNKNOWN); 681456Sroot } 691456Sroot #ifdef FULLDEBUG 701456Sroot printf("%d errorentrys\n", nerrors); 711456Sroot #endif 721456Sroot arrayify(r_errorc, r_errorv, er_head); 731456Sroot } 741456Sroot 751456Sroot /* 761456Sroot * create a new error entry, given a zero based array and count 771456Sroot */ 781456Sroot erroradd(errorlength, errorv, errorclass, errorsubclass) 791456Sroot int errorlength; 801456Sroot char **errorv; 811456Sroot Errorclass errorclass; 821456Sroot Errorclass errorsubclass; 831456Sroot { 845592Srrh reg Eptr newerror; 855592Srrh reg char *cp; 861456Sroot 871456Sroot if (errorclass == C_TRUE){ 881456Sroot /* check canonicalization of the second argument*/ 891456Sroot for(cp = errorv[1]; *cp && isdigit(*cp); cp++) 901456Sroot continue; 911456Sroot errorclass = (*cp == '\0') ? C_TRUE : C_NONSPEC; 921456Sroot #ifdef FULLDEBUG 931456Sroot if (errorclass != C_TRUE) 941456Sroot printf("The 2nd word, \"%s\" is not a number.\n", 951456Sroot errorv[1]); 961456Sroot #endif 971456Sroot } 981456Sroot if (errorlength > 0){ 995592Srrh newerror = (Eptr)Calloc(1, sizeof(Edesc)); 1001456Sroot newerror->error_language = language; /* language is global */ 1011456Sroot newerror->error_text = errorv; 1021456Sroot newerror->error_lgtext = errorlength; 1031456Sroot if (errorclass == C_TRUE) 1041456Sroot newerror->error_line = atoi(errorv[1]); 1051456Sroot newerror->error_e_class = errorclass; 1061456Sroot newerror->error_s_class = errorsubclass; 1071456Sroot switch(newerror->error_e_class = discardit(newerror)){ 1081456Sroot case C_SYNC: nsyncerrors++; break; 1091456Sroot case C_DISCARD: ndiscard++; break; 1101456Sroot case C_NULLED: nnulled++; break; 1111456Sroot case C_NONSPEC: nnonspec++; break; 1121456Sroot case C_THISFILE: nthisfile++; break; 1131456Sroot case C_TRUE: ntrue++; break; 1141456Sroot case C_UNKNOWN: nunknown++; break; 1151456Sroot case C_IGNORE: nignore++; break; 1161456Sroot } 1171456Sroot newerror->error_next = er_head; 1181456Sroot er_head = newerror; 1191456Sroot newerror->error_no = nerrors++; 1201456Sroot } /* length > 0 */ 1211456Sroot } 1221456Sroot 1231456Sroot Errorclass onelong() 1241456Sroot { 1251456Sroot char **nwordv; 1261456Sroot if ( (wordc == 1) && (language != INLD) ){ 1271456Sroot /* 1281456Sroot * We have either: 1291456Sroot * a) file name from cc 1301456Sroot * b) Assembler telling world that it is complaining 1311456Sroot * c) Noise from make ("Stop.") 1321456Sroot * c) Random noise 1331456Sroot */ 1341456Sroot wordc = 0; 13516460Sedward if (strcmp(wordv[1], "Stop.") == 0){ 1361456Sroot language = INMAKE; return(C_SYNC); 1371456Sroot } 1381456Sroot if (strcmp(wordv[1], "Assembler:") == 0){ 1391456Sroot /* assembler always alerts us to what happened*/ 1401456Sroot language = INAS; return(C_SYNC); 1411456Sroot } else 1421456Sroot if (strcmp(wordv[1], "Undefined:") == 0){ 1431456Sroot /* loader complains about unknown symbols*/ 1441456Sroot language = INLD; return(C_SYNC); 1451456Sroot } 1461456Sroot if (lastchar(wordv[1]) == ':'){ 1471456Sroot /* cc tells us what file we are in */ 1481456Sroot currentfilename = wordv[1]; 1495592Srrh (void)substitute(currentfilename, ':', '\0'); 1501456Sroot language = INCC; return(C_SYNC); 1511456Sroot } 1521456Sroot } else 1531456Sroot if ( (wordc == 1) && (language == INLD) ){ 1541456Sroot nwordv = (char **)Calloc(4, sizeof(char *)); 1551456Sroot nwordv[0] = "ld:"; 1561456Sroot nwordv[1] = wordv[1]; 1571456Sroot nwordv[2] = "is"; 1581456Sroot nwordv[3] = "undefined."; 1591456Sroot wordc = 4; 1601456Sroot wordv = nwordv - 1; 1611456Sroot return(C_NONSPEC); 1621456Sroot } else 1631456Sroot if (wordc == 1){ 1641456Sroot return(C_SYNC); 1651456Sroot } 1661456Sroot return(C_UNKNOWN); 1671456Sroot } /* end of one long */ 1681456Sroot 1691456Sroot Errorclass cpp() 1701456Sroot { 1711456Sroot /* 1721456Sroot * Now attempt a cpp error message match 1731456Sroot * Examples: 1741456Sroot * ./morse.h: 23: undefined control 1751456Sroot * morsesend.c: 229: MAGNIBBL: argument mismatch 1761456Sroot * morsesend.c: 237: MAGNIBBL: argument mismatch 1771456Sroot * test1.c: 6: undefined control 1781456Sroot */ 1791456Sroot if ( (language != INLD) /* loader errors have almost same fmt*/ 1801456Sroot && (lastchar(wordv[1]) == ':') 1811456Sroot && (isdigit(firstchar(wordv[2]))) 1821456Sroot && (lastchar(wordv[2]) == ':') ){ 1831456Sroot language = INCPP; 1841456Sroot clob_last(wordv[1], '\0'); 1851456Sroot clob_last(wordv[2], '\0'); 1861456Sroot return(C_TRUE); 1871456Sroot } 1881456Sroot return(C_UNKNOWN); 1891456Sroot } /*end of cpp*/ 1901456Sroot 1912798Swnj Errorclass pccccom() 1921456Sroot { 1931456Sroot /* 1941456Sroot * Now attempt a ccom error message match: 1951456Sroot * Examples: 1961456Sroot * "morsesend.c", line 237: operands of & have incompatible types 1971456Sroot * "test.c", line 7: warning: old-fashioned initialization: use = 1981456Sroot * "subdir.d/foo2.h", line 1: illegal initialization 1991456Sroot */ 2001456Sroot if ( (firstchar(wordv[1]) == '"') 2011456Sroot && (lastchar(wordv[1]) == ',') 2021456Sroot && (next_lastchar(wordv[1]) == '"') 2031456Sroot && (strcmp(wordv[2],"line") == 0) 2041456Sroot && (isdigit(firstchar(wordv[3]))) 2051456Sroot && (lastchar(wordv[3]) == ':') ){ 2061456Sroot clob_last(wordv[1], '\0'); /* drop last , */ 2071456Sroot clob_last(wordv[1], '\0'); /* drop last " */ 2081456Sroot wordv[1]++; /* drop first " */ 2091456Sroot clob_last(wordv[3], '\0'); /* drop : on line number */ 2101456Sroot wordv[2] = wordv[1]; /* overwrite "line" */ 2111456Sroot wordv++; /*compensate*/ 21216460Sedward wordc--; 2136610Srrh currentfilename = wordv[1]; 2146610Srrh language = INCC; 2156610Srrh return(C_TRUE); 2161456Sroot } 2171456Sroot return(C_UNKNOWN); 2181456Sroot } /* end of ccom */ 2192798Swnj /* 2202798Swnj * Do the error message from the Richie C Compiler for the PDP11, 2212798Swnj * which has this source: 2222798Swnj * 2232798Swnj * if (filename[0]) 2242798Swnj * fprintf(stderr, "%s:", filename); 2252798Swnj * fprintf(stderr, "%d: ", line); 2262798Swnj * 2272798Swnj */ 2282798Swnj Errorclass richieccom() 2292798Swnj { 2305592Srrh reg char *cp; 2315592Srrh reg char **nwordv; 2325592Srrh char *file; 2335592Srrh 2342798Swnj if (lastchar(wordv[1]) == ':'){ 2352798Swnj cp = wordv[1] + strlen(wordv[1]) - 1; 2362798Swnj while (isdigit(*--cp)) 2372798Swnj continue; 2382798Swnj if (*cp == ':'){ 2392798Swnj clob_last(wordv[1], '\0'); /* last : */ 2402798Swnj *cp = '\0'; /* first : */ 2412798Swnj file = wordv[1]; 2422798Swnj nwordv = wordvsplice(1, wordc, wordv+1); 2432798Swnj nwordv[0] = file; 2442798Swnj nwordv[1] = cp + 1; 2452798Swnj wordc += 1; 2462798Swnj wordv = nwordv - 1; 2472798Swnj language = INCC; 2482798Swnj currentfilename = wordv[1]; 2492798Swnj return(C_TRUE); 2502798Swnj } 2512798Swnj } 2522798Swnj return(C_UNKNOWN); 2532798Swnj } 2541456Sroot 2551456Sroot Errorclass lint0() 2561456Sroot { 2575592Srrh reg char **nwordv; 2585592Srrh char *line, *file; 2591456Sroot /* 2601456Sroot * Attempt a match for the new lint style normal compiler 2611456Sroot * error messages, of the form 2621456Sroot * 2631456Sroot * printf("%s(%d): %s\n", filename, linenumber, message); 2641456Sroot */ 2651456Sroot if (wordc >= 2){ 2661456Sroot if ( (lastchar(wordv[1]) == ':') 2671456Sroot && (next_lastchar(wordv[1]) == ')') 2681456Sroot ) { 2691456Sroot clob_last(wordv[1], '\0'); /* colon */ 2701456Sroot if (persperdexplode(wordv[1], &line, &file)){ 2711456Sroot nwordv = wordvsplice(1, wordc, wordv+1); 2721456Sroot nwordv[0] = file; /* file name */ 2731456Sroot nwordv[1] = line; /* line number */ 2741456Sroot wordc += 1; 2751456Sroot wordv = nwordv - 1; 2761456Sroot language = INLINT; 2771456Sroot return(C_TRUE); 2781456Sroot } 2791456Sroot wordv[1][strlen(wordv[1])] = ':'; 2801456Sroot } 2811456Sroot } 2821456Sroot return (C_UNKNOWN); 2831456Sroot } 2841456Sroot 2851456Sroot Errorclass lint1() 2861456Sroot { 2871456Sroot char *line1, *line2; 2881456Sroot char *file1, *file2; 2891456Sroot char **nwordv1, **nwordv2; 2901456Sroot 2911456Sroot /* 2921456Sroot * Now, attempt a match for the various errors that lint 2931456Sroot * can complain about. 2941456Sroot * 2951456Sroot * Look first for type 1 lint errors 2961456Sroot */ 29710829Ssam if (wordc > 1 && strcmp(wordv[wordc-1], "::") == 0){ 2981456Sroot /* 2991456Sroot * %.7s, arg. %d used inconsistently %s(%d) :: %s(%d) 3001456Sroot * %.7s value used inconsistently %s(%d) :: %s(%d) 3011456Sroot * %.7s multiply declared %s(%d) :: %s(%d) 3021456Sroot * %.7s value declared inconsistently %s(%d) :: %s(%d) 3031456Sroot * %.7s function value type must be declared before use %s(%d) :: %s(%d) 3041456Sroot */ 3051456Sroot language = INLINT; 30610829Ssam if (wordc > 2 30710829Ssam && (persperdexplode(wordv[wordc], &line2, &file2)) 3081456Sroot && (persperdexplode(wordv[wordc-2], &line1, &file1)) ){ 3091456Sroot nwordv1 = wordvsplice(2, wordc, wordv+1); 3101456Sroot nwordv2 = wordvsplice(2, wordc, wordv+1); 3111456Sroot nwordv1[0] = file1; nwordv1[1] = line1; 3121456Sroot erroradd(wordc+2, nwordv1, C_TRUE, C_DUPL); /* takes 0 based*/ 3131456Sroot nwordv2[0] = file2; nwordv2[1] = line2; 3141456Sroot wordc = wordc + 2; 3151456Sroot wordv = nwordv2 - 1; /* 1 based */ 3161456Sroot return(C_TRUE); 3171456Sroot } 3181456Sroot } 3191456Sroot return(C_UNKNOWN); 3201456Sroot } /* end of lint 1*/ 3211456Sroot 3221456Sroot Errorclass lint2() 3231456Sroot { 3241456Sroot char *file; 3251456Sroot char *line; 3261456Sroot char **nwordv; 3271456Sroot /* 3281456Sroot * Look for type 2 lint errors 3291456Sroot * 3301456Sroot * %.7s used( %s(%d) ), but not defined 3311456Sroot * %.7s defined( %s(%d) ), but never used 3321456Sroot * %.7s declared( %s(%d) ), but never used or defined 3331456Sroot * 3341456Sroot * bufp defined( "./metric.h"(10) ), but never used 3351456Sroot */ 3361456Sroot if ( (lastchar(wordv[2]) == '(' /* ')' */ ) 3371456Sroot && (strcmp(wordv[4], "),") == 0) ){ 3381456Sroot language = INLINT; 3391456Sroot if (persperdexplode(wordv[3], &line, &file)){ 3401456Sroot nwordv = wordvsplice(2, wordc, wordv+1); 3411456Sroot nwordv[0] = file; nwordv[1] = line; 3421456Sroot wordc = wordc + 2; 3431456Sroot wordv = nwordv - 1; /* 1 based */ 3441456Sroot return(C_TRUE); 3451456Sroot } 3461456Sroot } 3471456Sroot return(C_UNKNOWN); 3481456Sroot } /* end of lint 2*/ 3491456Sroot 3501456Sroot char *Lint31[4] = {"returns", "value", "which", "is"}; 3511456Sroot char *Lint32[6] = {"value", "is", "used,", "but", "none", "returned"}; 3521456Sroot Errorclass lint3() 3531456Sroot { 3541456Sroot if ( (wordvcmp(wordv+2, 4, Lint31) == 0) 3551456Sroot || (wordvcmp(wordv+2, 6, Lint32) == 0) ){ 3561456Sroot language = INLINT; 3571456Sroot return(C_NONSPEC); 3581456Sroot } 3591456Sroot return(C_UNKNOWN); 3601456Sroot } 3611456Sroot 3621456Sroot /* 3631456Sroot * Special word vectors for use by F77 recognition 3641456Sroot */ 3651456Sroot char *F77_fatal[3] = {"Compiler", "error", "line"}; 3661456Sroot char *F77_error[3] = {"Error", "on", "line"}; 3671456Sroot char *F77_warning[3] = {"Warning", "on", "line"}; 36817211Sralph char *F77_no_ass[3] = {"Error.","No","assembly."}; 3691456Sroot f77() 3701456Sroot { 3711456Sroot char **nwordv; 3721456Sroot /* 3731456Sroot * look for f77 errors: 3741456Sroot * Error messages from /usr/src/cmd/f77/error.c, with 3751456Sroot * these printf formats: 3761456Sroot * 3771456Sroot * Compiler error line %d of %s: %s 3781456Sroot * Error on line %d of %s: %s 3791456Sroot * Warning on line %d of %s: %s 38017211Sralph * Error. No assembly. 3811456Sroot */ 38217211Sralph if (wordc == 3 && wordvcmp(wordv+1, 3, F77_no_ass) == 0) { 38317211Sralph wordc = 0; 38417211Sralph return(C_SYNC); 38517211Sralph } 3861456Sroot if (wordc < 6) 3871456Sroot return(C_UNKNOWN); 3881456Sroot if ( (lastchar(wordv[6]) == ':') 3891456Sroot &&( 3901456Sroot (wordvcmp(wordv+1, 3, F77_fatal) == 0) 3911456Sroot || (wordvcmp(wordv+1, 3, F77_error) == 0) 3921456Sroot || (wordvcmp(wordv+1, 3, F77_warning) == 0) ) 3931456Sroot ){ 3941456Sroot language = INF77; 3951456Sroot nwordv = wordvsplice(2, wordc, wordv+1); 3961456Sroot nwordv[0] = wordv[6]; 3971456Sroot clob_last(nwordv[0],'\0'); 3981456Sroot nwordv[1] = wordv[4]; 3991456Sroot wordc += 2; 4001456Sroot wordv = nwordv - 1; /* 1 based */ 4011456Sroot return(C_TRUE); 4021456Sroot } 4031456Sroot return(C_UNKNOWN); 4041456Sroot } /* end of f77 */ 4051456Sroot 4061456Sroot char *Make_Croak[3] = {"***", "Error", "code"}; 4071456Sroot char *Make_NotRemade[5] = {"not", "remade", "because", "of", "errors"}; 4081456Sroot Errorclass make() 4091456Sroot { 4101456Sroot if (wordvcmp(wordv+1, 3, Make_Croak) == 0){ 4111456Sroot language = INMAKE; 4121456Sroot return(C_SYNC); 4131456Sroot } 4141456Sroot if (wordvcmp(wordv+2, 5, Make_NotRemade) == 0){ 4151456Sroot language = INMAKE; 4161456Sroot return(C_SYNC); 4171456Sroot } 4181456Sroot return(C_UNKNOWN); 4191456Sroot } 4201456Sroot Errorclass ri() 4211456Sroot { 4221456Sroot /* 4231456Sroot * Match an error message produced by ri; here is the 4241456Sroot * procedure yanked from the distributed version of ri 4251456Sroot * April 24, 1980. 4261456Sroot * 4271456Sroot * serror(str, x1, x2, x3) 4281456Sroot * char str[]; 4291456Sroot * char *x1, *x2, *x3; 4301456Sroot * { 4311456Sroot * extern int yylineno; 4321456Sroot * 4331456Sroot * putc('"', stdout); 4341456Sroot * fputs(srcfile, stdout); 4351456Sroot * putc('"', stdout); 4361456Sroot * fprintf(stdout, " %d: ", yylineno); 4371456Sroot * fprintf(stdout, str, x1, x2, x3); 4381456Sroot * fprintf(stdout, "\n"); 4391456Sroot * synerrs++; 4401456Sroot * } 4411456Sroot */ 4421456Sroot if ( (firstchar(wordv[1]) == '"') 4431456Sroot &&(lastchar(wordv[1]) == '"') 4441456Sroot &&(lastchar(wordv[2]) == ':') 4451456Sroot &&(isdigit(firstchar(wordv[2]))) ){ 4461456Sroot clob_last(wordv[1], '\0'); /* drop the last " */ 4471456Sroot wordv[1]++; /* skip over the first " */ 4481456Sroot clob_last(wordv[2], '\0'); 4491456Sroot language = INRI; 4501456Sroot return(C_TRUE); 4511456Sroot } 4521456Sroot return(C_UNKNOWN); 4531456Sroot } 4541456Sroot 4551456Sroot Errorclass catchall() 4561456Sroot { 4571456Sroot /* 4581456Sroot * Catches random things. 4591456Sroot */ 4601456Sroot language = INUNKNOWN; 4611456Sroot return(C_NONSPEC); 4621456Sroot } /* end of catch all*/ 46313106Srrh 46413106Srrh Errorclass troff() 46513106Srrh { 46613106Srrh /* 46713106Srrh * troff source error message, from eqn, bib, tbl... 46813106Srrh * Just like pcc ccom, except uses `' 46913106Srrh */ 47013106Srrh if ( (firstchar(wordv[1]) == '`') 47113106Srrh && (lastchar(wordv[1]) == ',') 47213106Srrh && (next_lastchar(wordv[1]) == '\'') 47313106Srrh && (strcmp(wordv[2],"line") == 0) 47413106Srrh && (isdigit(firstchar(wordv[3]))) 47513106Srrh && (lastchar(wordv[3]) == ':') ){ 47613106Srrh clob_last(wordv[1], '\0'); /* drop last , */ 47713106Srrh clob_last(wordv[1], '\0'); /* drop last " */ 47813106Srrh wordv[1]++; /* drop first " */ 47913106Srrh clob_last(wordv[3], '\0'); /* drop : on line number */ 48013106Srrh wordv[2] = wordv[1]; /* overwrite "line" */ 48113106Srrh wordv++; /*compensate*/ 48213106Srrh currentfilename = wordv[1]; 48313106Srrh language = INTROFF; 48413106Srrh return(C_TRUE); 48513106Srrh } 48613106Srrh return(C_UNKNOWN); 48713106Srrh } 488*17499Srrh Errorclass mod2() 489*17499Srrh { 490*17499Srrh if ( (strcmp(wordv[1], "!!!") == 0) 491*17499Srrh && (lastchar(wordv[2]) == ',') /* file name */ 492*17499Srrh && (strcmp(wordv[3], "line") == 0) 493*17499Srrh && (isdigit(firstchar(wordv[4]))) /* line number */ 494*17499Srrh && (lastchar(wordv[4]) == ':') /* line number */ 495*17499Srrh ){ 496*17499Srrh clob_last(wordv[2], '\0'); /* drop last , on file name */ 497*17499Srrh clob_last(wordv[4], '\0'); /* drop last : on line number */ 498*17499Srrh wordv[3] = wordv[2]; /* file name on top of "line" */ 499*17499Srrh wordv += 2; 500*17499Srrh wordc -= 2; 501*17499Srrh currentfilename = wordv[1]; 502*17499Srrh language = INMOD2; 503*17499Srrh return(C_TRUE); 504*17499Srrh } 505*17499Srrh return(C_UNKNOWN); 506*17499Srrh } 507