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

Defined functions

alldigits defined in line 129; used 4 times
instringset defined in line 136; used 3 times
isdateformat defined in line 147; used 1 times
pi defined in line 177; used 2 times
piptr defined in line 159; used 1 times

Defined variables

Days defined in line 108; used 1 times
Months defined in line 103; used 1 times
Piroutines defined in line 111; used 1 times
c_header defined in line 18; used 4 times
c_linenumber defined in line 16; used 4 times
multiple defined in line 116; used 3 times
pi_Endmatched defined in line 118; used 1 times
pi_Inserted defined in line 119; used 1 times
pi_imp1 defined in line 126; used 1 times
pi_imp2 defined in line 127; used 1 times
pi_multiple defined in line 121; used 1 times
pi_structured defined in line 122; used 1 times
pi_und1 defined in line 124; used 1 times
pi_und2 defined in line 125; used 1 times
sccsid defined in line 8; never used
structured defined in line 116; used 3 times
unk_hdr defined in line 17; used 1 times
  • in line 18
Last modified: 1987-02-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3504
Valid CSS Valid XHTML 1.0 Strict