|
|
1.1 ! root 1: static char *sccsid = "@(#)errorpi.c 1.1 (Berkeley) 10/16/80"; ! 2: #include <stdio.h> ! 3: #include <ctype.h> ! 4: #include "error.h" ! 5: ! 6: extern char *currentfilename; ! 7: static char *c_linenumber; ! 8: static char *unk_hdr[] = {"In", "program", "???"}; ! 9: static char **c_header = &unk_hdr[0]; ! 10: ! 11: /* ! 12: * Attempt to handle error messages produced by pi (and by pc) ! 13: * ! 14: * problem #1: There is no file name available when a file does not ! 15: * use a #include; this will have to be given to error ! 16: * in the command line. ! 17: * problem #2: pi doesn't always tell you what line number ! 18: * a error refers to; for example during the tree ! 19: * walk phase of code generation and error detection, ! 20: * an error can refer to "variable foo in procedure bletch" ! 21: * without giving a line number ! 22: * problem #3: line numbers, when available, are attached to ! 23: * the source line, along with the source line itself ! 24: * These line numbers must be extracted, and ! 25: * the source line thrown away. ! 26: * problem #4: Some error messages produce more than one line number ! 27: * on the same message. ! 28: * There are only two (I think): ! 29: * %s undefined on line%s ! 30: * %s improperly used on line%s ! 31: * here, the %s makes line plural or singular. ! 32: * ! 33: * Here are the error strings used in pi version 1.2 that can refer ! 34: * to a file name or line number: ! 35: * ! 36: * Multiply defined label in case, lines %d and %d ! 37: * Goto %s from line %d is into a structured statement ! 38: * End matched %s on line %d ! 39: * Inserted keyword end matching %s on line %d ! 40: * ! 41: * Here are the general pi patterns recognized: ! 42: * define piptr == -.*^-.* ! 43: * define msg = .* ! 44: * define digit = [0-9] ! 45: * definename = .* ! 46: * define date_format letter*3 letter*3 (digit | (digit digit)) ! 47: * (digit | (digit digit)):digit*2 digit*4 ! 48: * ! 49: * {e,E} (piptr) (msg) Encounter an error during textual scan ! 50: * E {digit}* - (msg) Have an error message that refers to a new line ! 51: * E - msg Have an error message that refers to current ! 52: * function, program or procedure ! 53: * (date_format) (name): When switch compilation files ! 54: * ... (msg) When refer to the previous line ! 55: * 'In' ('procedure'|'function'|'program') (name): ! 56: * pi is now complaining about 2nd pass errors. ! 57: * ! 58: * Here is the output from a compilation ! 59: * ! 60: * ! 61: * 2 var i:integer; ! 62: * e --------------^--- Inserted ';' ! 63: * E 2 - All variables must be declared in one var part ! 64: * E 5 - Include filename must end in .i ! 65: * Mon Apr 21 15:56 1980 test.h: ! 66: * 2 begin ! 67: * e ------^--- Inserted ';' ! 68: * Mon Apr 21 16:06 1980 test.p: ! 69: * E 2 - Function type must be specified ! 70: * 6 procedure foo(var x:real); ! 71: * e ------^--- Inserted ';' ! 72: * In function bletch: ! 73: * E - No assignment to the function variable ! 74: * w - variable x is never used ! 75: * E 6 - foo is already defined in this block ! 76: * In procedure foo: ! 77: * w - variable x is neither used nor set ! 78: * 9 z : = 23; ! 79: * E --------------^--- Undefined variable ! 80: * 10 y = [1]; ! 81: * e ----------------^--- Inserted ':' ! 82: * 13 z := 345.; ! 83: * e -----------------------^--- Digits required after decimal point ! 84: * E 10 - Constant set involved in non set context ! 85: * E 11 - Type clash: real is incompatible with integer ! 86: * ... Type of expression clashed with type of variable in assignment ! 87: * E 12 - Parameter type not identical to type of var parameter x of foo ! 88: * In program mung: ! 89: * w - variable y is never used ! 90: * w - type foo is never used ! 91: * w - function bletch is never used ! 92: * E - z undefined on lines 9 13 ! 93: */ ! 94: char *Months[] = { ! 95: "Jan", "Feb", "Mar", "Apr", "May", "Jun", ! 96: "Jul", "Aug", "Sep", "Oct","Nov", "Dec", ! 97: 0 ! 98: }; ! 99: char *Days[] = { ! 100: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0 ! 101: }; ! 102: char *Piroutines[] = { ! 103: "program", "function", "procedure", 0 ! 104: }; ! 105: ! 106: ! 107: static boolean structured, multiple; ! 108: ! 109: char *pi_Endmatched[] = {"End", "matched"}; ! 110: char *pi_Inserted[] = {"Inserted", "keyword", "end", "matching"}; ! 111: ! 112: char *pi_multiple[] = {"Mutiply", "defined", "label", "in", "case,", "line"}; ! 113: char *pi_structured[] = {"is", "into", "a", "structured", "statement"}; ! 114: ! 115: char *pi_und1[] = {"undefined", "on", "line"}; ! 116: char *pi_und2[] = {"undefined", "on", "lines"}; ! 117: char *pi_imp1[] = {"improperly", "used", "on", "line"}; ! 118: char *pi_imp2[] = {"improperly", "used", "on", "lines"}; ! 119: ! 120: boolean alldigits(string) ! 121: register char *string; ! 122: { ! 123: for (; *string && isdigit(*string); string++) ! 124: continue; ! 125: return(*string == '\0'); ! 126: } ! 127: boolean instringset(member, set) ! 128: char *member; ! 129: register char **set; ! 130: { ! 131: for(; *set; set++){ ! 132: if (strcmp(*set, member) == 0) ! 133: return(TRUE); ! 134: } ! 135: return(FALSE); ! 136: } ! 137: ! 138: boolean isdateformat(wordc, wordv) ! 139: int wordc; ! 140: char **wordv; ! 141: { ! 142: return( ! 143: (wordc == 5) ! 144: && (instringset(wordv[0], Days)) ! 145: && (instringset(wordv[1], Months)) ! 146: && (alldigits(wordv[2])) ! 147: && (alldigits(wordv[4])) ); ! 148: } ! 149: ! 150: boolean piptr(string) ! 151: register char *string; ! 152: { ! 153: int state = 0; ! 154: if (*string != '-') ! 155: return(FALSE); ! 156: while (*string && *string == '-') ! 157: string++; ! 158: if (*string != '^') ! 159: return(FALSE); ! 160: string++; ! 161: while (*string && *string == '-') ! 162: string++; ! 163: return(*string == '\0'); ! 164: } ! 165: ! 166: extern int wordc; ! 167: extern char **wordv; ! 168: ! 169: Errorclass pi() ! 170: { ! 171: char **nwordv; ! 172: char buffer[128]; ! 173: ! 174: if ( ( strlen(wordv[1]) == 1) ! 175: && ( (wordv[1][0] == 'e') || (wordv[1][0] == 'E') ) ! 176: && ( piptr(wordv[2]) ) ! 177: ) { ! 178: boolean longpiptr = 0; ! 179: /* ! 180: * We have recognized a first pass error of the form: ! 181: * letter ------^---- message ! 182: * ! 183: * turn into an error message of the form: ! 184: * ! 185: * file line 'pascal errortype' letter \n |---- message ! 186: * or of the form: ! 187: * file line letter |---- message ! 188: * when there are strlen("(*[pi]") or more ! 189: * preceding '-' on the error pointer. ! 190: * ! 191: * Where the | is intended to be a down arrow, so that ! 192: * the pi error messages can be inserted above the ! 193: * line in error, instead of below. (All of the other ! 194: * langauges put thier messages before the source line, ! 195: * instead of after it as does pi.) ! 196: * ! 197: * where the pointer to the error has been truncated ! 198: * by 6 characters to account for the fact that ! 199: * the pointer points into a tab preceded input line. ! 200: */ ! 201: language = INPI; ! 202: substitute(wordv[2], '^', '|'); ! 203: longpiptr = position(wordv[2],'|') > (6+8); ! 204: nwordv = wordvsplice(longpiptr ? 2 : 4, wordc, wordv+1); ! 205: nwordv[0] = strsave(currentfilename); ! 206: nwordv[1] = strsave(c_linenumber); ! 207: if (!longpiptr){ ! 208: nwordv[2] = "pascal errortype"; ! 209: nwordv[3] = wordv[1]; ! 210: nwordv[4] = strsave("%%%\n"); ! 211: if (strlen(nwordv[5]) > (8-2)) /* this is the pointer */ ! 212: nwordv[5] += (8-2); /* bump over 6 characters */ ! 213: } ! 214: wordv = nwordv - 1; /* convert to 1 based */ ! 215: wordc += longpiptr ? 2 : 4; ! 216: return(C_TRUE); ! 217: } ! 218: if ( (wordc >= 4) ! 219: && (strlen(wordv[1]) == 1) ! 220: && ( (*wordv[1] == 'E') || (*wordv[1] == 'w') || (*wordv[1] == 'e') ) ! 221: && (alldigits(wordv[2])) ! 222: && (strlen(wordv[3]) == 1) ! 223: && (wordv[3][0] == '-') ! 224: ){ ! 225: /* ! 226: * Message of the form: letter linenumber - message ! 227: * Turn into form: filename linenumber letter - message ! 228: */ ! 229: language = INPI; ! 230: nwordv = wordvsplice(1, wordc, wordv + 1); ! 231: nwordv[0] = strsave(currentfilename); ! 232: nwordv[1] = wordv[2]; ! 233: nwordv[2] = wordv[1]; ! 234: c_linenumber = wordv[2]; ! 235: wordc += 1; ! 236: wordv = nwordv - 1; ! 237: return(C_TRUE); ! 238: } ! 239: if ( (wordc >= 3) ! 240: && (strlen(wordv[1]) == 1) ! 241: && ( (*(wordv[1]) == 'E') || (*(wordv[1]) == 'w') || (*(wordv[1]) == 'e') ) ! 242: && (strlen(wordv[2]) == 1) ! 243: && (wordv[2][0] == '-') ! 244: ) { ! 245: /* ! 246: * Message of the form: letter - message ! 247: * This happens only when we are traversing the tree ! 248: * during the second pass of pi, and discover semantic ! 249: * errors. ! 250: * ! 251: * We have already (presumably) saved the header message ! 252: * and can now construct a nulled error message for the ! 253: * current file. ! 254: * ! 255: * Turns into a message of the form: ! 256: * filename (header) letter - message ! 257: * ! 258: * First, see if it is a message referring to more than ! 259: * one line number. Only of the form: ! 260: * %s undefined on line%s ! 261: * %s improperly used on line%s ! 262: */ ! 263: boolean undefined = 0; ! 264: int wordindex; ! 265: ! 266: language = INPI; ! 267: if ( (undefined = (wordvcmp(wordv+2, 3, pi_und1) == 0) ) ! 268: || (undefined = (wordvcmp(wordv+2, 3, pi_und2) == 0) ) ! 269: || (wordvcmp(wordv+2, 4, pi_imp1) == 0) ! 270: || (wordvcmp(wordv+2, 4, pi_imp2) == 0) ! 271: ){ ! 272: for (wordindex = undefined ? 5 : 6; wordindex <= wordc; ! 273: wordindex++){ ! 274: nwordv = wordvsplice(2, undefined ? 2 : 3, wordv+1); ! 275: nwordv[0] = strsave(currentfilename); ! 276: nwordv[1] = wordv[wordindex]; ! 277: if (wordindex != wordc) ! 278: erroradd(undefined ? 4 : 5, nwordv, ! 279: C_TRUE, C_UNKNOWN); ! 280: } ! 281: wordc = undefined ? 4 : 5; ! 282: wordv = nwordv - 1; ! 283: return(C_TRUE); ! 284: } ! 285: ! 286: nwordv = wordvsplice(1+3, wordc, wordv+1); ! 287: nwordv[0] = strsave(currentfilename); ! 288: nwordv[1] = strsave(c_header[0]); ! 289: nwordv[2] = strsave(c_header[1]); ! 290: nwordv[3] = strsave(c_header[2]); ! 291: wordv = nwordv - 1; ! 292: wordc += 1 + 3; ! 293: return(C_THISFILE); ! 294: } ! 295: if (strcmp(wordv[1], "...") == 0){ ! 296: /* ! 297: * have a continuation error message ! 298: * of the form: ... message ! 299: * Turn into form : filename linenumber message ! 300: */ ! 301: language = INPI; ! 302: nwordv = wordvsplice(1, wordc, wordv+1); ! 303: nwordv[0] = strsave(currentfilename); ! 304: nwordv[1] = strsave(c_linenumber); ! 305: wordv = nwordv - 1; ! 306: wordc += 1; ! 307: return(C_TRUE); ! 308: } ! 309: if( (wordc == 6) ! 310: && (lastchar(wordv[6]) == ':') ! 311: && (isdateformat(5, wordv + 1)) ! 312: ){ ! 313: /* ! 314: * Have message that tells us we have changed files ! 315: */ ! 316: language = INPI; ! 317: currentfilename = strsave(wordv[6]); ! 318: clob_last(currentfilename, '\0'); ! 319: return(C_SYNC); ! 320: } ! 321: if( (wordc == 3) ! 322: && (strcmp(wordv[1], "In") == 0) ! 323: && (lastchar(wordv[3]) == ':') ! 324: && (instringset(wordv[2], Piroutines)) ! 325: ) { ! 326: language = INPI; ! 327: c_header = wordvsplice(0, wordc, wordv+1); ! 328: return(C_SYNC); ! 329: } ! 330: /* ! 331: * now, check for just the line number followed by the text ! 332: */ ! 333: if (alldigits(wordv[1])){ ! 334: language = INPI; ! 335: c_linenumber = wordv[1]; ! 336: return(C_IGNORE); ! 337: } ! 338: /* ! 339: * Attempt to match messages refering to a line number ! 340: * ! 341: * Multiply defined label in case, lines %d and %d ! 342: * Goto %s from line %d is into a structured statement ! 343: * End matched %s on line %d ! 344: * Inserted keyword end matching %s on line %d ! 345: */ ! 346: multiple = structured = 0; ! 347: if ( ! 348: ( (wordc == 6) && (wordvcmp(wordv+1, 2, pi_Endmatched) == 0)) ! 349: || ( (wordc == 8) && (wordvcmp(wordv+1, 4, pi_Inserted) == 0)) ! 350: || ( multiple = ((wordc == 9) && (wordvcmp(wordv+1,6, pi_multiple) == 0) ) ) ! 351: || ( structured = ((wordc == 10) && (wordvcmp(wordv+6,5, pi_structured) == 0 ) )) ! 352: ){ ! 353: language = INPI; ! 354: nwordv = wordvsplice(2, wordc, wordv+1); ! 355: nwordv[0] = strsave(currentfilename); ! 356: nwordv[1] = structured ? wordv [5] : wordv[wordc]; ! 357: wordc += 2; ! 358: wordv = nwordv - 1; ! 359: if (!multiple) ! 360: return(C_TRUE); ! 361: erroradd(wordc, nwordv, C_TRUE, C_UNKNOWN); ! 362: nwordv = wordvsplice(0, wordc, nwordv); ! 363: nwordv[1] = wordv[wordc - 2]; ! 364: return(C_TRUE); ! 365: } ! 366: return(C_UNKNOWN); ! 367: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.