Chapter 1. Pascal Implementation
Prev |  | Next

## Chapter 1. Pascal Implementation

The Pascal language supported by the compiler is an implementation of ANSI Standard Pascal (ANSI/IEEE770X3.97-1983). This implementation complies with ANSI requirements except for the extensions. When this chapter refers to “SGI Pascal,” it means the IRIS-4D extended implementation of Pascal.

This chapter lists and describes the set of extensions that are supported by the Pascal compiler on the IRIS. The 1.2 Pascal Release Notes provide a detailed list of changes from the ANSI standard.

This implementation extends the ANSI definition of Pascal to provide features for application development, and to meet the following objectives:

- Provide extensions that make Pascal usable for a wide class of programs

- Anticipate the requirements of programmers

- Be consistent with the direction of the emerging extended standard

- Be consistent with the IRIX/C programming environment

Read Section 1.1 to learn how ANSI Pascal is extended in this implementation.

## Names

There are three extensions for names.

### Use of Underscores

SGI Pascal allows underscores (_) in identifiers. You can use underscores to make names that are composed of several words. You can also use an underscore as the first character of an identifier.

This feature is consistent with the use of underscores in the C language, making calls between SGI Pascal routines and C functions compatible.

Examples are shown below.

    read_integer
    _bits_per_word

### Lowercase in Public Names

Pascal is not case-sensitive to variable names. Be aware that this causes problems for Pascal names intended to be linked with C functions, because case is significant in C.

SGI Pascal converts to lowercase all characters in the names of external variables, procedures, or functions.

### Alphabetic Labels

SGI Pascal permits alphabetic labels in addition to numeric labels as specified by ANSI Pascal.

## Constants

There are four extensions for constants.

### Non-Decimal Number Constants

SGI Pascal allows the use of any radix from base 2 to 36.

It is often useful to write integer constants in a radix other than base 10. This occurs in programs that use data structures defined by the system. After base 10, base 2, 8, and 16 are the most frequently used bases.

You can specify a number in these bases with this form:

    base#number

where base is a decimal number in the range 2 to 36, and number is a number in the specified radix using a..z (either case) to denote the values 10 through 25.

The number must specify a value in the range 0..`maxint` (2147483647). The example below shows the number 42 as it would be written in several different bases:

    2#101010
    3#1120
    4#222
    8#52
    42
    10#42
    11#39
    16#2a

If the radix is a power of two (2, 4, 8, 16, or 32), the number may be negative if it specifies a 32-bit value. For example, 16#8000000 is -2147483648, which is the smallest integer contained in a 32-bit number.

### String Padding

SGI Pascal pads a string constant with blanks on the right according to its use. That is, assigning a 3-character literal to a 6-character variable causes the string literal to be treated as being 6 characters long. Assigning a 6-character literal string to a variable containing three characters causes an error.

ANSI Pascal requires that a literal character string have the same length as the variable with which it is used. Manually adding extra blanks invites errors, and changing a Pascal type definition would require manually changing all literal strings that are used with variables of that type.

### Non-Graphic Characters

Literal character strings cannot contain ASCII characters that have no graphic representation. Control characters are the most commonly used characters having no graphic representation.

SGI Pascal has a special form of character string, enclosed in double quotation marks, in which such characters may be included. A backslash ( \ ) escape character is used to signal the use of a special character. For example, the following line rings (beeps) the bell on an ASCII terminal.

    writeln(output, "\a")

Table 1-1, following, lists escape character sequences used to encode special characters.

Table 1-1. Escape Character Sequences

Character | Result
--- | ---
\a | alert (16#07)
\b | backspace (16#08)
\f | form feed (16#0c)
\n | newline (16#0a)
\r | char (16#0d)
\t | horizontal tab (16#09)
\v | vertical feed (16#0b)
\\ | backslash (16#5c)
\" | quotation mark (16#22)
\' | single quote (16#27)
\nnn | character with octal value of nnn
\xnnn | character with hexadecimal value of nnn.

### Constant Expressions

Using a constant expression in type definitions or constant definitions often makes programs easier to read and maintain. The following example shows one use of a constant expression. Changing a single definition (array_size) changes both the size of the array and the definition of the index type used to access it.

    const
      array_size = 100;
    type
      array_index = 0..array_size-1;
    var
    v : array[ array_index ] of integer;

SGI Pascal permits you to use a constant expression where you might ordinarily use a single integer or scalar constant. An expression can consist of any of the following operators and predefined functions, as shown in Table 1-2.

Table 1-2. Constant Operators and Predefined Functions

Operator | Function
--- | ---
+ | addition
- | subtraction and unary minus
* | multiplication
div | integer division
mod | modulo
= | equality relation
<> | inequality relation
< | less than
<= | less than or equal to
>= | greater than or equal to
> | greater than
() | parentheses
bitand | bitwise AND
bitor | bitwise OR
bitxor | bitwise exclusive-OR
lshift | logical left shift
rshift | logical right shift
lbound | low bound of array
hbound | high bound of array
first | lowest value of a scalar type
last | highest value of a scalar type
sizeof | the size (in bytes) of a data type
abs | absolute value
chr | inverse ordinal value of a scalar value
ord | the ordinal value of a scalar value
pred | the predecessor of a scalar value
succ | the successor of a scalar value
type-functions | converts from one type to another

SGI Pascal does not allow the use of a leading left parenthesis in constant expressions for the lower value of subrange types. That is, Pascal mistakenly assumes that:

    subrange = (11+12)*13 .. 14+15;

is an enumeration instead of a subrange.

## Statement Extensions

There are seven statement extensions.

### Ranges in Case Statement Constants

SGI Pascal permits the specification of value ranges in a `case` statement. You can specify the selectors in a case statement using the SGI Pascal range notation to mean all values inclusive, as in the following example.

    case i of
       1900..1999 : writeln('twentieth century');
       1800..1899 : writeln('nineteenth century');
       1700..1799 : writeln('eighteenth century');
       1600..1699 : writeln('seventeenth century');
    otherwise :
       write(i div 100:1);
       writeln('th century');
    end

### Otherwise Clause in Case Statement

SGI Pascal extends the `case` statement to allow an `otherwise` clause, which is the default statement when no case clause equal to the case value exists. You can include any number of statements between `otherwise` and `end`, as in the example in the section above.

If no `otherwise` is specified, and no case clause satisfies the case selector values during execution, a case error warning message is printed.

### Return Statement

SGI Pascal provides a `return` statement that permits a procedure or function to return to the caller without branching to the end of the procedure or function.

If used within a function, `return` may optionally supply a function result. Unless this expression is specified, the last value assigned to the function name is the function result. Using the `return` statement is equivalent to assigning the value in the expression to the function name and executing a `goto` to the end of a routine.

    function factorial(n:integer):integer;
       begin
          if n = 1 then return(1)
          else return(n*factorial(n-1))
     end;

### Continue Statement

The `continue` statement causes the flow of control to continue at the next iteration to the nearest enclosing loop statement (`for`, `while`, or `repeat`). If the statement is a `for` statement, the control variable is incremented and the termination test is performed.

    for J := 1 to i do begin
        if Line[J] = ' ' then continue;
        write(output, Line:J);
    end (for);f1

### Next Statement

The `next` statement performs the same function as the `continue` statement.

### Break Statement

The `break` statement causes the flow of control to exit the nearest enclosing loop statement (`for`, `while`, or `repeat`). This feature permits you to end a loop without using the test specified in the loop statement.

    while p <>  nil do begin
       if p^.flag = 0 then break;
       p := p^.next
    end;

### Exit Statement

The `exit` statement performs the same function as the `break` statement.

## Declaration Extensions

There are six declaration extensions.

### Separate Compilation

SGI Pascal permits breaking a program into several compilation units: one that contains the main program, and the others containing procedures or functions called by the main program. (The procedures and functions it calls need not be written in Pascal.)

SGI Pascal also permits separately compiled compilation units to share data.

The compilation unit that contains the main program (the program compilation unit) follows ANSI Pascal syntax for a program. Only one program compilation unit is permitted.

A compilation unit that contains separately compiled procedures and functions is called a separate compilation unit. In a separate compilation unit, procedure, functions, and variables are placed sequentially without any program headers or main program block.

SGI Pascal allows Pascal declarations to be placed before the program header, whereas ANSI Pascal does not. All procedures, functions, and variables preceding the program header are given external scope. This means that they may be called (as with procedures and functions) or used (as with variables) by separate compilation units.

Figure 1-1 shows the external declarations in a program compilation unit. The top box shows the code in the include file `externs.h`, and the declarations.

In this example, the `external` directives and other statements in the header file `externs.h` specify that `initialize` and `sum` (used by the main program) and their parameters are defined in a separate compilation unit. (The separate compilation unit is shown Figure 1-2.)

You can use the external directive to qualify only unnested routine names.

Figure 1-1. External Declarations in Header File

`Initialize` and `sum` must be defined when the main program is link edited. Consider the two commands below, in which the file `mainone.p` contains the Pascal source code for the main program, and `bodies.o` contains a previously compiled object module of `initialize` and `sum`:

    pc -c mainone.p                 (This compiles mainone.p)
    pc -o exec mainone.o bodies.o    (This link edits mainone with initialize

and `sum`)

The external directive is similar to the Pascal `forward` directive, because it declares a routine name and its parameters without defining the body of the routine. You can use the external directive only to qualify unnested routine names.

All procedures, functions, and variables at the outermost level have external scope.

Continuing with the example on the previous page, Figure 1-2 shows the separate compilation unit in which `initialize` and `sum` are defined with the `external` directive.

Figure 1-2. Separate Compilation Unit with External Declarations

Note that, in this example, the external declarations are placed in the include file `externs.h`. This reduces the chance of errors due to inconsistent declarations. Use include files this way for statements shared by multiple compilation units.

### Shared Variables

All variables that are declared at the outermost nesting of a compilation unit have an external scope and can be used in different compilation units.

The variable can have only one initializing clause and can be placed in only one compilation unit. Look again at the example above. It illustrates a variable named v that is accessed from both compilation units.

### Initialization Clauses

SGI Pascal permits an external variable to have a clause that initializes either a scalar, a set, an array, or a pointer. The BNF syntax of the extended variable declaration is shown below.

    var-decl ::= identifier-list ":" type-denoter
                              [" := "initial-clause]

        initial-clause ::= constant-expr |
         "[" initial-value-list "]"
        initial-value ::= constant-expr [".." constant-expr] |
               constant-expr ":" constant-expr |
               "otherwise" ":" constant-expr |
               "[" initial-value-list "]"
        initial-value-list ::= initial-value |
               initial-value-list "," initial-value

For scalar types, this initialization is very simple:

    var
       a : integer := 5;
       letter : char := 'x';
       x1 : real := 6.5;

An initial value may also be given to a structured type (array or set). Every element of an array must be initialized or given a specific default value.

    type
        color = (red, yellow, blue);
        hue = set of color;
        vector = array[1..100] of integer;
    var
        orange : hue := [red, yellow];
        white : hue :=
                [first(color)..last(color);
        name : packed array[1..32] of char :=
                'Silicon Graphics Computer Systems':
        vect : vector :=
               [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
               30 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
               otherwise : 99];
    pointers : array[0..127] of ^vector := [otherwise: nil];

The above clauses initialize two sets, a string, and two arrays. All elements of the array vect, except the first 10 elements and the 10 elements starting at index 30, are initialized to 99. The array pointers is initialized entirely to the value nil.

### Relax Declaration Ordering

The declaration clauses described in this section can be written in any order and may be repeated. The ANSI requirement that a declaration must precede any use must still be observed.

### Internal and Extern

If you declare a procedure or function with the `internal` attribute, the procedure or function becomes a local rather than global symbol. If you declare a procedure or function `extern`, you can define it in a separate file. In the following example, x is internal and therefore local:

    function x (num : integer) : integer ; internal;

### Function Return Types

Functions can return scalar types, records, arrays, and sets. For example:

    program main;
    type
        rec = record
        field1 : char;
        field2 : integer;
    end;
    var
        reca : rec;
    function xx : rec;
    var recb : rec;
    begin
        recb.field1 := 'a';
        recb.field2 := 9;
        xx := recb;
    end;
    begin
    reca := xx;
    end.

## Predefined Procedures

There are four extensions of predefined procedures.

### Assert

    assert(

    boolean-expr [,

    string])

The `assert` procedure evaluates a boolean expression and signals an execution time error (similar to a checking error) if the value is not true.

If you specify the optional string, the string is written to standard error, otherwise, this message is generated, along with the line number and file name of the `assert` statement that causes the error:

    assertion error in Pascal program

### Argv

    argv(

    integer-expr,

    string-var)

The `argv` procedure returns the i-th program argument, placing the result in a string. The string can be blank, padded, or truncated, as required.

The value of the first parameter must be in the range 0.. `argc-1`. Argument 0 is the name of the program.

### Date

    date(

    string-var)

The `date` procedure returns the current date.

The resulting string has the form yy/mm/dd, where yy is replaced with the last two digits of the year, mm is replaced with the number of the month (January is 01), and dd is replaced with the day of the month (the first day is 01).

If the string is less than 8 characters long, data is truncated on the right; if the string is longer than 8 characters, the string is padded with blanks on the right.

### Time

    time(

    string-var)

The `time` procedure returns the current time. The resulting string has the form hh:mm:ss, where hh is replaced with the hour (on the 24-hour clock), mm is replaced with minutes (00 means on the hour), and ss is replaced with seconds (00 means on the minute).

If the string is less than eight characters, data is truncated on the right; if the string is longer than eight characters, the string is padded with blanks on the right.

## Predefined Functions

There are 20 predefined function extensions.

### Type Functions

ANSI Pascal offers two predefined type functions, `ord` and`chr`, that convert predefined scalar types.

SGI Pascal allows all scalar types to have a conversion function that converts an integer into that scalar type. As in ANSI Pascal, the `ord` function converts from the scalar type to integer.

SGI Pascal lets all type identifiers for a scalar type be used in an expression to convert its integer argument into the corresponding scalar value. Thus, if color is an enumerated data type, `color(i)` is a function that returns the i-th element of the enumeration.

    boolean-var := boolean (integer-expr)
    char-var    := char(integer-expr)
    color-var   := color(

    integer-expr)

In Pascal, the `ord` function also operates on pointers, returning the machine address of the item referenced by the pointer. A data type identifier that represents a pointer data type can also be used to convert a cardinal number into a valid pointer of that type. This feature is highly machine-dependent and should be used sparingly.

### Min

    scalar-var  := min(

    scalar-expr[

    ,scalar-exp]...)

The `min` function returns the smallest of its scalar arguments. For example,`min`(-6, 3, 5) returns -6.

### Max

    scalar-var := max(

    scalar-expr[,

    scalar-expr]...)

The `max` function returns the largest of its scalar arguments. For example, `max`(-2, 3, 5) returns 5.

### Lbound

    scalar-var := lbound(

    array-type[

    ,index])

The `lbound` function returns the lower bound of the array type specified by the first argument. The array type must be specified by a type identifier or a variable whose type is array. If the array is multi-dimensional, then an optional second argument specifies the dimension. The default is 1, which specifies the first or outermost dimension.

### Hbound

    scalar-var := hbound(

    array-type[

    ,index])

The`hbound` function returns the upper bound of the array type specified by the first argument. The array type must be specified by a type identifier or a variable whose type is array. If the array is multi-dimensional, then an optional second argument specifies the dimension. The default is 1, which specifies the first or outermost dimension.

### First

    scalar-var := first(

    type-identifier)

The `first` function returns the first (lowest) value of the named scalar type. For example,`first`( `integer`) returns -2147483848.

You can use `first` to find the bottom end of a range, or other scalar data type. Scalar types include integers, ranges, boolean, characters and enumerations.

### Last

    scalar-var := last(

    type-identifier)

The `last` function returns the last (highest) value of the named scalar type. For example, `last`( `integer`) returns 2147483847 (`maxint`). Use it to find the top end of a range.

### Sizeof

    sizeof(

    type-id[,

    tagfield-value]...)

The `sizeof` function returns the number of bytes occupied by the data type specified as an argument. If the argument specifies a record with a variant record part, then additional arguments specify the value of each tagfield.

### Argc

    integer-var := argc

The `argc` function returns the number of arguments passed to the program. The value of the function is 1 or greater.

### Bitand

    integer-var := bitand(

    integer-expr,

    integer-expr)

The `bitand` function returns the bitwise AND of the two integer-valued operands.

### Bitor

    integer-var := bitor(

    integer-expr,

    integer-expr)

The `bitor` function returns the bitwise OR of the two integer-valued operands.

### Bitxor

    integer-var := bitxor(

    integer-expr,

    integer-expr)

The `bitxor` function returns the bitwise exclusive-OR of the two integer-valued operands.

### Bitnot

    integer-var := bitnot(

    integer-expr,

    integer-expr)

The `bitnot` function returns the bitwise NOT of the two integer-valued operands.

### Clock

    integer-var := clockf1

The `clock` function returns the number of milliseconds of processor time used by the current process.

### Lshift

    integer-var := lshift(

    integer-expr,

    integer-expr)

The `lshift` function returns the left shift of the first integer-valued operand by the amount specified in the second argument. Zeros are inserted on the right.

### Rshift

    integer-var := rshift(

    integer-expr,

    integer-expr)

The `rshift` function returns the right shift of the first integer-valued operand by the amount specified in the second argument. Sign bits are inserted on the left if the operand is an integer type; zero bits are inserted if the operand is a cardinal type. You can force zero bits with the following construct:

    rshift(cardinal(intexpr), shiftamount)

### Firstof

The `firstof` function is equivalent to the `first` function.

### Lastof

The `lastof` function is equivalent to the `last` function.

### Addr

The `addr` function returns a pointer to the variable or function argument. The argument can be a string constant but cannot be another other type of constant. The argument can not be a nested or internal procedure, or a variable.

### Bitsize

The `bitsize` function returns the size in bits of the data type indicated by the argument.

## I/O Extensions

There are six I/O extensions.

### Specifying Radix in the Write Statement

Pascal permits the specification of operands in a `write` statement that writes numbers in any radix from 2 through 36. The following code writes a number in each radix:

    for i := 2 to 36 do
      writeln('x is',x:1:i,' in radix',i:1);

A minus sign precedes any printed number if the type of the number is integer and the value is less than zero. If the type of the number is cardinal, then the compiler interprets the number as not having a sign and prints the sign bit as part of the number (rather than with a negative sign).

### Filename on Rewrite and Reset

SGI Pascal accepts an optional string argument that specifies the path name of the file to be opened or created. Otherwise, SGI Pascal creates a temporary file that exists only during program execution, in the directory `/tmp`.

    reset(inputfile [,string])
    rewrite(outputfile [,string])

### Reading Character Strings

SGI Pascal allows you to read characters into a character string array, while ANSI Pascal does not. A string is defined to be a packed array of char whose lower bond is 1 and whose upper bond is greater than 1.

In the following example, characters are read into the array one line at a time until the end-of-file (eof) is reached.

    program CountLines(input, output);
    type
        string80 = packed array[1..80] of char;
    var
        Line : string80;
     begin
        .
        .
       while not eof(input) do begin
              readln(input, Line)
           i := i+1;
       end; {while}
       write ('The number of lines is ', I:1);f1

### Reading and Writing Enumeration Types

SGI Pascal provides an extension to permit any enumerated scalar type to be specified as the operand of a `read` or a `write` to a text file.

Reading an enumeration value interprets the programmer-defined name, preceded optionally by blank, tab, or new-line characters. The end of the name is delimited by any character that is not a valid character of an identifier. The delimiting character is skipped. Good choices for delimiting characters are blanks, tabs, commas, or new-lines.

Writing an enumerated value causes the programmer defined name to be written out to the text file.

The following piece of code is an example of using enumerated values:

    program testenum(input, output);
    type
    color = (red, orange, yellow, green, blue, violet,
                black, white);
    var
       vcolor : color;
    begin
       repeat
           writeln('enter color');
           read(vcolor);
           writeln('The color is ', vcolor : 0);
       until eof;
    end.

If any color other than the one specified in the color enumeration is entered, the following message is displayed:

    enumerated value string not within type
              The color is red

where string represents the incorrect value entered.

When an incorrect value is entered, the first value in the enumeration (red in the example above) is written to the screen.

### Lazy I/O

SGI Pascal provides an extension to ANSI Pascal I/O that simplifies terminal-oriented I/O. Standard Pascal defines the file pointer of a text file to point to the first character of a line after a `reset` or `readln` operation. This makes it difficult to issue a prompt message because the physical I/O operation for the next line occurs at the end of the `readln` procedure.

SGI Pascal follows ANSI Pascal conventions, except that it does not perform physical I/O until the program user actually uses the file pointer.

In effect, it is lazy about performing the I/O operation. This allows the user to issue a prompt message after the `readln` (or reset) prior to the time when the user's terminal attempts to read the next line.

### Standard Error

SGI Pascal provides an additional predefined text file called `err`, which is mapped to IRIX standard error. Also, the files `input` and `output` are mapped to the IRIX file standard input and standard output.

## Predefined Data Type Extensions

There are six predefined data type extensions.

### Cardinal

SGI Pascal accepts the `cardinal` data type that represents an unsigned integer in the range 0..4294967295 ( 2 32 -1 ). If either operand of an expression is cardinal, then the compiler uses unsigned arithmetic.

### Double

SGI Pascal accepts a new predefined data type called `double` that represents a double-precision floating point number. If either operand of an expression is double, then the compiler uses double-precision.

### Pointer

SGI Pascal defines a new predefined data type called `pointer` that is compatible with any pointer type. This can be thought of as the type of the Pascal value `nil`. Use `pointer` to write procedures and functions that accept an arbitrary pointer type as an operand.

Note that you cannot directly de-reference a variable of this type because it is not bound to a base type. To de-reference it, you must first assign the variable to a normally typed pointer.

#### Procedure and Function Pointers

You can use the `addr` function to assign a value to a variable defined to be a procedure or function pointer. This is useful in passing the address of a procedure or function as a parameter. For example:

    var proc_ptr : ^procedure (i:integer);
    func_ptr : ^function (a,b:integer) : real;

### String

This new SGI Pascal predefined array type is defined as

    type string = array[1..80] of char;

### INTEGER16

A variable defined as `INTEGER16` represents a signed 16-bit integer, and occupies a halfword.

### INTEGER32

A variable defined as `INTEGER32` represents a signed 32-bit integer, and occupies a full word.

## Predefined Data Type Attributes

SGI Pascal supports two new data type attributes: `static` and `volatile`.

### static

The compiler will allocate space for a static variable and keep the name local to the procedure. The variable retains its value from one invocation of the procedure to the next. In the following example, k is a static integer.

    var first : boolean := true;
    j : integer;
    function show_static: integer;
    var k : static integer;
    i : integer;
    begin
        if first then begin
           k := 9;
           first := false;
        end else
        k := k + 3;
        show_static := k;
    end;
    program main;
    begin
        for j := 1 to 2 do
            writeln('Show_Static ;+ ',show_static:3);
    end.

### volatile

The compiler will not perform certain optimizations for a volatile variable. This is useful for retaining pointer references that might appear to the optimizer to be redundant.

### Static Arrays

SGI Pascal permits you to initialize a `static` variable of type `array` (single or multi-dimensional). For example:

    type foo = (one,two);
    var x : array [foo,foo] of foo := [[one,two], [two,one]];

### Static Variables of Type Record

SGI Pascal permits you to initialize `static` variables of type `record`. For example:

    type rec = record;
    field1 : integer;
    field2 : char;
    end

    var rec1 : rec := [1,'a'];
    rec2 : rec := [Field2 := 'M' ; Field1 := 3]'

### Packed Records

In packed records, fields of subrange data types based on integers and enumerated types are assumed by default to have word alignment. Thus, in allocating the field, the compiler skips bits as necessary to avoid crossing a word boundary. In extracting the field, the compiler always loads words. The base type of a subrange can now be specified using the `of` keyword, as in the following example:

    i: 0..32767 of INTEGER16;

This causes the field i to have halfword alignment. Similarly,

    i: 0..255 of char;

causes the field i to have the alignment of the data type char, that is, byte alignment.

## Parameter Extensions

### Univ

The compiler will not perform type checking for a parameter with the universal attribute Univ. The compiler will still perform size checking. For example:

    var y : real;
    procedure x (j: univ integer);
    …
    x(y);

### Conformant Array Parameters

Conformant array parameters allow array type parameters of functions and procedures to have variable dimensions. You can use any array that conforms to the parameter definition as an actual parameter. For example:

    procedure print (msg : array[min..max: integer] of char);
    var i : integer;
    begin
        for i := min to max do
            write(msg[i]);
        writeln;
    end;
    var
        large : array [-10..10] of char
        small : array [2..7] of char;

    begin
        … {Load some values into the arrays}
        print(large);
        print(small);
    end.

### In, Out, and In Out

These keywords specify the direction of parameter passing between routines. Parameters declared as type `in` can not be changed within the scope of the routine. Parameters declared as `out` are not expected to have a value when they enter the procedure, but are expected to have a value when they leave it. Flagging a parameter as `in` `out` tells the compiler that it contains a value and that the procedure is permitted to modify that value.

## Compiler Notes

These notes describe extensions that affect the compile process.

### Macro Preprocessor

SGI Pascal invokes the C preprocessor (`cpp`) before each compilation, allowing you to use `cpp` syntax in the program. The `cpp` variables LANGUAGE_PASCAL, LANGUAGE_C, LANGUAGE_FORTRAN, and LANGUAGE_ASSEMBLY are defined automatically, allowing you to build header files that can be used by different languages.

The following example shows two conditional statements, one written in Pascal and the other written in C.

    #ifdef LANGUAGE_PASCAL
    type
        pair =
            record
                 high, low : integer;
            end; {record}
    #end

    #ifdef LANGUAGE_C
    typedef struct {
        int high, low;
        } pair
    #end

You can also use the full conditional expression syntax of `cpp`, as well as C style comments ( /* ...*/ ), which are stripped during compilation.

### Short Circuiting

SGI Pascal always short circuits boolean expressions. Short circuiting is a technique where only a portion of a boolean expression is actually executed.

For example, in this code:

    if (P<>nil) and (P^.Count > 0) then

the expression involving `P^.Count` is not evaluated if the first expression is false. This extension is permitted by ANSI Pascal. A program that relies on this feature, as does this example, would not be portable.

### Translation Limits

The following table shows the maximum limits imposed on certain items by the Pascal compiler. Chapter 3 discusses set sizing rules in greater detail; see Chapter 3 for more information.

Table 1-3. Maximum Limits of Data Items

Pascal Specification | Maximum
--- | ---
Literal string length | 288
Procedure nesting levels | 20
Set size | 451 - 512 (see Section 3.4 for rules)
Significant characters | 32

### The -apc Option

This option enables some of the Apollo Pascal extensions that are implemented in the SGI Pascal compiler. This option must be passed to the SGI Pascal compiler by using `-Wf`, `-apc`.

These extensions include:

- `IN_RANGE`: This built-in function determines whether a specified scalar variable is within the defined range of an integer subrange or enumerated type.

      var i : -7..7;
      begin
      write(' enter i : ');
      readln(i);
      if (in_range(i)) then
      ....

- `DISCARD`: This procedure explicitly discards an expression value, which could include a value returned by a function call.

- Non-standard `MOD` operator: Under this flag the `MOD` operator returns a negative result when the dividend is negative.

- `DEFINE`: This attribute tells the compiler to allocate the variable in the static data area and to make its name accessible externally.

      var j : define integer := 9;

- `EXTERN`: This attribute tells the compiler not to allocate a space for the variable since it may be allocated in a separate compiled procedure.

- infix bit operators: These bitwise operators are:

  - & equivalent to `BITAND`

  - ! equivalent to `BITOR`

  - ~ equivalent to `BITNOT`

  Examples:

      var i,j : integer;
       .  .  .
      (i & j)
      (i ! j )
      (~ i)

- Type coercion: `TYPE`(var). Type coercions are a bitwise transfer from a variable of one data type to a variable of another data type.

      var i : integer;
      x : real;
      begin  i := 456;
      x := real(i);

  The variable x now contains the same bits that i does, not the same number value. Note that the SGI Pascal compiler currently implements type conversion using the above syntax. Under the `-apc` flag the compiler interprets this as a type coercion rather than type conversion.

- <type-id> pseudo function: SGI Pascal permits the use of the transfer function on the left hand side of an assignment statement.

      real(i) := x + y;

  The above means that the assignment is done in floating point mode and that the bits of i contain the same number as x+y.

- Constant strings may be assigned to non-packed arrays of char.

- Correctly aligned objects within a packed array are passed as `VAR` parameters.

- implicit null otherwise: If no `CASE` is taken and `OTHERWISE` is left undefined, the `CASE` statement has no effect and executes without an error.

- array initialization [N of C]: This form tells the compiler to initialize N elements of the array to the value C.

- Wild card array initialization: When initializing an array in the var part of a routine, the compiler can compute the first dimension of the array.

      var arr: array[1..*] of char := 'This is a test';

- Under the `-apc` flag `integer` is equivalent to `INTEGER16` and occupies two bytes of storage. Therefore, `MAXINT` = 32767.

- Real constants are permitted to be of the form “123.”

### The -casesense Option

Assert case sensitivity on variable names. The default is case insensitive, that is, variable names ABC and abc are considered to be the same identifier.

Prev | Table of Contents | Next
Introduction |  | Chapter 2. Compiling, Linking, and Running Pascal Programs