BSD 4_1_snap development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 21 Jul 1980 03:33:48 +0000 (19:33 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 21 Jul 1980 03:33:48 +0000 (19:33 -0800)
Work on file usr/doc/efl

Synthesized-from: CSRG/cd1/4.1.snap

usr/doc/efl [new file with mode: 0644]

diff --git a/usr/doc/efl b/usr/doc/efl
new file mode 100644 (file)
index 0000000..5ece358
--- /dev/null
@@ -0,0 +1,2969 @@
+.ds [[ \fR\z[\h'.15m'[\fP
+.ds ]] \fR\z]\h'.15m']\fP
+.ND "4 June 1979"
+. .TM 79-1273-6 39199 39199-11
+.RP
+.TL
+The Programming Language EFL
+.AU "MH 2C-570" 2059
+Stuart I. Feldman
+.AI
+.MH
+.OK
+Fortran
+Preprocessors
+Ratfor
+.AB
+.PP
+EFL is a clean, general purpose computer language intended to encourage
+portable programming.
+It has a uniform and readable syntax and good data and control flow structuring.
+EFL programs can be translated into efficient Fortran code,
+so the EFL programmer can take advantage of the ubiquity of Fortran,
+the valuable libraries of software written in that language, and the portability
+that comes with the use of a standardized language,
+without suffering from Fortran's many failings as a language.
+It is especially useful for numeric programs.
+The EFL language permits the programmer to express
+complicated ideas in a comprehensible way,
+while permitting access to the power of the Fortran environment.
+EFL can be viewed as a descendant of B. W. Kernighan's Ratfor [1];
+the name originally stood for `Extended Fortran Language'.
+The current version of the EFL compiler is written in
+portable C.
+.AE
+.CS 35 0 35 0 0 1
+.SH
+.ds ~ \\v'.25m'\\s+2~\\s-2\\v'-.25m'
+.if n .ls 2
+.EQ
+delim @@
+.EN
+.NH 1
+INTRODUCTION
+.NH 2
+Purpose
+.PP
+EFL is a clean, general purpose computer language intended to encourage
+portable programming.
+It has a uniform and readable syntax and good data and control flow structuring.
+EFL programs can be translated into efficient Fortran code,
+so the EFL programmer can take advantage of the ubiquity of Fortran,
+the valuable libraries of software written in that language, and the portability
+that comes with the use of a standardized language,
+without suffering from Fortran's many failings as a language.
+It is especially useful for numeric programs.
+Thus, the EFL language permits the programmer to express
+complicated ideas in a comprehensible way,
+while permitting access to the power of the Fortran environment.
+.NH 2
+History
+.PP
+EFL can be viewed as a descendant of B. W. Kernighan's Ratfor [1];
+the name originally stood for `Extended Fortran Language'.
+A. D. Hall designed the initial version of the language and wrote a preliminary version of a compiler.
+I extended and modified the language and wrote a full compiler (in C) for it.
+The current compiler is much more than a simple preprocessor:
+it attempts to diagnose all syntax errors, to provide readable Fortran output,
+and to avoid a number of niggling restrictions.  To achieve this goal, a sizable two-pass translator is needed.
+.NH 2
+Notation
+.PP
+In examples and syntax specifications,
+.B boldface
+type is used to indicate literal words and punctuation, such as
+\fBwhile\fR.
+Words in
+.I italic
+type
+indicate an item in a category, such as an
+.I expression.
+A construct surrounded by double brackets represents a list of one or more of those items, separated by commas.
+Thus, the notation
+.DS C
+\fI\*([[ item \*(]]\fR
+.DE
+could refer to any of the following:
+.DS B
+.I
+item
+item\fB, \fIitem
+\fIitem\fB, \fIitem\fB, \fIitem\fR
+.DE
+.PP
+The reader should have a fair degree of familiarity with some procedural language.
+There will be occasional references to Ratfor and to Fortran
+which may be ignored if the reader is unfamiliar with those languages.
+.bp
+.NH 1
+LEXICAL FORM
+.NH 2
+Character Set
+.PP
+The following characters are legal in an EFL program:
+.KS
+.TS
+center;
+ll.
+\fIletters     \fBa b c d e f g h i j k l m\fI
+       \fBn o p q r s t u v w x y z\fI
+digits \fB0 1 2 3 4 5 6 7 8 9\fI
+white space    \fIblank  tab\fI
+quotes \fB\'  "\fI
+sharp  \fB#\fI
+continuation   \fB\(ru\fI
+braces \fB{   }\fI
+parentheses    \fB(  )\fI
+other  \fB,   ;   :   .   +   \-   \(**   /\fI
+       \fB=   <   >   &   \*~   |   $\fI
+.TE
+.KE
+Letter case (upper or lower) is ignored except within strings,
+so `\fBa\fR' and `\fBA\fR' are treated as the same character.
+All of the examples below are printed in lower case.
+An exclamation mark (`\fB!\fR') may be used in place of a tilde (`\fB\*~\fR').
+Square brackets (`[' and `]') may be used in place of braces (`{' and `}').
+.NH 2
+Lines
+.PP
+EFL is a line-oriented language.
+Except in special cases (discussed below),
+the end of a line marks the end of a token and the end of a statement.
+The trailing portion of a line may be used for a comment.
+There is a mechanism for diverting input from one source file to another,
+so a single line in the program may be replaced by a number of lines from the other file.
+Diagnostic messages are labeled with the line number of the file on which they are detected.
+.NH 3
+White Space
+.PP
+Outside of a character string or comment,
+any sequence of one or more spaces or tab characters acts as a single space.
+Such a space terminates a token.
+.NH 3
+Comments
+.PP
+A comment may appear at the end of any line.
+It is introduced by a sharp (#) character,
+and continues to the end of the line.
+(A sharp inside of a quoted string does not mark a comment.)
+The sharp and succeeding characters on the line are discarded.
+A blank line is also a comment.
+Comments have no effect on execution.
+.NH 3
+Include Files
+.PP
+It is possible to insert the contents of a file at a point in the source text,
+by referencing it in a line like
+.DS C
+.B
+include joe
+.R
+.DE
+No statement or comment may follow an
+.B include
+on a line.
+In effect, the
+.B include
+line is replaced by the lines in the named file,
+but diagnostics refer to the line number in the included file.
+\fBInclude\fRs may be nested at least ten deep.
+.NH 3
+Continuation
+.PP
+Lines may be continued explicitly by using the underscore (\fB_\fR) character.
+If the last character of a line (after comments and trailing white space have been stripped) is an underscore,
+the end of line and the initial blanks on the next line are ignored.
+Underscores are ignored in other contexts (except inside of quoted strings).
+Thus
+.DS B
+     1_000_000_
+         000
+.DE
+equals @10 sup 9@.
+.PP
+There are also rules for continuing lines automatically:
+the end of line is ignored whenever it is obvious that the statement is not complete.
+To be specific, a statement is continued if the last token on a line is an operator, comma,
+left brace, or left parenthesis.
+(A statement is not continued just because of unbalanced braces or parentheses.)
+Some compound statements are also continued automatically;
+these points are noted in the sections on executable statements.
+.NH 3
+Multiple Statements on a Line
+.PP
+A semicolon terminates the current statement.
+Thus, it is possible to write more than one statement on a line.
+A line consisting only of a semicolon, or a semicolon following a semicolon, forms a null statement.
+.NH 2
+Tokens
+.PP
+A program is made up of a sequence of tokens.
+Each token is a sequence of characters.
+A blank terminates any token other than a quoted string.
+End of line also terminates a token unless explicit continuation (see above) is signaled by an underscore.
+.NH 3
+Identifiers
+.PP
+An identifier is a letter or a letter followed by letters or digits.
+The following is a list of the reserved words that have special meaning in EFL.
+They will be discussed later.
+.KF
+.TS
+center;
+lll .
+.B
+array  exit    precision
+automatic      external        procedure
+break  false   read
+call   field   readbin
+case   for     real
+character      function        repeat
+common go      return
+complex        goto    select
+continue       if      short
+debug  implicit        sizeof
+default        include static
+define initial struct
+dimension      integer subroutine
+do     internal        true
+double lengthof        until
+doubleprecision        logical value
+else   long    while
+end    next    write
+equivalence    option  writebin
+.R
+.TE
+.KE
+The use of these words is discussed below.
+These words may not be used for any other purpose.
+.NH 3
+Strings
+.PP
+A character string is a sequence of characters surrounded by quotation marks.
+If the string is bounded by single-quote marks ( \fB\'\fR ), it may contain double
+quote marks ( \fB"\fR ), and vice versa.
+A quoted string may not be broken across a line boundary.
+.DS
+.B
+ \'hello there\'
+ "ain\'t misbehavin\'"
+.R
+.DE
+.NH 3
+Integer Constants
+.PP
+An integer constant is a sequence of one or more digits.
+.DS B
+.B
+0
+57
+123456
+.R
+.DE
+.NH 3
+Floating Point Constants
+.PP
+A floating point constant contains a dot and/or an exponent field.
+An
+.I "exponent field"
+is a letter
+.B d
+or
+.B e
+followed by an optionally signed integer constant.
+If
+@I@
+and
+@J@
+are integer constants and
+@E@
+is an exponent field, then a floating constant has one of the following forms:
+.DS B
+.I
+ \fB.\fPI
+ I\fB.\fP
+ I\fB.\fPJ
+ IE
+ I\fB.\fPE
+ \fB.\fPIE
+ I\fB.\fPJE
+.R
+.DE
+.NH 3
+Punctuation
+.PP
+Certain characters are used to group or separate objects in the language.
+These are
+.TS
+center;
+ll.
+parentheses    (  )
+braces {  }
+comma  ,
+semicolon      ;
+colon  :
+end-of-line
+.TE
+The end-of-line is a token (statement separator)
+when the line is neither blank nor continued.
+.NH 3
+Operators
+.PP
+The EFL operators are written as sequences of one or more
+non-alphanumeric characters.
+.DS B
++   \-   \(**   /   \(**\(**
+<   <=   >   >=   ==   \*~=
+&&   |\||   &   |
++=   \-=   \(*=   /=   \(**\(**=
+&&=   |\||=      &=   |=
+\->   .   $
+.DE
+A dot (`\fB.\fR') is an operator when it qualifies a structure element name,
+but not when it acts as a decimal point in a numeric constant.
+There is a special mode (see the Atavisms section)
+in which some of the operators may be represented by a string consisting of a dot, an identifier, and a dot
+(\fIe.g., \fB.lt.\fR ).
+.NH 2
+Macros
+.PP
+EFL has a simple macro substitution facility.
+An identifier may be defined to be equal to a string of tokens;
+whenever that name appears as a token in the program,
+the string replaces it.
+A macro name is given a value in a
+.B define
+statement like
+.DS
+define count     n += 1
+.DE
+Any time the name
+.B count
+appears in the program, it is replaced by the statement
+.DS C
+.B
+n += 1
+.R
+.DE
+A
+.B define
+statement must appear alone on a line;
+the form is
+.DS  C
+\fBdefine   \fIname   \fIrest-of-line\fR
+.DE
+Trailing comments are part of the string.
+.NH 1
+PROGRAM FORM
+.NH 2
+Files
+.PP
+A
+.I file
+is a sequence of lines.
+A file is compiled as a single unit.
+It may contain one or more procedures.
+Declarations and options that appear outside of a procedure
+affect the succeeding procedures on that file.
+.NH 2
+Procedures
+.PP
+Procedures are the largest grouping of statements in EFL.
+Each procedure has a name by which it is invoked.
+(The first procedure invoked during execution, known as the
+.I main
+procedure,
+has the null name.)
+Procedure calls and argument passing are discussed in Section 8.
+.NH 2
+Blocks
+.PP
+Statements may be formed into groups inside of a procedure.
+To describe the scope of names, it is convenient to introduce the ideas of
+.I block
+and of
+.I "nesting level."
+The beginning of a program file is at nesting level zero.
+Any options, macro definitions,
+or variable declarations there are also at level zero.
+The text immediately following a
+.B procedure
+statement is at level 1.
+After the declarations,
+a left brace marks the beginning of a new block and increases the nesting level by 1;
+a right brace drops the level by 1.
+(Braces inside declarations do not mark blocks.)
+(See Section 7.2).
+An
+.B end
+statement marks the end of the procedure, level 1, and the return to level 0.
+A name
+(variable or macro)
+that is defined at level
+@k@
+is defined throughout that block and in all deeper nested levels in which that name is not
+redefined or redeclared.
+Thus, a procedure might look like the following:
+.DS B
+.ta .7i 1.4i 2.1i 2.8i
+.B
+#   block 0
+procedure george
+real x
+x = 2
+ . . .
+if(x > 2)
+       {       # new block
+       integer x       # a different variable
+       do x = 1,7
+               write(,x)
+       . . .
+       }       # end of block
+end    # end of procedure, return to block 0
+.DE
+.NH 2
+Statements
+.PP
+A statement is terminated by end of line or by a semicolon.
+Statements are of the following types:
+.DS B
+Option
+Include
+Define
+.sp .3
+Procedure
+End
+.sp .3
+Declarative
+Executable
+.DE
+The
+.B option
+statement is described in Section 10.
+The
+.B include,
+.B define,
+and
+.B end
+statements have been described above;
+they may not be followed by another statement on a line.
+Each procedure begins with a
+.B procedure
+statements and finishes with an
+.B end
+statement; these are discussed in Section 8.
+Declarations describe types and values of variables and
+procedures.
+Executable statements cause specific actions to be taken.
+A block is an example of an executable statement; it is made up
+of declarative and executable statements.
+.NH 2
+Labels
+.PP
+An executable statement may have a
+.I label
+which may be used in a branch statement.
+A label is an identifier followed by a colon, as in
+.DS B
+.B
+.ta 1i
+       read(, x)
+       if(x < 3) goto error
+       . . .
+error: fatal("bad input")
+.R
+.DE
+.NH 1
+DATA TYPES AND VARIABLES
+.PP
+EFL supports a small number of basic (scalar) types.
+The programmer may define objects made up of variables of basic type;
+other aggregates may then be defined in terms of previously defined aggregates.
+.NH 2
+Basic Types
+.PP
+The basic types are
+.DS B
+\fBlogical
+\fBinteger
+\fBfield(\fIm\|\fB:\fIn\|\fB)
+\fBreal
+\fBcomplex
+\fBlong real
+\fBlong complex
+\fBcharacter(\fIn\|\fB)
+.R
+.DE
+A logical quantity may take on the two values true and false.
+An integer may take on any whole number value in some machine-dependent range.
+A field quantity is an integer restricted to a particular closed interval
+@([m:n])@.
+A `real' quantity is a floating point approximation to a real or rational number.
+A long real is a more precise approximation to a rational.
+(Real quantities are represented as single precision floating point numbers;
+long reals are double precision floating point numbers.)
+A complex quantity is an approximation to a complex number, and is represented as a pair of reals.
+A character quantity is a fixed-length string of @n@ characters.
+.NH 2
+Constants
+.PP
+There is a notation for a constant of each basic type.
+.LP
+A logical may take on the two values
+.DS B
+.B
+true
+false
+.R
+.DE
+An integer or field constant is a fixed point constant,
+optionally preceded by a plus or minus sign, as in
+.DS B
+.B
+17
+\-94
++6
+0
+.R
+.DE
+A long real (`double precision') constant is a floating point constant containing an exponent field that
+begins with the letter
+.B d.
+A real (`single precision') constant is any other floating point constant.
+A real or long real constant may be preceded by a plus or minus sign.
+The following are valid
+.B real
+constants:
+.DS B
+.B
+ 17.3
+ \-.4
+ 7.9e\-6   @(~=~7.9 times 10 sup -6 )@
+14e9    @(~=~1.4 times 10 sup 10 )@
+.R
+.DE
+The following are valid
+.B "long real"
+constants
+.DS B
+.B
+ 7.9d\-6   @(~=~7.9 times 10 sup -6 )@
+5d3
+.R
+.DE
+.LP
+A character constant is a quoted string.
+.NH 2
+Variables
+.PP
+A variable is a quantity with a name and a location.
+At any particular time the variable may also have a value.
+(A variable is said to be
+.I undefined
+before it is initialized or assigned its first value,
+and after certain indefinite operations are performed.)
+Each variable has certain attributes:
+.NH 3
+Storage Class
+.PP
+The association of a name and a location is either
+transitory or permanent.
+Transitory association is achieved when arguments are passed to procedures.
+Other associations are permanent (static).
+(A future extension of EFL may include dynamically allocated variables.)
+.NH 3
+Scope of Names
+.PP
+The names of
+common areas
+are global,
+as are procedure names:
+these names may be used anywhere in the program.
+All other names are local to the block in which they are declared.
+.NH 3
+Precision
+.PP
+Floating point variables are either of normal or
+.B long
+precision.
+This attribute may be stated independently of the basic type.
+.NH 2
+Arrays
+.PP
+It is possible to declare rectangular arrays (of any dimension) of values of the same type.
+The index set is always a cross-product of intervals of integers.
+The lower and upper bounds of the intervals must be constants for arrays that are local or
+.B common.
+A formal argument array may have intervals that are of length equal to one of the other formal arguments.
+An element of an array is denoted by the array name followed by a parenthesized comma-separated list of integer values,
+each of which must lie within the corresponding interval.
+(The intervals may include negative numbers.)
+Entire arrays may be passed as procedure arguments or in input/output lists,
+or they may be initialized;
+all other array references must be to individual elements.
+.NH 2
+Structures
+.PP
+It is possible to define new types which are made up of elements of other types.
+The compound object is known as a
+.I structure;
+its constituents are called
+.I members
+of the structure.
+The structure may be given a name,
+which acts as a type name in the remaining statements within the scope of its declaration.
+The elements of a structure may be of any type
+(including previously defined structures),
+or they may be arrays of such objects.
+Entire structures may be passed to procedures or be used in input/output lists;
+individual elements of structures may be referenced.
+The uses of structures will be detailed below.
+The following structure might represent a symbol table:
+.DS B
+.B
+.ta .7i 1.4i 2.1i
+struct tableentry
+       {
+       character(8) name
+       integer hashvalue
+       integer numberofelements
+       field(0:1) initialized, used, set
+       field(0:10) type
+       }
+.DE
+.NH 1
+EXPRESSIONS
+.PP
+Expressions are syntactic forms that yield a value.
+An expression may have any of the following forms, recursively applied:
+.DS B
+.I
+primary
+\fB(\fI expression \fB)\fI
+unary-operator  expression
+expression  binary-operator  expression
+.DE
+In the following table of operators,
+all operators on a line have equal precedence
+and have higher precedence than operators on later lines.
+The meanings of these operators are described in sections 5.3 and 5.4.
+.DS B
+.B
+\->  .
+\(**\(**
+\(**  /      \fIunary\fB +  \-  ++  \-\-
++  \-
+<  <=  >  >=  ==  \*~=
+&  &&
+|  |\||
+$
+=  +=  \-=  \(**=  /=  \(**\(**=    &=  |=  &&=  |\||=
+.R
+.DE
+Examples of expressions are
+.DS B
+.B
+a<b && b<c
+\-(a + sin(x)) / (5+cos(x))\(**\(**2
+.R
+.DE
+.NH 2
+Primaries
+.PP
+Primaries are the basic elements of expressions, as follows:
+.NH 3
+Constants
+.PP
+Constants are described in Section 4.2.
+.NH 3
+Variables
+.PP
+Scalar variable names are primaries.
+They may appear on the left or the right side of an assignment.
+Unqualified names of aggregates (structures or arrays)
+may only appear as procedure arguments and in input/output lists.
+.NH 3
+Array Elements
+.PP
+An element of an array is denoted by the array name followed by a parenthesized list of subscripts,
+one integer value for each declared dimension:
+.DS B
+.B
+a(5)
+b(6,\|\-3,\|4)
+.R
+.DE
+.NH 3
+Structure Members
+.PP
+A structure name followed by a dot followed by the name of a member of that structure constitutes a reference to
+that element.
+If that element is itself a structure, the reference may be further qualified.
+.DS B
+.B
+a.b
+x(3).y(4).z(5)
+.R
+.DE
+.NH 3
+Procedure Invocations
+.PP
+A procedure is invoked by an expression of one of the forms
+.DS B
+\fIprocedurename \fB( )\fR
+\fIprocedurename \fB( \fIexpression\fB )\fR
+\fIprocedurename \fB( \fIexpression-1\fB, \fI...\fB, \fIexpression-n \fB)\fR
+.DE
+The
+.I procedurename
+is either the name of a variable
+declared
+.B external
+or it is the name of a
+function known to the EFL compiler (see Section 8.5),
+or it is the actual name of a procedure, as it appears in a
+.B procedure
+statement.
+If a
+.I procedurename
+is declared
+.B external
+and is an argument of the current procedure,
+it is associated with the procedure name passed as actual argument;
+otherwise it is the actual name of a procedure.
+Each
+.I expression
+in the above is called an
+.I "actual argument".
+Examples of procedure invocations are
+.DS B
+.B
+f(x)
+work()
+g(x, y+3, 'xx')
+.R
+.DE
+When one of these procedure invocations is to be performed,
+each of the actual argument expressions is first evaluated.
+The types, precisions, and bounds of actual and formal arguments should agree.
+If an actual argument is a variable name, array element, or structure member,
+the called procedure is permitted to use the corresponding formal argument as the left side
+of an assignment or in an input list;
+otherwise it may only use the value.
+After the formal and actual arguments are associated,
+control is passed to the first executable statement of the procedure.
+When a
+.B return
+statement is executed in that procedure,
+or when control reaches the
+.B end
+statement of that procedure,
+the function value is made available as the value of the procedure invocation.
+The type of the value is determined by the attributes of
+the
+.I procedurename
+that are declared or implied in the calling procedure,
+which must agree with the attributes declared for the function in its procedure.
+In the special case of a generic function,
+the type of the result is also affected by the type of the argument.
+See Chapter 8 for details.
+.NH 3
+Input/Output Expressions
+.PP
+The EFL input/output syntactic forms
+may be used as integer primaries that have
+a non-zero value
+if an error occurs during the input or output.
+See Section 7.7.
+.NH 3
+Coercions
+.PP
+An expression of one precision or type may be converted to another by an expression of the form
+.DS C
+\fIattributes \fB( \fIexpression \fB)\fR
+.DE
+At present, the only
+.I attributes
+permitted are precision and basic types.
+Attributes are separated by white space.
+An arithmetic value of one type may be coerced to any other arithmetic type;
+a character expression of one length may be coerced to a character expression of another length;
+logical expressions may not be coerced to a nonlogical type.
+As a special case,
+a quantity of
+.B complex
+or
+.B "long complex"
+type may be constructed from two integer or real quantities
+by passing two expressions (separated by a comma) in the coercion.
+Examples and equivalent values are
+.DS B
+.B
+integer(5.3) = 5
+long real(5) = 5.0d0
+complex(5,3) = @5+3i@
+.R
+.DE
+Most conversions are done implicitly,
+since most binary operators permit operands of different arithmetic types.
+Explicit coercions are of most use when it is necessary to convert the type of an actual argument
+to match that of the corresponding formal parameter in a procedure call.
+.NH 3
+Sizes
+.PP
+There is a notation which yields the amount of memory required to store a datum
+or an item of specified type:
+.DS B
+\fBsizeof ( \fIleftside\fB )
+\fBsizeof ( \fIattributes\fB )
+.R
+.DE
+In the first case,
+.I leftside
+can denote a variable, array, array element, or structure member.
+The value of
+.B sizeof
+is an integer, which gives the size in arbitrary units.
+If the size is needed in terms of the size of some specific unit, this
+can be computed by division:
+.DS B
+.B
+sizeof(x) / sizeof(integer)
+.R
+.DE
+yields the size of the variable
+.B x
+in integer words.
+.PP
+The distance between consecutive elements of an array may not equal
+.B sizeof
+because certain data types require final padding on some machines.
+The
+.B lengthof
+operator gives this larger value, again in arbitrary units.
+The syntax is
+.DS B
+\fBlengthof ( \fIleftside\fB )
+\fBlengthof ( \fIattributes\fB )
+.R
+.DE
+.NH 2
+Parentheses
+.PP
+An expression surrounded by parentheses is itself an expression.
+A parenthesized expression must be evaluated before an expression of which it is a part is evaluated.
+.NH 2
+Unary Operators
+.PP
+All of the unary operators in EFL are prefix operators.
+The result of a unary operator has the same type as its operand.
+.NH 3
+Arithmetic
+.PP
+Unary
+.B +
+has no effect.
+A unary
+.B \-
+yields the negative of its operand.
+.PP
+The prefix operator
+.B ++
+adds one to its operand.
+The prefix operator
+.B \-\-
+subtracts one from its operand.
+The value of either expression is the result of the addition or subtraction.
+For these two operators, the operand must be a scalar,
+array element, or structure member of arithmetic type.
+(As a side effect, the operand value is changed.)
+.NH 3
+Logical
+.PP
+The only logical unary operator is complement
+(\fB\*~\fR).
+This operator is defined by the equations
+.DS B
+.B
+\*~ true = false
+\*~ false = true
+.R
+.DE
+.NH 2
+Binary Operators
+.PP
+Most EFL operators have two operands, separated by the operator.
+Because the character set must be limited,
+some of the operators are denoted by strings of two or three special characters.
+All binary operators except exponentiation are left associative.
+.NH 3
+Arithmetic
+.PP
+The binary arithmetic operators are
+.KS
+.TS
+center;
+ll.
++      addition
+@-@    subtraction
+\(**   multiplication
+/      division
+\(**\(**       exponentiation
+.TE
+.KE
+Exponentiation is right associative:
+a\(**\(**b\(**\(**c = a\(**\(**(b\(**\(**c) = @a sup {(b sup c )}@
+The operations have the conventional meanings:
+@8+2~=~10@,
+@8-2 ~=~ 6@,
+@8\(** 2 ~=~ 16@,
+@8/2~=~ 4@,
+@8 \(**\(** 2 ~=~ 8 sup 2 ~=~ 64@.
+.PP
+The type of the result of a binary operation
+@A~op~B@
+is determined by the types of its operands:
+.KS
+.TS
+center;
+l|lllll .
+                       Type of B
+.sp .5
+Type of A      integer real    long real       complex long complex
+_
+integer        integer real    long real       complex long complex
+real   real    real    long real       complex long complex
+long real      long real       long real       long real       long complex    long complex
+complex        complex complex long complex    complex long complex
+long complex   long complex    long complex    long complex    long complex    long complex
+.TE
+.KE
+If the type of an operand differs from the type of the result,
+the calculation is done as if the operand were first coerced to the type of the result.
+If both operands are integers, the result is of type integer, and is computed exactly.
+(Quotients are truncated toward zero, so
+@8/3 = 2@.)
+.NH 3
+Logical
+.PP
+The two binary logical operations in EFL,
+.B and
+and
+.B or,
+are defined by the truth tables:
+.KS
+.TS
+center;
+cccc
+aaaa .
+A      B       A and B A or B
+_
+false  false   false   false
+false  true    false   true
+true   false   false   true
+true   true    true    true
+.R
+.TE
+.R
+.KE
+Each of these operators comes in two forms.
+In one form, the order of evaluation is specified.
+The expression
+.DS C
+.B
+a && b
+.R
+.DE
+is evaluated by first evaluating
+.B a ;
+if it is false then the expression is false and
+.B b
+is not evaluated;
+otherwise the expression has the value of
+.B b.
+The expression
+.DS C
+.B
+a |\|| b
+.R
+.DE
+is evaluated by first evaluating
+.B a;
+if it is true then the expression is true and
+.B b
+is not evaluated;
+otherwise the expression has the value of
+.B b.
+The other forms of the operators
+(\fB&\fR for \fBand\fR and \fB|\fR for \fBor\fR)
+do not imply an order of evaluation.
+With the latter operators,
+the compiler may speed up the code by
+evaluating the operands in any order.
+.NH 3
+Relational Operators
+.PP
+There are six relations between arithmetic quantities.
+These operators are not associative.
+.KS
+.TS
+center;
+ccs
+lll.
+EFL Operator   Meaning
+_
+<      <       less than
+<=     @<=@    less than or equal to
+==     @=@     equal to
+\*~=   @!=@    not equal to
+>      >       greater than
+>=     @>=@    greater than or equal
+.TE
+.KE
+Since the complex numbers are not ordered, the only relational operators that may take complex operands
+are
+\fB==\fR
+and
+\fB\*~=\fR .
+The character collating sequence is not defined.
+.NH 3
+Assignment Operators
+.PP
+All of the assignment operators are right associative.
+The simple form of assignment is
+.DS C
+\fIbasic-left-side  \fB=  \fIexpression\fR
+.DE
+A
+.I basic-left-side
+is a scalar variable name, array element, or structure member of basic type.
+This statement computes the expression on the right side, and stores that value
+(possibly after coercing the value to the type of the left side)
+in the location named by the left side.
+The value of the assignment expression is the value assigned to the left side after coercion.
+.PP
+There is also an assignment operator corresponding to each binary arithmetic and logical operator.
+In each case,
+@a ~op = ~ b@
+is equivalent to
+@a ~=~ a ~ op~ b@.
+(The operator and equal sign must not be separated by blanks.)
+Thus,
+.B n+=2
+adds 2 to n.
+The location of the left side is evaluated only once.
+.NH 2
+Dynamic Structures
+.PP
+EFL does not have an address (pointer, reference) type.
+However, there is a notation for dynamic structures,
+.DS B
+\fIleftside \fB\-> \fIstructurename\fR
+.DE
+This expression is a structure with the shape implied by
+.I structurename
+but starting at the location of
+.I leftside.
+In effect, this overlays the structure template at the specified location.
+The
+.I leftside
+must be a variable, array, array element, or structure member.
+The type of the
+.I leftside
+must be one of the types in the structure declaration.
+An element of such a structure is denoted in the usual way using the dot operator.
+Thus,
+.DS C
+.B
+place(i) \-> st.elt
+.R
+.DE
+refers to the
+.B elt
+member of the
+.B st
+structure starting at the
+@i sup th@
+element of the array
+.B place.
+.NH 2
+Repetition Operator
+.PP
+Inside of a list, an element of the form
+.DS C
+\fIinteger-constant-expression \fB$\fI constant-expression\fR
+.DE
+is equivalent to the appearance of the
+.I expression
+a number of times equal to the first expression.
+Thus,
+.DS C
+.B
+(3, 3$4, 5)
+.R
+.DE
+is equivalent to
+.DS C
+.B
+(3, 4, 4, 4, 5)
+.R
+.DE
+.NH 2
+Constant Expressions
+.PP
+If an expression is built up out of operators (other than functions) and constants,
+the value of the expression is a constant, and may be used anywhere a constant is required.
+.NH 1
+DECLARATIONS
+.PP
+Declarations statement describe the meaning, shape, and size of named
+objects in the EFL language.
+.NH 2
+Syntax
+.PP
+A declaration statement is made up of attributes and variables.
+Declaration statements are of two form:
+.DS B
+.I
+attributes  variable-list
+attributes  {  declarations  }
+.R
+.DE
+In the first case, each name in the
+.I variable-list
+has the specified attributes.
+In the second, each name in the declarations also has the specified attributes.
+A variable name may appear in more than one variable list,
+so long as the attributes are not contradictory.
+Each name of a nonargument variable may be accompanied by an initial value specification.
+The
+.I declarations
+inside the braces are one or more declaration statements.
+Examples of declarations are
+.DS B
+.B
+integer k=2
+.sp .5
+long real b(7,3)
+.sp .5
+common(cname)
+      {
+      integer i
+      long real array(5,0:3) x, y
+      character(7) ch
+      }
+.R
+.DE
+.ne 1i
+.NH 2
+Attributes
+.NH 3
+Basic Types
+.PP
+The following are basic types in declarations
+.DS
+.B
+logical
+integer
+field(@m:n@)
+character(@k@)
+real
+complex
+.R
+.DE
+In the above, the quantities @k@, @m@, and @n@ denote integer constant expressions with the properties
+@k>0@ and @n>m@.
+.NH 3
+Arrays
+.PP
+The dimensionality may be declared by an
+.B array
+attribute
+.EQ C
+bold array( b sub 1 , ..., b sub n bold )
+.EN
+Each of the @b sub i@
+may either be a single integer expression or a pair of integer expressions separated by a colon.
+The pair of expressions form a lower and an upper bound; the single expression is an upper bound with
+an implied lower bound of 1.
+The number of dimensions is equal to
+@n,@
+the number of bounds.
+All of the integer expressions must be constants.
+An exception is permitted only if all of the variables associated with an
+array declarator are formal arguments of the procedure; in this case, each bound
+must have the property that
+@upper - lower + 1@
+is equal to a formal argument of the procedure.
+(The compiler has limited ability to simplify expressions, but it will recognize
+important cases such as
+.B "(0:n\-1)".
+The upper bound for the last dimension
+@(b sub n )@
+may be marked by an asterisk
+( \fB\(**\fR )
+if the size of the array is not known.
+The following are legal @bold array@ attributes:
+.DS B
+.B
+array(5)
+array(5, 1:5, \-3:0)
+array(5, \(**)
+array(0:m\-1, m)
+.R
+.DE
+.NH 3
+Structures
+.PP
+A structure declaration is of the form
+.DS B
+\fBstruct \fIstructname \fB{ \fI declaration statements \fB}\fR
+.DE
+The
+.I structname
+is optional; if it is present, it acts as if it were the name of a type in the rest of its scope.
+Each name that appears inside the
+.I declarations
+is a
+.I member
+of the structure, and has a special meaning when used to qualify any variable declared with the structure type.
+A name may appear as a member of any number of structures,
+and may also be the name of an ordinary variable,
+since a structure member name is used only in contexts where the parent type is known.
+The following are valid structure attributes
+.DS B
+.B
+struct xx
+        {
+        integer a, b
+        real x(5)
+        }
+
+struct { xx z(3); character(5) y }
+.R
+.DE
+The last line defines a structure containing an array of three @bold xx 's@
+and a character string.
+.NH 3
+Precision
+.PP
+Variables of floating point
+(@bold real@ or @bold complex@) type may be declared to be
+@bold long@
+to ensure they have higher precision than ordinary floating point variables.
+The default precision is
+\fBshort\fR.
+.NH 3
+Common
+.PP
+Certain objects called
+.I common\ areas
+have external scope,
+and may be referenced by any procedure that has a declaration for the name using a
+.DS C
+\fBcommon ( \fI commonareaname \fB)\fR
+.DE
+attribute.
+All of the variables declared with a particular \fBcommon\fR attribute are in the same
+block; the order in which they are declared is significant.
+Declarations for the same block in differing procedures must have the variables in the same order and with the
+same types, precision, and shapes, though not necessarily with the same names.
+.NH 3
+External
+.PP
+If a name is used as the procedure name in a procedure invocation,
+it is implicitly declared to have the
+.B external
+attribute.
+If a procedure name is to be passed as an argument, it is necessary to declare
+it in a statement of the form
+.DS B
+\fBexternal \*([[ \fIname \fB\*(]]\fR
+.DE
+If a name has the external attribute and it is a formal argument of
+the procedure,
+then it is associated with a procedure identifier passed as an actual argument
+at each call.
+If the name is not a formal argument, then that name is the actual name
+of a procedure, as it appears in the corresponding
+.B procedure
+statement.
+.NH 2
+Variable List
+.PP
+The elements of a variable list in a declaration
+consist of a name,
+an optional dimension specification,
+and an optional initial value specification.
+The name follows the usual rules.
+The dimension specification is the same form and meaning as the parenthesized list in an
+.B array
+attribute.
+The initial value specification is an equal sign (\fB=\fR) followed by a constant expression.
+If the name is an array, the right side of the equal sign may be a parenthesized list of constant expressions,
+or repeated elements or lists; the total number of elements in the list must not exceed the number of elements of the
+array, which are filled in column-major order.
+.NH 2
+The Initial Statement
+.PP
+An initial value may also be specified for a simple variable,
+array, array element, or member of a structure
+using a statement of the form
+.DS B
+\fBinitial \*([[ \fIvar \fB= \fIval \*(]]\fR
+.DE
+The @var@ may be a variable name, array element specification, or member of structure.
+The right side follows the same rules as for an initial value specification
+in other declaration statements.
+.NH 1
+EXECUTABLE STATEMENTS
+.PP
+Every useful EFL program contains executable statements \(em
+otherwise it would not do anything and would not need to be run.
+Statements are frequently made up of other statements.
+Blocks are the most obvious case,
+but many other forms contain statements as constituents.
+.PP
+To increase the legibility of EFL programs,
+some of the statement forms can be broken without an explicit continuation.
+A square (\fR\(sq\fP) in the syntax represents a point where the end of a line will be ignored.
+.NH 2
+Expression Statements
+.NH 3
+Subroutine Call
+.PP
+A procedure invocation that returns no value is known as a subroutine call.
+Such an invocation is a statement.
+Examples are
+.DS B
+.B
+work(in, out)
+run(\|)
+.R
+.DE
+.PP
+Input/output statements (see Section 7.7)
+resemble procedure invocations
+but do not yield a value.
+If an error occurs
+the program stops.
+.NH 3
+Assignment Statements
+.PP
+An expression that is a simple assignment (\fB=\fR) or
+a compound assignment (\fB+=\fR etc.) is a statement:
+.DS B
+.B
+a = b
+a = sin(x)/6
+x \(**= y
+.R
+.DE
+.NH 2
+Blocks
+.PP
+A block is a compound statement that acts as a statement.
+A block begins with a left brace,
+optionally followed by declarations,
+optionally followed by executable statements,
+followed by a right brace.
+A block may be used anywhere a statement is permitted.
+A block is not an expression and does not have a value.
+An example of a block is
+.DS B
+.B
+ {
+ integer i     # this variable is unknown outside the braces
+.sp .3
+ big = 0
+ do i = 1,n
+     if(big < a(i))
+            big = a(i)
+ }
+.R
+.DE
+.NH 2
+Test Statements
+.PP
+Test statements permit execution of certain statements conditional on the truth of a predicate.
+.NH 3
+If Statement
+.PP
+The simplest of the test statements is the
+.B if
+statement, of form
+.DS C
+\fBif ( \fIlogical-expression\fB ) \fR\(sq\fP \fIstatement\fR
+.DE
+The logical expression is evaluated;
+if it is true, then the
+.I statement
+is executed.
+.NH 3
+If-Else
+.PP
+A more general statement is of the form
+.DS B
+\fBif ( \fIlogical-expression \fB) \fR\(sq\fP \fI statement-1 \fR\(sq\fP \fBelse \fR\(sq\fP \fI statement-2 \fR
+.DE
+If the expression is
+.B true
+then
+.I statement-1
+is executed, otherwise
+.I statement-2
+is executed.
+Either of the consequent statements may itself be an
+.B if-else
+so a completely nested test sequence is possible:
+.DS B
+.B
+if(x<y)
+    if(a<b)
+        k = 1
+    else
+        k = 2
+else
+    if(a<b)
+        m = 1
+    else
+        m = 2
+.R
+.DE
+An
+.B else
+applies to the nearest preceding un-\fBelse\fRd \fBif\fR.
+A more common use is as a sequential test:
+.DS B
+.B
+if(x==1)
+    k = 1
+else if(x==3  |  x==5)
+    k = 2
+else
+    k = 3
+.R
+.DE
+.NH 3
+Select Statement
+.PP
+A multiway test on the value of a quantity is succinctly stated as a
+.B select
+statement, which has the general form
+.DS B
+\fBselect( \fIexpression\fB ) \fR\(sq\fP \fIblock\fR
+.DE
+Inside the block
+two special types of labels are recognized.
+A prefix of the form
+.DS B
+\fBcase \fI\*([[ constant \*(]] \fB:\fR
+.DE
+marks the statement to which control is passed if the
+expression
+in the select has a value equal to one of the case constants.
+If the expression equals none of these constants, but there is
+a label
+.B default
+inside the select,
+a branch is taken to that point;
+otherwise the statement following the right brace is executed.
+Once execution begins at a
+.B case
+or
+.B default
+label, it continues until the next
+.B case
+or
+.B default
+is encountered.
+The
+.B else-if
+example above is better written as
+.DS B
+.B
+select(x)
+    {
+    case 1:
+        k = 1
+    case 3,5:
+        k = 2
+    default:
+        k = 3
+    }
+.R
+.DE
+Note that control does not `fall through' to the next case.
+.NH 2
+Loops
+.PP
+The loop forms provide the best way of repeating a statement
+or sequence of operations.
+The simplest (\fBwhile\fR) form is theoretically sufficient, but it is very convenient to have
+the more general loops available, since each expresses a mode of control
+that arises frequently in practice.
+.NH 3
+While Statement
+.PP
+This construct has the form
+.DS C
+\fBwhile ( \fIlogical-expression\fB ) \fR\(sq\fP \fIstatement\fR
+.DE
+The expression is evaluated; if it is true, the statement is executed, and then the test is performed again.
+If the expression is false, execution proceeds to the next statement.
+.NH 2
+For Statement
+.PP
+The
+.B for
+statement is a more elaborate looping construct.
+It has the form
+.DS C
+\fBfor ( \fIinitial-statement \fB, \fR\(sq\fP \fIlogical-expression \fB, \fR\(sq\fP \fI iteration-statement \fB) \fR\(sq\fP \fIbody-statement
+.DE
+Except for the behavior of the
+.B next
+statement (see Section 7.6.3), this construct is equivalent to
+.DS B
+\fIinitial-statement
+\fBwhile ( \fIlogical-expression\fB )
+    {
+    \fIbody-statement
+    \fIiteration-statement
+    }
+.DE
+This form is useful for general arithmetic iterations, and for various pointer-type operations.
+The sum of the integers from 1 to 100 can be computed by the fragment
+.DS B
+.B
+n = 0
+for(i = 1, i <= 100, i += 1)
+        n += i
+.R
+.DE
+Alternatively, the computation could be done by the single statement
+.DS B
+.B
+for(  { n = 0 ;  i = 1 } ,  i<=100 ,  { n += i ;  ++i } )
+        ;
+.R
+.DE
+Note that the body of the
+.B for
+loop is a null statement in this case.
+An example of following a linked list will be given later.
+.NH 3
+Repeat Statement
+.PP
+The statement
+.DS B
+\fBrepeat \fR\(sq\fP \fIstatement\fR
+.DE
+executes the statement, then does it again, without any termination test.
+Obviously, a test inside the
+.I statement
+is needed to stop the loop.
+.NH 3
+Repeat...Until Statement
+.PP
+The
+.B while
+loop performs a test before each iteration.
+The statement
+.DS B
+\fBrepeat \fR\(sq \fIstatement \fR\(sq \fBuntil ( \fIlogical-expression \fB)
+.DE
+executes the
+.I statement,
+then evaluates the logical;
+if the logical is
+true the loop is complete;
+otherwise control returns to the
+.I statement.
+Thus, the body is always executed at least once.
+The
+.B until
+refers to the nearest preceding
+.B repeat
+that has not been paired with an
+.B until.
+In practice, this appears to be the least frequently used looping construct.
+.NH 3
+Do Loops
+.PP
+The simple arithmetic progression is a very common one in numerical applications.
+EFL has a special loop form for ranging over an ascending arithmetic sequence
+.DS B
+\fBdo \fIvariable \fB= \fIexpression-1, expression-2, expression-3\fR
+     \fIstatement\fR
+.DE
+The variable is first given the value
+.I expression-1.
+The statement is executed, then
+.I expression-3
+is added to the variable.
+The loop is repeated until the variable exceeds
+.I expression-2.
+If
+.I expression-3
+and the preceding comma are omitted, the increment is taken to be 1.
+The loop above is equivalent to
+.DS B
+t2 = expression-2
+t3 = expression-3
+for(variable = expression-1 , variable <= t2 , variable += t3)
+     statement
+.DE
+(The compiler translates EFL
+.B do
+statements into Fortran
+DO statements,
+which are in turn usually compiled into excellent code.)
+The
+.B do
+.I variable
+may not be changed inside of the loop,
+and
+.I expression-1
+must not exceed
+.I expression-2.
+The sum of the first hundred positive integers could be computed by
+.DS B
+.B
+n = 0
+do i = 1, 100
+           n += i
+.R
+.DE
+.NH 2
+Branch Statements
+.PP
+Most of the need for branch statements in programs can be
+averted by using the loop and test constructs,
+but there are programs where they are very useful.
+.NH 3
+Goto Statement
+.PP
+The most general, and most dangerous, branching statement is the simple unconditional
+.DS B
+\fBgoto \fIlabel\fR
+.DE
+After executing this statement, the next statement performed is the one following the given label.
+Inside of a
+.B select
+the case labels of that block may be used as labels, as in the following example:
+.KS
+.B
+.TS
+center;
+lll .
+select(k)
+       {
+       case 1:
+               error(7)
+
+       case 2:
+               k = 2
+               goto case 4
+
+       case 3:
+               k = 5
+               goto case 4
+
+       case 4:
+               fixup(k)
+               goto default
+
+       default:
+               prmsg("ouch")
+       }
+.TE
+.KE
+.R
+(If two
+.B select
+statements are nested,
+the case labels of the outer
+.B select
+are not accessible from the inner one.)
+.NH 3
+Break Statement
+.PP
+A safer statement is one which transfers control to the statement following the current
+.B select
+or loop form.
+A statement of this sort is almost always needed in a
+.B repeat
+loop:
+.DS B
+.B
+repeat
+    {
+    \fIdo a computation
+    if\|( finished )
+          \fBbreak\fI
+    }
+.R
+.DE
+More general forms permit controlling a branch out of more than one construct.
+.DS C
+.B
+break 3
+.R
+.DE
+transfers control to the statement following the third loop and/or
+.B select
+surrounding the statement.
+It is possible to specify which type of construct
+(\fBfor\fR, \fBwhile\fR, \fBrepeat\fR, \fBdo\fR, or \fBselect\fR)
+is to be counted.
+The statement
+.DS C
+.B
+break while
+.R
+.DE
+breaks out of the first surrounding
+.B while
+statement.
+Either of the statements
+.DS B
+.B
+break 3 for
+break for 3
+.R
+.DE
+will transfer to the statement after the third enclosing
+.B for
+loop.
+.NH 3
+Next Statement
+.PP
+The
+.B next
+statement causes the first surrounding loop statement to go on to the next iteration:
+the next operation performed is the
+test of a
+.B while,
+the
+.I iteration-statement
+of a
+.B for,
+the body of a
+.B repeat,
+the test of a
+.B repeat...until,
+or the increment of a
+.B do.
+Elaborations similar to those for
+.B break
+are available:
+.DS B
+.B
+next
+next 3
+next 3 for
+next for 3
+.R
+.DE
+A
+.B next
+statement ignores
+.B select
+statements.
+.NH 3
+Return
+.PP
+The last statement of a procedure is followed by a return of control to the caller.
+If it is desired to effect such a return from any other point in the procedure, a
+.DS B
+\fBreturn\fR
+.DE
+statement may be executed.
+Inside a function procedure, the function value is specified as an argument of the statement:
+.DS B
+\fBreturn ( \fIexpression \fB)
+.DE
+.NH 2
+Input/Output Statements
+.PP
+EFL has two input statements (\fBread\fR and \fBreadbin\fR),
+two output statements (\fBwrite\fR and \fBwritebin\fR),
+and three control statements (\fBendfile\fR, \fBrewind\fR, and \fBbackspace\fR).
+These forms may be used either as a primary with a
+.B integer
+value
+or as a statement.
+If an exception occurs when one of these forms is used as a statement,
+the result is undefined but will probably be treated as a fatal error.
+If they are used in a context where they return a value,
+they return
+zero if no exception occurs.
+For the input forms, a negative value indicates end-of-file and
+a positive value an error.
+The input/output part of EFL very strongly reflects the facilities of Fortran.
+.NH 3
+Input/Output Units
+.PP
+Each I/O statement refers to a `unit',
+identified by a small positive integer.
+Two special units are defined by EFL,
+the
+.I "standard input unit"
+and the
+.I "standard output unit."
+These particular units are assumed if no unit is specified in an I/O transmission statement.
+.PP
+The data on the unit are organized into
+.I records.
+These records may be read or written in a fixed sequence,
+and each transmission moves an integral number of records.
+Transmission proceeds from the first record until the
+.I "end of file."
+.NH 3
+Binary Input/Output
+.PP
+The
+.B readbin
+and
+.B writebin
+statements transmit data in a machine-dependent but swift manner.
+The statements are of the form
+.DS B
+\fBwritebin( \fIunit \fB, \fIbinary-output-list \fB)\fR
+\fBreadbin( \fIunit \fB, \fIbinary-input-list \fB)\fR
+.DE
+Each statement moves one unformatted record between storage and the device.
+The
+.I unit
+is an integer expression.
+A
+.I binary-output-list
+is an
+.I iolist
+(see below) without any format specifiers.
+A
+.I binary-input-list
+is an
+.I iolist
+without format specifiers in which each of the expressions
+is a variable name, array element, or structure member.
+.NH 3
+Formatted Input/Output
+.PP
+The
+.B read
+and
+.B write
+statements
+transmit data in the form of lines of characters.
+Each statement moves one or more records (lines).
+Numbers are translated into decimal notation.
+The exact form of the lines is determined by format specifications,
+whether provided explicitly in the statement
+or implicitly.
+The syntax of the statements is
+.DS B
+\fBwrite( \fIunit \fB,\fI formatted-output-list \fB)\fR
+\fBread( \fIunit \fB,\fI formatted-input-list \fB)\fR
+.DE
+The lists are of the same form as for binary I/O,
+except that the lists may include format specifications.
+If the
+.I unit
+is omitted, the standard input or output unit is used.
+.NH 3
+Iolists
+.PP
+An
+.I iolist
+specifies a set of values to be written or a set of variables into which
+values are to be read.
+An
+.I iolist
+is a list of one or more
+.I ioexpressions
+of the form
+.DS B
+\fIexpression
+\fB{ \fIiolist \fB}
+\fIdo-specification \fB{ \fIiolist \fB}\fR
+.DE
+For formatted I/O,
+an
+.I ioexpression
+may also have the forms
+.DS B
+\fIioexpression \fB:\fI format-specifier
+\fB:\fI format-specifier\fR
+.DE
+A
+.I do-specification
+looks just like a
+.B do
+statement, and has a similar effect:
+the values in the braces are transmitted repeatedly until the
+.B do
+execution is complete.
+.NH 3
+Formats
+.PP
+The following are permissible
+.I format-specifiers.
+The quantities
+@w@, @d@, and @k@ must be integer constant expressions.
+.KS
+.TS
+center;
+ll .
+\fBi(\fIw\fB)\fR       integer with \fIw\fR digits
+\fBf(\fIw\fB,\fId\fB)\fR       floating point number of \fIw\fR characters,
+       \fId\fR of them to the right of the decimal point.
+\fBe(\fIw\fB,\fId\fB)\fR       floating point number of \fIw\fR characters,
+       \fId\fR of them to the right of the decimal point,
+       with the exponent field marked with the letter \fBe\fR
+\fBl(\fIw\fB)\fR       logical field of width \fIw\fR characters,
+       the first of which is \fBt\fR or \fBf\fR
+       (the rest are blank on output, ignored on input)
+       standing for \fBtrue\fR and \fBfalse\fR respectively
+\fBc\fR        character string of width equal to the length of the datum
+\fBc(\fIw\fB)\fR       character string of width \fIw\fR
+\fBs(\fIk\fB)\fR       skip \fIk\fR lines
+\fBx(\fIk\fB)\fR       skip \fIk\fR spaces
+" ... "        use the characters inside the string as a Fortran format
+.TE
+.KE
+If no format is specified for an item in a formatted input/output statement,
+a default form is chosen.
+.PP
+If an item in a list is an array name,
+then the entire array is transmitted as a sequence of elements,
+each with its own format.
+The elements are transmitted in column-major order,
+the same order used for array initializations.
+.NH 3
+Manipulation statements
+.PP
+The three input/output statements
+.DS B
+.B
+backspace(@unit@)
+rewind(@unit@)
+endfile(@unit@)
+.R
+.DE
+look like ordinary procedure calls,
+but may be used either as statements or as integer expressions
+which yield
+non-zero
+if an error is detected.
+.B backspace
+causes the specified unit to back up,
+so that the next
+read will re-read the previous record,
+and the next write will over-write it.
+.B rewind
+moves the device to its beginning,
+so that the next input statement will read the first record.
+.B endfile
+causes the file to be marked so that the record most recently written will be the last record on the file,
+and any attempt to read past is an error.
+.NH 1
+PROCEDURES
+.PP
+Procedures are the basic unit of an EFL program,
+and provide the means of segmenting a program into separately compilable
+and named parts.
+.NH 2
+Procedure Statement
+.PP
+Each procedure begins with a statement of one of the forms
+.DS B
+\fBprocedure
+\fIattributes \fBprocedure \fIprocedurename
+\fIattributes \fBprocedure \fIprocedurename \fB( )\fR
+\fIattributes \fBprocedure \fIprocedurename \fB( \fI\*([[ name \*(]] \fB) \fR
+.DE
+The first case specifies the main procedure, where execution begins.
+In the two other cases, the
+.I attributes
+may specify precision and type,
+or they may be omitted entirely.
+The precision and type of the procedure may be declared in an ordinary declaration statement.
+If no type is declared, then the procedure is called a
+.I subroutine
+and no value may be returned for it.
+Otherwise, the procedure is a function and a value of the declared type is returned for each call.
+Each
+.I name
+inside the parentheses in the last form above is called a
+.I "formal argument"
+of the procedure.
+.NH 2
+End Statement
+.PP
+Each procedure terminates with a statement
+.DS C
+.B
+end
+.R
+.DE
+.NH 2
+Argument Association
+.PP
+When a procedure is invoked,
+the actual arguments are evaluated.
+If an actual argument is the name of a variable, an array element,
+or a structure member,
+that entity becomes associated with the formal argument,
+and the procedure may reference the values in the object,
+and assign to it.
+Otherwise,
+the value of the actual is associated with the formal argument,
+but the procedure may not attempt to change the value of that formal argument.
+.PP
+If the value of one of the arguments is changed in the procedure,
+it is not permitted that the corresponding actual argument be associated
+with another formal argument or with a
+.B common
+element that is referenced in the procedure.
+.NH 2
+Execution and Return Values
+.PP
+After actual and formal arguments have been associated,
+control passes to the first executable statement of the procedure.
+Control returns to the invoker
+either when the
+.B end
+statement of the procedure is reached or when a
+.B return
+statement is executed.
+If the procedure is a function
+(has a declared type),
+and a
+@bold return( value )@
+is executed, the value
+is coerced to the correct type and precision and returned.
+.NH 2
+Known Functions
+.PP
+A number of functions are known to EFL, and need not be declared.
+The compiler knows the types of these functions.
+Some of them are
+.I generic;
+i.e., they name a family of functions that differ in the types of their arguments and return values.
+The compiler chooses which element of the set to invoke based upon the attributes of the actual arguments.
+.NH 3
+Minimum and Maximum Functions
+.PP
+The generic functions are
+.B min
+and
+.B max.
+The
+.B min
+calls return the value of their smallest argument;
+the
+.B max
+calls return the value of their largest argument.
+These are the only functions that may take different numbers of arguments in different calls.
+If any of the arguments are
+.B "long real"
+then the result is
+.B "long real".
+Otherwise, if any of the arguments are
+.B real
+then the result is
+.B real;
+otherwise all the arguments and the result must be
+.B integer.
+Examples are
+.DS B
+.B
+min(5, x, \-3.20)
+max(i, z)
+.R
+.DE
+.NH 3
+Absolute Value
+.PP
+The
+.B abs
+function is a generic function that returns the magnitude of its argument.
+For
+integer and real arguments the type of the result is identical to the type of the argument;
+for complex arguments the type of the result is the real of the same precision.
+.NH 3
+Elementary Functions
+.PP
+The following generic functions take arguments of
+\fBreal\fR, \fBlong real\fR, or \fBcomplex\fR
+type and return a result of the same type:
+.DS
+.TS
+center;
+ll.
+.B
+sin    sine function
+cos    cosine function
+exp    exponential function (@e sup x@).
+log    natural (base \fIe\fP) logarithm
+log10  common (base 10) logarithm
+sqrt   square root function (@sqrt x@).
+.R
+.TE
+.DE
+In addition, the following functions accept only
+.B real
+or
+.B "long real"
+arguments:
+.DS
+.TS
+center;
+ll .
+\fBatan\fR     @atan(x) = tan sup -1 x@
+\fBatan2\fR    @atan2(x,y) = tan sup -1 x over y@
+.TE
+.DE
+.NH 3
+Other Generic Functions
+.PP
+The
+.B sign
+functions takes two arguments of identical type;
+@bold sign (x,y) ~=~ sgn(y) |x|@.
+The
+.B mod
+function yields the remainder of its first argument when divided by its second.
+These functions accept integer and real arguments.
+.NH 1
+ATAVISMS
+.PP
+Certain facilities are included in the EFL language to ease the conversion of old
+Fortran or Ratfor programs to EFL.
+.NH 2
+Escape Lines
+.PP
+In order to make use of nonstandard features of the local Fortran compiler,
+it is occasionally necessary to pass a particular line through to the EFL compiler output.
+A line that begins with a percent sign (`\fB%\fR')
+is copied through to the output, with the percent sign removed but no other change.
+Inside of a procedure, each escape line is treated as an executable statement.
+If a sequence of lines constitute a continued Fortran statement, they should be enclosed in braces.
+.NH 2
+Call Statement
+.PP
+A subroutine call may be preceded by the keyword
+.B call.
+.DS B
+.B
+call joe
+call work(17)
+.R
+.DE
+.NH 2
+Obsolete Keywords
+.PP
+The following keywords are recognized as synonyms of EFL keywords:
+.TS
+center;
+cc
+ll.
+Fortran        EFL
+.sp .3
+\fBdouble precision    long real
+\fBfunction    procedure
+\fBsubroutine  procedure \fI(untyped)\fR
+.TE
+.NH 2
+Numeric Labels
+.PP
+Standard statement labels are identifiers.
+A numeric (positive integer constant) label is also permitted;
+the colon is optional following a numeric label.
+.NH 2
+Implicit Declarations
+.PP
+If a name is used but does not appear in a declaration,
+the EFL compiler gives a warning and assumes a declaration for it.
+If it is used in the context of a procedure invocation, it is assumed to be a procedure name;
+otherwise it is assumed to be a local variable defined at nesting level 1 in the current procedure.
+The assumed type is determined by the first letter of the name.
+The association of letters and types may be given in an
+.B implicit
+statement, with syntax
+.DS C
+\fBimplicit ( \fIletter-list\fB ) \fI type \fR
+.DE
+where a
+.I letter-list
+is a list of individual letters or ranges (pair of letters separated by a minus sign).
+If no
+.B implicit
+statement appears, the following rules are assumed:
+.DS B
+.B
+implicit (a\-h, o\-z) real
+implicit (i\-n) integer
+.R
+.DE
+.NH 2
+Computed \fBgoto\fR
+.PP
+Fortran contains an indexed multi-way branch; this facility may be used in EFL
+by the computed GOTO:
+.DS C
+\fBgoto ( \fI\*([[ label \*(]] \fB), \fIexpression\fR
+.DE
+The expression must be of type integer and be positive but be no larger than the number of labels in the list.
+Control is passed to the statement marked by the label whose position in the list is equal to the expression.
+.NH 2
+Go To Statement
+.PP
+In unconditional and computed \fBgoto\fR
+statements, it is permissible to separate the \fBgo\fR and \fBto\fR words, as in
+.DS B
+.B
+go to xyz
+.R
+.DE
+.NH 2
+Dot Names
+.PP
+Fortran uses a restricted character set,
+and represents certain operators by multi-character sequences.
+There is an option (\fBdots=on\fR; see Section 10.2) which forces the compiler to recognize the forms
+in the second column below:
+.DS
+.B
+.TS
+center;
+ll.
+<      .lt.
+<=     .le.
+>      .gt.
+>=     .ge.
+==     .eq.
+\*~=   .ne.
+&      .and.
+|      .or.
+&&     .andand.
+|\||   .oror.
+\*~    .not.
+true   .true.
+false  .false.
+.TE
+.R
+.DE
+In this mode, no structure element may be named
+.B lt,
+.B le,
+etc.
+The readable forms in the left column are always recognized.
+.NH 2
+Complex Constants
+.PP
+A complex constant may be written as a parenthesized list of real quantities, such as
+.DS C
+.B
+(1.5, 3.0)
+.R
+.DE
+The preferred notation is by a type coercion,
+.DS C
+.B
+complex(1.5, 3.0)
+.R
+.DE
+.NH 2
+Function Values
+.PP
+The preferred way to return a value from a function in EFL is the
+@bold return ( value )@
+construct.
+However, the name of the function acts as a variable to which values may be assigned;
+an ordinary
+@bold return@
+statement returns the last value assigned to that name as the function value.
+.NH 2
+Equivalence
+.PP
+A statement of the form
+.EQ C
+bold equivalence ~ v sub 1 ,~  v sub 2 ,~ ...,~ v sub n
+.EN
+declares that each of the @v sub i@ starts at the same memory location.
+Each of the @v sub i@ may be a variable name, array element name, or structure member.
+.NH 2
+Minimum and Maximum Functions
+.PP
+There are a number of non-generic functions in this category,
+which differ in the required types of the arguments and the type of the return value.
+They may also have variable numbers of arguments, but all the arguments must have the same type.
+.DS
+.TS
+center;
+ccc
+lll .
+Function       Argument Type   Result Type
+_
+.B
+amin0  integer real
+amin1  real    real
+min0   integer integer
+min1   real    integer
+dmin1  long real       long real
+
+amax0  integer real
+amax1  real    real
+max0   integer integer
+max1   real    integer
+dmax1  long real       long real
+.R
+.TE
+.DE
+.NH 1
+COMPILER OPTIONS
+.PP
+A number of options can be used to control the output
+and to tailor it for various compilers and systems.
+The defaults chosen are conservative, but it is sometimes necessary to change the output to match peculiarities of the
+target environment.
+.PP
+Options are set with statements of the form
+.DS C
+\fBoption \fI\*([[ \fIopt \fI\*(]]\fR
+.DE
+where each
+.I opt
+is of one of the forms
+.DS B
+.I
+optionname
+optionname \fB= \fIoptionvalue
+.R
+.DE
+The
+.I optionvalue
+is either a constant (numeric or string) or
+a name associated with that option.
+The two names
+.B yes
+and
+.B no
+apply to a number of options.
+.NH 2
+Default Options
+.PP
+Each option has a default setting.
+It is possible to change the whole set of defaults to those appropriate
+for a particular environment
+by using the
+.B system
+option.
+At present, the only valid values are
+.B system=unix
+and
+.B system=gcos.
+.NH 2
+Input Language Options
+.PP
+The
+.B dots
+option determines whether the compiler recognizes
+.B .lt.
+and similar forms.  The default setting is
+.B no.
+.NH 2
+Input/Output Error Handling
+.PP
+The
+.B ioerror
+option can be given three values:
+.B none
+means that none of the I/O statements may be used in expressions, since there is no way to detect errors.
+The implementation of the
+.B ibm
+form uses ERR= and END= clauses.
+The implementation of the
+.B fortran77
+form uses IOSTAT= clauses.
+.NH 2
+Continuation Conventions
+.PP
+By default, continued Fortran statements are indicated by a character in column 6 (Standard Fortran).
+The option
+.B "continue=column1"
+puts an ampersand (\fB&\fR) in the first column of the continued lines instead.
+.NH 2
+Default Formats
+.PP
+If no format is specified for a datum in an
+iolist
+for a
+.B read
+or
+.B write
+statement, a default is provided.
+The default formats can be changed by setting certain options
+.DS
+.TS
+center;
+cc
+ll.
+Option Type
+_
+\fBiformat\fR  integer
+\fBrformat\fR  real
+\fBdformat\fR  long real
+\fBzformat\fR  complex
+\fBzdformat\fR long complex
+\fBlformat\fR  logical
+.TE
+.DE
+The associated value must be a Fortran format, such as
+.DS C
+.B
+option rformat=f22.6
+.R
+.DE
+.NH 2
+Alignments and Sizes
+.PP
+In order to implement
+.B character
+variables, structures, and the
+.B sizeof
+and
+.B lengthof
+operators, it is necessary to know how much space various Fortran data types require,
+and what boundary alignment properties they demand.
+The relevant options are
+.DS
+.B
+.TS
+center;
+ccc
+lll.
+Fortran Type   Size Option     Alignment Option
+_
+integer        isize   ialign
+real   rsize   ralign
+long real      dsize   dalign
+complex        zsize   zalign
+logical        lsize   lalign
+.R
+.TE
+.DE
+The sizes are given in terms of an arbitrary unit;
+the alignment is given in the same units.
+The option
+.B charperint
+gives the number of characters per
+.B integer
+variable.
+.NH 2
+Default Input/Output Units
+.PP
+The options
+.B ftnin
+and
+.B ftnout
+are the numbers of the standard input and output units.
+The default values are
+.B ftnin=5
+and
+.B ftnout=6.
+.NH 2
+Miscellaneous Output Control Options
+.PP
+Each Fortran procedure generated by the compiler will be preceded by the value of the
+.B procheader
+option.
+.PP
+No Hollerith strings will be passed as subroutine arguments if
+.B hollincall=no
+is specified.
+.PP
+The Fortran statement numbers normally start at 1 and increase by 1.
+It is possible to change the increment value by using the
+.B deltastno
+option.
+.ta .5i 1i 1.5i 2i 2.5i 3.0i
+.NH 1
+EXAMPLES
+.PP
+In order to show the flavor or programming in EFL,
+we present a few examples.
+They are short, but show some of the convenience of the language.
+.NH 2
+File Copying
+.PP
+The following short program copies the standard input to the standard output,
+provided that the input is a formatted file containing
+lines no longer than a hundred characters.
+.DS 
+.B
+procedure   # main program
+character(100) line
+
+while( read( , line) == 0 )
+       write( , line)
+end
+.R
+.DE
+Since
+.B read
+returns
+zero
+until the end of file (or a read error),
+this program keeps reading and writing until the input is exhausted.
+.NH 2
+Matrix Multiplication
+.PP
+The following procedure multiplies the
+@m times n@ matrix a
+by the
+@n times p@ matrix b
+to give the @m times p@ matrix c.
+The calculation obeys the formula
+@c sub ij ~=~ sum a sub ik b sub kj@.
+.DS 
+.ta .7i 1.4i 2.1i 2.8i
+.B
+procedure matmul(a,b,c, m,n,p)
+integer i, j, k, m, n, p
+long real a(m,n), b(n,p), c(m,p)
+.sp .3
+do i = 1,m
+do j = 1,p
+       {
+       c(i,j) = 0
+       do k = 1,n
+               c(i,j) += a(i,k) \(** b(k,j)
+       }
+end
+.R
+.DE
+.NH 2
+Searching a Linked List
+.PP
+Assume we have a list of pairs of numbers @(x,y)@.
+The list is stored as a linked list sorted in ascending order of @x@ values.
+The following procedure searches this list for a particular value of @x@
+and returns the corresponding @y@ value.
+.DS 
+.B
+.ta .7i 1.4i 2.1i 2.8i
+define LAST    0
+define NOTFOUND        \-1
+
+integer procedure val(list, first, x)
+
+#   list is an array of structures.
+#   Each structure contains a thread index value, an x, and a y value.
+.sp .3
+struct
+       {
+       integer nextindex
+       integer x, y
+       } list(\(**)
+.sp .3
+integer first, p, arg
+
+for(p = first , p\*~=LAST && list(p).x<=x , p = list(p).nextindex)
+       if(list(p).x == x)
+               return( list(p).y )
+
+return(NOTFOUND)
+end
+.R
+.DE
+The search is a single
+.B for
+loop that begins with the head of the list
+and examines items until either the list is exhausted
+(p==LAST)
+or until it is known that the specified value is not on the list
+(list(p).x > x).
+The two tests in the conjunction must
+be performed in the specified order
+to avoid using an invalid subscript in the
+.B list(p)
+reference.
+Therefore, the
+.B &&
+operator is used.
+The next element in the chain is found by the iteration statement
+.B "p=list(p).nextindex".
+.NH 2
+Walking a Tree
+.PP
+As an example of a more complicated problem, let us imagine we have
+an expression tree stored in a common area,
+and that we want to print out an infix form of the tree.
+Each node is either a leaf (containing a numeric value)
+or it is a binary operator, pointing to a left and a right descendant.
+In a recursive language,
+such a tree walk would be implement by the following simple pseudocode:
+.DS 
+.I
+if this node is a leaf
+       print its value
+otherwise
+       print a left parenthesis
+       print the left node
+       print the operator
+       print the right node
+       print a right parenthesis
+.R
+.DE
+In a nonrecursive language like EFL, it is necessary to maintain an explicit stack
+to keep track of the current state of the computation.
+The following procedure
+calls a procedure
+.B outch
+to print a single character
+and a procedure
+.B outval
+to print a value.
+.DS 
+.ta .7i 1.4i 2.1i 2.8i
+.B
+procedure walk(first)  # print out an expression tree
+.sp .5
+integer first          # index of root node
+integer currentnode
+integer stackdepth
+common(nodes) struct
+       {
+       character(1) op
+       integer leftp, rightp
+       real val
+       } tree(100)     # array of structures
+.sp .5
+struct
+       {
+       integer nextstate
+       integer nodep
+       } stackframe(100)
+.sp .5
+define NODE    tree(currentnode)
+define STACK   stackframe(stackdepth)
+.sp .5
+#   nextstate values
+define DOWN    1
+define LEFT    2
+define RIGHT   3
+.DE
+.DS
+.B
+#   initialize stack with root node
+stackdepth = 1
+STACK.nextstate = DOWN
+STACK.nodep = first
+.DE
+.DS
+.B
+while( stackdepth > 0 )
+       {
+       currentnode = STACK.nodep
+       select(STACK.nextstate)
+               {
+               case DOWN:
+                       if(NODE.op == " ")   # a leaf
+                               {
+                               outval( NODE.val )
+                               stackdepth \-= 1
+                               }
+                       else    {   # a binary operator node
+                               outch( "(" )
+                               STACK.nextstate = LEFT
+                               stackdepth += 1
+                               STACK.nextstate = DOWN
+                               STACK.nodep = NODE.leftp
+                               }
+.sp .5
+               case LEFT:
+                       outch( NODE.op )
+                       STACK.nextstate = RIGHT
+                       stackdepth += 1
+                       STACK.nextstate = DOWN
+                       STACK.nodep = NODE.rightp
+.sp .5
+               case RIGHT:
+                       outch( ")" )
+                       stackdepth \-= 1
+               }
+       }
+end
+.DE
+.NH 1
+PORTABILITY
+.PP
+One of the major goals of the EFL language is to make it easy to write portable programs.
+The output of the EFL compiler is intended to be acceptable to any Standard Fortran
+compiler
+(unless the
+.B fortran77
+option is specified).
+.NH 2
+Primitives
+.PP
+Certain EFL operations cannot be implemented in portable Fortran,
+so a few machine-dependent procedures must be provided in each environment.
+.NH 3
+Character String Copying
+.PP
+The subroutine
+.B ef1asc
+is called to copy one character string to another.
+If the target string is shorter than the source,
+the final characters are not copied.
+If the target string is longer, its end is padded with blanks.
+The calling sequence is
+.DS B
+subroutine ef1asc(a, la, b, lb)
+integer a(\(**), la, b(\(**), lb
+.DE
+and it must copy the first
+.B lb
+characters from
+.B b
+to the first
+.B la
+characters of
+.B a.
+.NH 3
+Character String Comparisons
+.PP
+The function
+.B ef1cmc
+is invoked to determine the order of two character strings.
+The declaration is
+.DS B
+integer function ef1cmc(a, la, b, lb)
+integer a(\(**), la, b(\(**), lb
+.DE
+The function returns a negative value if the string
+.B a
+of length
+.B la
+precedes the string
+.B b
+of length
+.B lb.
+It returns zero if the strings are equal, and a positive value otherwise.
+If the strings are of differing length, the comparison is carried out
+as if the end of the shorter string were padded with blanks.
+.NH 1
+ACKNOWLEDGMENTS
+.PP
+A. D. Hall originated the EFL language and wrote the first compiler for it;
+he also gave inestimable aid when I took up the project.
+B. W. Kernighan and W. S. Brown made a number of useful suggestions about the language and about this report.
+N. L. Schryer has acted as willing, cheerful, and severe first user
+and helpful critic of each new version and facility.
+J. L. Blue, L. C. Kaufman, and D. D. Warner
+made very useful contributions by making serious use of the compiler,
+and noting and tolerating its misbehaviors.
+.NH 1
+REFERENCE
+.IP 1.
+B. W. Kernighan,
+``Ratfor \(em A Preprocessor for a Rational Fortran'',
+Bell Laboratories Computing Science Technical Report #55
+.bp
+.SH
+APPENDIX A.  Relation Between EFL and Ratfor
+.PP
+There are a number of differences between Ratfor and EFL,
+since EFL is a defined language while Ratfor is
+the union of the special control structures and the language accepted by the underlying Fortran compiler.
+Ratfor running over Standard Fortran is almost a subset of EFL.
+Most of the features described in the Atavisms section are present to ease
+the conversion of Ratfor programs to EFL.
+.PP
+There are a few incompatibilities:
+The syntax of the
+.B for
+statement is slightly different in the two languages:
+the three clauses are separated by semicolons in Ratfor,
+but by commas in EFL.
+(The initial and iteration statements may be compound statements in EFL because of this change).
+The input/output syntax is quite different in the two languages,
+and there is no FORMAT statement in EFL.
+There are no ASSIGN or assigned GOTO statements in EFL.
+.PP
+The major linguistic additions are
+character data,
+factored declaration syntax,
+block structure,
+assignment and sequential test operators,
+generic functions,
+and
+data structures.
+EFL permits more general forms for expressions,
+and provides a more uniform syntax.
+(One need not worry about the Fortran/Ratfor restrictions
+on subscript or DO expression forms, for example.)
+.SH
+APPENDIX B.  COMPILER
+.SH
+B.1.  Current Version
+.PP
+The current version of the EFL compiler is a two-pass translator written in
+portable C.
+It implements all of the features of the language described above except for
+.B "long complex"
+numbers.
+Versions of this compiler run under the
+.SM GCOS
+and
+.UX
+operating systems.
+.SH
+B.2.  Diagnostics
+.PP
+The EFL compiler diagnoses all syntax errors.
+It gives the line and file name (if known) on which the error was detected.
+Warnings are given for variables that are used but not explicitly declared.
+.SH
+B.3.  Quality of Fortran Produced
+.PP
+The Fortran produced by EFL is quite clean and readable.
+To the extent possible, the variable names that appear in the EFL program are used in the Fortran code.
+The bodies of loops and test constructs are indented.
+Statement numbers are consecutive.
+Few unneeded GOTO and CONTINUE statements are used.
+It is considered a compiler bug if incorrect Fortran is produced
+(except for escaped lines).
+The following is the Fortran procedure produced by the EFL compiler for
+the matrix multiplication example (Section 11.2):
+.DS B
+.B
+\0\0\0\0\0\0subroutine\0matmul(a,\0b,\0c,\0m,\0n,\0p)
+\0\0\0\0\0\0integer\0m,\0n,\0p
+\0\0\0\0\0\0double\0precision\0a(m,\0n),\0b(n,\0p),\0c(m,\0p)
+\0\0\0\0\0\0integer\0i,\0j,\0k
+\0\0\0\0\0\0do\0\03\0i\0=\01,\0m
+\0\0\0\0\0\0\0\0\0do\0\02\0j\0=\01,\0p
+\0\0\0\0\0\0\0\0\0\0\0\0c(i,\0j)\0=\00
+\0\0\0\0\0\0\0\0\0\0\0\0do\0\01\0k\0=\01,\0n
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0c(i,\0j)\0=\0c(i,\0j)+a(i,\0k)*b(k,\0j)
+\0\0\01\0\0\0\0\0\0\0\0\0\0\0continue
+\0\0\02\0\0\0\0\0\0\0\0continue
+\0\0\03\0\0\0\0\0continue
+\0\0\0\0\0\0end
+.R
+.DE
+The following is the procedure for the tree walk (Section 11.4):
+.DS B
+.B
+\0\0\0\0\0\0subroutine\0walk(first)
+\0\0\0\0\0\0integer\0first
+\0\0\0\0\0\0common\0/nodes/\0tree
+\0\0\0\0\0\0integer\0tree(4,\0100)
+\0\0\0\0\0\0real\0tree1(4,\0100)
+\0\0\0\0\0\0integer\0staame(2,\0100),\0stapth,\0curode
+\0\0\0\0\0\0integer\0const1(1)
+\0\0\0\0\0\0equivalence\0(tree(1,1),\0tree1(1,1))
+\0\0\0\0\0\0data\0const1(1)/4h\0\0\0\0/
+c\0print\0out\0an\0expression\0tree
+c\0index\0of\0root\0node
+c\0array\0of\0structures
+c\0\0\0nextstate\0values
+c\0\0\0initialize\0stack\0with\0root\0node
+\0\0\0\0\0\0stapth\0=\01
+\0\0\0\0\0\0staame(1,\0stapth)\0=\01
+\0\0\0\0\0\0staame(2,\0stapth)\0=\0first
+\0\0\01\0\0if\0(stapth\0.le.\00)\0goto\0\09
+\0\0\0\0\0\0\0\0\0curode\0=\0staame(2,\0stapth)
+\0\0\0\0\0\0\0\0\0goto\0\07
+\0\0\02\0\0\0\0\0\0\0\0if\0(tree(1,\0curode)\0.ne.\0const1(1))\0goto\03
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0call\0outval(tree1(4,\0curode))
+c\0a\0leaf
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0stapth\0=\0stapth-1
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0goto\0\04
+\0\0\03\0\0\0\0\0\0\0\0\0\0\0call\0outch(1h()
+c\0a\0binary\0operator\0node
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staame(1,\0stapth)\0=\02
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0stapth\0=\0stapth+1
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staame(1,\0stapth)\0=\01
+\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0staame(2,\0stapth)\0=\0tree(2,\0curode)
+\0\0\04\0\0\0\0\0\0\0\0goto\0\08
+\0\0\05\0\0\0\0\0\0\0\0call\0outch(tree(1,\0curode))
+\0\0\0\0\0\0\0\0\0\0\0\0staame(1,\0stapth)\0=\03
+\0\0\0\0\0\0\0\0\0\0\0\0stapth\0=\0stapth+1
+\0\0\0\0\0\0\0\0\0\0\0\0staame(1,\0stapth)\0=\01
+\0\0\0\0\0\0\0\0\0\0\0\0staame(2,\0stapth)\0=\0tree(3,\0curode)
+\0\0\0\0\0\0\0\0\0\0\0\0goto\0\08
+\0\0\06\0\0\0\0\0\0\0\0call\0outch(1h))
+\0\0\0\0\0\0\0\0\0\0\0\0stapth\0=\0stapth-1
+\0\0\0\0\0\0\0\0\0\0\0\0goto\0\08
+\0\0\07\0\0\0\0\0\0\0\0if\0(staame(1,\0stapth)\0.eq.\03)\0goto\0\06
+\0\0\0\0\0\0\0\0\0\0\0\0if\0(staame(1,\0stapth)\0.eq.\02)\0goto\0\05
+\0\0\0\0\0\0\0\0\0\0\0\0if\0(staame(1,\0stapth)\0.eq.\01)\0goto\0\02
+\0\0\08\0\0\0\0\0continue
+\0\0\0\0\0\0\0\0\0goto\0\01
+\0\0\09\0\0continue
+\0\0\0\0\0\0end
+.R
+.DE
+.SH
+APPENDIX C.  CONSTRAINTS ON THE DESIGN OF THE EFL LANGUAGE
+.PP
+Although Fortran can be used to simulate any finite computation,
+there are realistic limits on the generality of a language that can be
+translated into Fortran.
+The design of EFL was constrained by the implementation strategy.
+Certain of the restrictions are petty (six character external names),
+but others are sweeping (lack of pointer variables).
+The following paragraphs describe the major limitations imposed by Fortran.
+.SH
+C.1.  External Names
+.PP
+External names (procedure and COMMON block names)
+must be no longer than six characters in Fortran.
+Further, an external name is global to the entire program.
+Therefore, EFL can support block structure within a procedure,
+but it can have only one level of external name if the
+EFL procedures are to be compilable separately,
+as are Fortran procedures.
+.SH
+C.2.  Procedure Interface
+.PP
+The Fortran standards, in effect, permit arguments to be passed between
+Fortran procedures either by reference or by copy-in/copy-out.
+This indeterminacy of specification shows through into EFL.
+A program that depends on the method of argument transmission is
+illegal in either language.
+.PP
+There are no procedure-valued variables in Fortran: a procedure name may
+only be passed as an argument or be invoked; it cannot be stored.
+Fortran (and EFL) would be noticeably simpler if a procedure variable mechanism
+were available.
+.SH
+C.3.  Pointers
+.PP
+The most grievous problem with Fortran is its lack of a pointer-like
+data type.
+The implementation of the compiler would have been far easier if certain hard
+cases could have been handled by pointers.
+Further, the language could have been simplified considerably if pointers were
+accessible in Fortran.
+(There are several ways of simulating pointers by using subscripts,
+but they founder on the problems of external variables and initialization.)
+.SH
+C.4.  Recursion
+.PP
+Fortran procedures are not recursive,
+so it was not practical to permit EFL procedures to be recursive.
+(Recursive procedures with arguments can be simulated only with great pain.)
+.SH
+C.5.  Storage Allocation
+.PP
+The definition of Fortran does not specify the lifetime of variables.
+It would be possible but cumbersome to implement stack or heap
+storage disciplines by using COMMON blocks.