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

Defined functions

alldigits defined in line 121; used 4 times
instringset defined in line 128; used 3 times
isdateformat defined in line 139; used 1 times
pi defined in line 169; used 2 times
piptr defined in line 151; used 1 times

Defined variables

Days defined in line 100; used 1 times
Months defined in line 95; used 1 times
Piroutines defined in line 103; used 1 times
c_header defined in line 10; used 4 times
c_linenumber defined in line 8; used 4 times
multiple defined in line 108; used 3 times
pi_Endmatched defined in line 110; used 1 times
pi_Inserted defined in line 111; used 1 times
pi_imp1 defined in line 118; used 1 times
pi_imp2 defined in line 119; used 1 times
pi_multiple defined in line 113; used 1 times
pi_structured defined in line 114; used 1 times
pi_und1 defined in line 116; used 1 times
pi_und2 defined in line 117; used 1 times
sccsid defined in line 1; never used
structured defined in line 108; used 3 times
unk_hdr defined in line 9; used 1 times
  • in line 10
Last modified: 1983-06-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1254
Valid CSS Valid XHTML 1.0 Strict