Previous Next Contents Index Doc Set Home


Error Diagnostics

9


This chapter discusses the errors you may come across while writing software programs with Pascal. It contains the following sections:

Compiler Syntax Errors

page 209

Compiler Semantic Errors

page 214

Compiler Panics, I/O Errors

page 221

Runtime Errors

page 221


Note - Appendix B, "Error Messages," lists in numerical order all the error messages generated by Pascal.


Compiler Syntax Errors

Here are some common syntax errors in Pascal programs and the ways that the compiler handles them.

Illegal Characters

Characters such as @ are not part of Pascal. If they are found in the source program and are not part of a string constant, a character constant, or a comment, they are considered to be illegal characters. This error can happen if you leave off a closing string quotation mark (').

Most nonprinting characters in your input are also illegal, except in character constants and character strings. Except for the tab and formfeed characters, which are used to format the program, nonprinting characters in the input file print as the character ? in your listing.

String Errors

Encountering an end-of-line after an opening string quotation mark (') without first encountering the matching closing quote yields the diagnostic:

Unmatched ' for string.
Also, anything enclosed in double quotes (for example, "hello") is treated as a comment and is, therefore, ignored.

Programs containing # characters (other than in column 1 or in arbitrary-based integers) can produce this diagnostic, because early implementations of Pascal use # as a string delimiter. In this version, # is used for #include and preprocessor directives, and must be in column 1.

Digits in Real Numbers

Pascal requires digits in real numbers before the decimal point. Thus, the statements b := .075; and c := 05e-10; generate the following diagnostics in Pascal:

Mon Feb 13 10:46:44 1995 digerr.p:
           5  	b:= .075;
e 18740-------------------^---  Digits required before decimal 
point
           6  	c:= .05e-10
e 18740-------------------^---  Digits required before decimal 
point

These constructs are also illegal as data input to variables in read statements whose arguments are variables of type real, single, shortreal, double, and longreal.

Replacements, Insertions, and Deletions

When Pascal encounters a syntax error in the input text, the compiler invokes an error recovery procedure. This procedure examines the input text immediately after the point of error and uses a set of simple corrections to determine whether or not to allow the analysis to continue. These corrections involve replacing an input token with a different token or inserting a token. Most of these changes do not cause fatal syntax errors.

The exception is the insertion of or replacement with a symbol, such as an identifier or a number; in these cases, the recovery makes no attempt to determine which identifier or what number should be inserted. Thus, these are considered fatal syntax errors.

The Pascal program, synerr.p, which uses ** as an exponentiation operator

program synerr_example(output);

var i, j are integer;

begin
    for j :* 1 to 20 begin
        write(j);
        i = 2 ** j;
        writeln(i))
    end
end. { synerr_example }

synerr.p produces a fatal syntax error when you compile it because Pascal does not have an exponentiation operator.

hostname% pc synerr.p
Mon Feb 13 10:56:19 1995 synerr.p:
           3  var i, j are integer;
e 18460----------------^---  Replaced identifier with a ':'
           6      for j :* 1 to 20 begin
E 18490-----------------^---  Expected keyword (null)
E 18460-----------------^---  Replaced ':' with a identifier
e 18480----------------------------^---  Inserted keyword do
           8          i = 2 ** j;
e 18480---------------^---  Inserted keyword if
E 18480----------------------^---  Inserted identifier
e 18480-------------------------^---  Inserted keyword then
           9          writeln(i))
e 18450-------------------------^---  Deleted ')'

Undefined or Improper Identifiers

If an identifier is encountered in the input but is undeclared, the error recovery mechanism replaces it with an identifier of the appropriate class.

Further references to this identifier are summarized at the end of the containing procedure, function, or at the end of the program. This is the case if the reference occurs in the main program.

Similarly, if you use an identifier in an inappropriate way, for example, if a type identifier is used in an assignment statement, pc produces a diagnostic and inserts an identifier of the appropriate class. Further incorrect references to this identifier are flagged only if they involve incorrect use in a different way. pc summarizes all incorrect uses in the same way it summarizes uses of undeclared variables.

Expected Symbols and Malformed Constructs

If none of the corrections mentioned previously appears reasonable, the error recovery routine examines the input to the left of the point of error to see if there is only one symbol that can follow this input. If so, the recovery prints a diagnostic which indicates that the given symbol is expected.

In cases where none of these corrections resolve the problems in the input, the recovery may issue a diagnostic that indicates "malformed" input. If necessary, pc can then skip forward in the input to a place where analysis can continue. This process may cause some errors in the missed text to be skipped.

See this example:

The Pascal program, synerr2.p. Here output is misspelled, and a is given a FORTRAN-style variable declaration.

program synerr2_example(input,outpu);

integer a(10)

begin
    read(b);
    for c := 1 to 10 do
        a(c) := b * c
end. { synerr2_example }

These are the error messages you receive when you compile synerr2.p. On line 6, parentheses are used for subscripting (as in FORTRAN), rather than the square brackets that are used in Pascal.

The compiler noted that a was not defined as a procedure (delimited by parentheses in Pascal). Since you cannot assign values to procedure calls, pc diagnosed a malformed statement at the point of assignment.

hostname% pc synerr2.p
Mon Feb 13 11:02:04 1995 synerr2.p:
           3  integer a(10)
e 18480-------^---  Inserted '['
E 18490-----------------^---  Expected identifier
           6      read(b);
E 18420----------------^---  Undefined variable
           7      for c := 1 to 10 do
E 18420---------------^---  Undefined variable
           8          a(c) := b * c
E 18420---------------^---  Undefined procedure
E 15010 line 1 -  File output listed in program statement but not 
declared
In program synerr2_example:
E 18240 a undefined on line 8
E 18240 b undefined on lines 6 8
E 18240 c undefined on lines 7 8

Expected and Unexpected End-of-file

If pc finds a complete program, but there is more (noncomment) text in the input file, then it indicates that an end-of-file is expected. This situation may occur after a bracketing error, or if too many ends are present in the input. The message may appear after the recovery says that it Expected '.' because a period (.) is the symbol that terminates a program.

If severe errors in the input prohibit further processing, pc may produce a diagnostic message followed by QUIT. Examples include unterminated comments and lines longer than 1,024 characters.

The Pascal program, mism.p

program mismatch_example(output);

begin
    writeln('***');
    { The next line is the last line in the file. }
    writeln

When you compile mism.p, the end-of-file is reached before an end delimiter

hostname% pc mism.p
E 26020-------^---  Malformed declaration
  15130-------^---  Unexpected end-of-file - QUIT


Compiler Semantic Errors

The following sections explain the typical formats and terminology used in Pascal error messages.

Format of the Error Diagnostics

In the example program above, the error diagnostics from the Pascal compiler include the line number in the text of the program, as well as the text of the error message. While this number is most often the line where the error occurred, it can refer to the line number containing a bracketing keyword like end or until. If so, the diagnostic may refer to the previous statement. This diagnostic occurs because of the method the compiler uses for sampling line numbers. The absence of a trailing semicolon (;) in the previous statement causes the line number corresponding to the end or until to become associated with the statement.

As Pascal is a free-format language, the line number associations can only be approximate and may seem arbitrary in some cases.

Incompatible Types

Since Pascal is a strongly-typed language, many type errors can occur, which are called type clashes by the compiler.

The Pascal compiler distinguishes among the following type classes in its diagnostics:

array

integer

scalar

boolean

pointer

string

char

real

varying

file

record

Thus, if you try to assign an integer value to a char variable, you receive a diagnostic as follows:

Mon Feb 13 13:16:20 1995 inchar.p:
E 25190 line 6 -  Type clash: integer is incompatible with char
  ... 25560: Type of expression clashed with type of variable in assignment

In this case, one error produces a two-line error message. If the same error occurs more than once, the same explanatory diagnostic is given each time.

The scalar Class

The only class whose meaning is not self-explanatory is scalar. It has a precise meaning in the Pascal standard where it refers to char, integer, and boolean types as well as the enumerated types. For the purposes of the Pascal compiler, scalar in an error message refers to a user-defined enumerated type, such as color in:

type color = (red, green, blue)
For integers, the more precise denotation integer is used.

Procedure and Function Type Errors

For built-in procedures and functions, two kinds of errors may occur. If a routine is called with the wrong number of arguments, a message similar to the following is displayed:

Mon Feb 13 13:21:26 1995 sin.p:
E 10010 line 6 -  Builtin function SIN takes exactly 1 argument

If the type of an argument is wrong, you receive a message similar to the following:

Mon Feb 13 13:31:14 1995 abs.p:
E 10180 line 8 -  Argument to ABS must be of type integer or real, not char

Scalar Error Messages

Error messages stating that scalar (user-defined) types cannot be read from and written to files are often difficult to interpret. In fact, if you define:

type color = (red, green, blue)
standard Pascal does not associate these constants with the strings red, green, and blue in any way. Pascal adds an extension so that enumerated types can be read and written; however, if the program is to be portable, you must write your own routines to perform these functions.

Standard Pascal only allows the reading of characters, integers, and real numbers from text files, including input (not strings or booleans). You can make the following declaration:

file of color
However, the representation is binary rather than as strings, and it is impossible to define input as other than a text file.

Expression Diagnostics

The diagnostics for semantically ill-formed expressions are explicit, as the following program shows. This program, expr.p, is admittedly far-fetched, but illustrates that the error messages are clear enough so you can easily determine the problem in the expressions.

program expr_example(output);

var
    a: set of char;
    b: Boolean;
    c: (red, green, blue);
    p: ^ integer;
    A: alfa;
    B: packed array [1..5] of char;

begin
    b := true;
    c := red;
    new(p);
    a := [];
    A := 'Hello, yellow';
    b := a and b;
    a := a * 3;
    if input < 2 then writeln('boo');
    if p <= 2 then writeln('sure nuff');
    if A = B then writeln('same');
    if c = true then writeln('hue''s and color''s')
end. { expr_example }

This program generates the following error messages:

hostname% pc expr.p
Mon Feb 13 13:36:51 1995 expr.p:
E 13050 line 16 -  Constant string too long
E 20070 line 17 -  Left operand of and must be Boolean, not set
E 25550 line 18 -  expression has invalid type
E 20030 line 18 -  Cannot mix sets with integers and reals as operands of *
E 20240 line 19 -  files may not participate in comparisons
E 20230 line 20 -  pointers and integers cannot be compared - operator was <=
E 20220 line 21 -  Strings not same length in = comparison
E 20230 line 22 -  scalars and Booleans cannot be compared - operator was =

Type Equivalence

The Pascal compiler produces several diagnostics that generate the following message:

non-equivalent types
In general, Pascal considers types to be the same only if they derive from the same type identifier. Therefore, the following two variables have different types, even though the types look the same and have the same characteristics.

x : record
		a: integer;
		b: char;
	end;
y :  record 
		a: integer;
		b: char;
	end;

The assignment:

x := y
produces the following diagnostic messages:

Mon Feb 13 14:22:46 1995 inchar.p:
E 25170 line 12 -  Type clash: non-identical record types
   ... 25560: Type of expression clashed with type of variable in assignment

To make the assignment statement work, you must declare a type and use it to declare the variables, as follows:

type
	r = record
		a: integer;
		b: char;
	end;
var
	x: r;
 	y: r;

Alternatively, you could use the declaration:

x, y : record
		a: integer;
		b: char;
	end;

The assignment statement then works.

Unreachable Statements

Pascal flags unreachable statements. Such statements usually correspond to errors in the program logic, as shown in the following example:

The Pascal program, unreached.p

program unreached_example(output);

label
    1;

begin
    goto 1;
    writeln('Unreachable.');
    1:
    writeln('Reached this.');
end. { unreached_example }

This error message is generated when you compile unreached.p.

hostname% pc unreached.p
Tue Feb 14 14:21:03 1995 unreached.p:
w 18630 line 8 -  Unreachable statement

A statement is considered to be reachable if there is a potential path of control, even if it cannot be taken. Thus, no diagnostic is produced for the statement:

if false then
writeln('Impossible!')

The goto Statement

Pascal detects and produces an error message about goto statements that transfer control into structured statements--for example, for and while. It does not allow such jumps, nor does it allow branching from the then part of an if statement into the else part. Such checks are made only within the body of a single procedure or function.

Uninitialized Variables

Pascal does not necessarily set variables to an initial value unless you explicitly request that with the -Z option. The exception is static variables, which are guaranteed to be initialized with zero values.

Because variable use is not tracked across separate compilation units, pc does nothing about uninitialized or unused variables in global scope, that is, in the main program. However, pc checks variables with local scope--those declared in procedures and functions, to make sure they are initialized before being used. pc flags uninitialized variables with a warning message.

Unused Variables, Constants, Types, Labels, and Routines

If you declare a variable, constant, type, procedure, or function in local scope but never use it, Pascal gives you a warning message. It does not do this for items declared in global scope because you can use the items in a separately compiled unit.

If you declare a label but never use it, Pascal gives you a warning. This is true even for a label declared in global scope.


Compiler Panics, I/O Errors

One class of error that rarely occurs, but which causes termination of all processing when it does, is a panic.

A panic indicates a compiler-detected internal inconsistency. A typical panic message follows:

pc0 internal error line=110 yyline=109
If you receive such a message, compilation is terminated. Save a copy of your program, then contact Sun Customer Support. If you were making changes to an existing program when the problem occurred, you may be able to work around the problem by determining which change caused the internal error and making a different change or error correction to your program.

The only other error that aborts compilation when no source errors are detected is running out of memory. Most tables in Pascal, with the exception of the parse stack, are dynamically allocated, and can grow to take up a good deal of process space. In general, you can get around this problem with large programs by using the separate compilation facility. See Chapter 5, "Separate Compilation," for details.

If you receive an out of space message during translation of a large procedure or function, or one containing a large number of string constants, either break the procedure or function into smaller pieces or increase the maximum data segment size using the limit command of csh(1).


Runtime Errors

When Pascal detects an error in a program during runtime, it prints an error message and aborts the program, producing a core image.

Following is a list of runtime errors that Pascal generates:

<filename> : Attempt to read from a file open for writing
<filename> : Attempt to write to a file open for reading
<filename> : Bad data found on enumerated read
<filename> : Bad data found on integer read
<filename> : Bad data found on real read
<filename> : Bad data found on string read
<filename> : Bad data found on varying of char read
<filename> : Cannot close file
<filename> : Could not create file
<filename> : Could not open file
<filename> : Could not remove file
<filename> : Could not reset file
<filename> : Could not seek file
<filename> : Could not write to file
<filename> : File name too long (maximum of <number> exceeded
<filename> : File table overflow (maximum of <number> 
exceeded)
<filename> : Line limit exceeded
<filename> : Non-positive format widths are non-standard
<filename> : Overflow on integer read
<filename> : Tried to read past end of file
<filename> : eoln is undefined when eof is true
Argument <number> is out of the domain of atan
Argument to argv of <number> is out of range
Assertion #<number> failed: <assertion message>
Cannot close null file
Cannot compute cos(<number>)
Cannot compute sin(<number>)
Cannot open null file
Enumerated type value of <number> is out of range on output
Floating point division by zero
Floating point operand is signaling Not-A-Number
Floating point overflow
Floating point underflow
Illegal argument of <number> to trunc
Inexact floating point result
Integer divide by zero
Integer overflow
Internal error in enumerated type read
Invalid floating point operand
Label of <number> not found in case
Negative argument of <number> to sqrt
Non-positive argument of <number> to ln
Overflow/Subrange/Array Subscript Error
Pointer value (<number>) out of legal range
Ran out of memory
Range lower bound of <number> out of set bounds
Range upper bound of <number> out of set bounds
Reference to an inactive file
Second operand to MOD (<number>) must be greater than zero
Statement count limit of <number> exceeded
Subrange or array subscript is out of range
Sun FPA not enabled
Unknown SIGFPE code
Unordered floating point comparison
Value of <number> out of set bounds
Varying length string index <number> is out of range
exp(<number>) yields a result that is out of the range of 
reals
i = <number>: Bad i to pack(a,i,z)
i = <number>: Bad i to unpack(z,a,i)
pack(a,i,z): z has <number> more elements than a
substring outside of bounds of string
unpack(z,a,i): z has <number> more elements than a

Previous Next Contents Index Doc Set Home