FORTRAN,
BASIC, and COBOL STOP Statements
Assembly
Language nop Instruction
Parentheses
around Comparisons
Copyright Dennie Van Tassel 2004.
Please send suggestions and comments to dvantassel@gavilan.edu
There are two ends to a program: the physical end and logical end. The physical end is the last statement in the program. The logical end is where the program stops execution. In C language family the final brace } is used to end the program. For example in C++ we have:
main() {
. . .
} // physical end of the program.
One
problem (or advantage) with this approach is that all kinds of blocks and compound
statements use the same symbol for ending. Other languages use a particular
statement (e.g. END) for ending the program that is used in no
other place. In these languages we know when we see an END statement, we at ending the
program and not just ending a compound statement or
block.
Other
languages have several ways to terminate program execution. For example, PL/I has four ways: end, stop,
exit, and return. The end statement is the last line
of the program or function. The stop or return statements are used for
normal termination and exit is used
for abnormal termination. Return statements are covered a little in this chapter
but are covered more in the Function chapter.
Most
early FORTRAN or BASIC programs would have an ending similar to this:
10 STOP
END
The
END statement is the last line
in the main program and in all subroutines or functions. Since an END statement is a non-executable
statement, the program cannot branch to an END statement. (This problem is discussed in detail in the “Placement of Labels within the Program”
section of the Labels chapter.) The STOP statement is the logical end of the
main program. And the statement number 10 on the STOP statement can be branched to as needed.
ALGOL
used the same stop and end statements as used in
FORTRAN. But ALGOL has blocks and uses begin and end for the block structure. So
the begin and end statements of ALGOL are
equivalent to open and closing brace in the C family of
languages. Thus the ALGOL end is used to indicate the end
of compound statements and the end of the program like the C family does with
closing braces.
Pascal
uses the end statement to indicate the end of compound statements and the program.
But the final end statement in Pascal must be followed by a period. So “end” is the end of a
compound statement or block, but “end.” (end period) is end of the program. Thus Pascal has a special command to end the
program.
COBOL
does not have an end statement. The last statement is the last statement and
that is all there is to it. When looking at other languages this seems a little
odd but it has worked fine with millions of COBOL programs.
Ruby
programmers use “__END__” (two underscores before and after END) with no leading or trailing white space, to end
their programs and any statements that follow will not be compiled. Ruby and
Awk have END blocks that are executed at
the close of the programs and these are discussed in the Block chapter.
So
some languages with a specific statement for the physical end of the program
are BASIC, FORTRAN, and Pascal. And I guess I have reached the end of this topic.
Some
languages use the end statement and the name of function,
program, or procedure to end the program. For example,
procedure swap(a, b: in out elem) is
temp: elem;
begin
temp := a;
a := b;
b := temp;
end swap;
So
the name of the procedure is swap and that is used to label the end statement.
FORTRAN
has programs, subroutines, and functions. In FORTRAN 90 each unit has their own
closing end statement, and the unit name can be optionally attached. For example,
we could have the following end statements:
end program main
! the program name is main
end function swap ! the function name is swap
end subroutine heading
! the subroutine name is heading
These
unit names are optional, but if there it must be
identical to the name specified in the program, function, or subroutine statement. In FORTRAN, functions
return a single value via the name of the function, whereas subroutines return
values by the argument list. Visual Basic makes a similar use of end statements, indicating the
unit being ended.
PL/I
uses similar label end statements. Here is the
swap program in PL/I:
swap:
procedure(a, b); /* notice the semicolon */
declare a, b,
temp float;
temp = a;
a = b;
b = temp;
end swap;
Again
the procedure name swap is used for the name of the
procedure and for the final end statement. This method is used in PL/I for the main program, subroutines, and functions.
A
statement or something is needed to stop the execution of the program. This is
the logical end of the program. In C++ we could just
have:
main(){
cout
<< “Good bye world.” << endl;
} // logical end of the program.
In this great program, the last brace (some times called close curly brace) indicates the logical end of the program. This method of ending is called falling off the end and considered non-elegant. We could be more politically correct (PC) if we did the following:
int
main(){
cout
<< “Good bye world.” << endl;
return(0); // logical end of the program.
}
So in C++ and other similar languages, the return statement is used to stop the execution of the program when in main( ).
While
we can only have one physical end (e.g. end or closing brace) of the
program, we can have one or more logical ends or return statements. For example:
if (x < 0) return(1); // error end of the program.
. . .
cin
>> x;
. . .
return(0); // normal end of the program.
}
Now
we can stop the execution of the program with the return statement in the if
statement. Or we can stop the execution of the program with the return statement before the closing brace. When you get to
the section on Return Codes later in this chapter, I cover the values (1 or 0)
in the return statements.
The
problem with using a return statement to stop the
program is that we may want to stop the program while in a function or
subroutine. But if we are in a function, then the return statement will just get us
back to the main or calling program. This is why some languages have a separate
command to stop execution. C++ uses the exit() function to terminate the program execution. Here
is an example:
if (x < 0) exit(1);
The
exit() is a function and not a
command. Unlike the return statement, it will cause a
program to stop execution even in a function. And the exit() function can also return a value when executed, like the return statement. So the C family has
three ways to end the program: exit(), return, and final closing brace.
Both
FORTRAN and BASIC have a STOP statement. The STOP statement cannot return a
value like exit() in C++. There is only one END statement in the program,
but there can be several STOP statements. We may have something like this
in these languages:
IF (x < 0 ) STOP
. . .
STOP
END
Or
we might change the above to the following so there is only one STOP statement:
IF (x < 0) GOTO 150
. . .
150 STOP
END
Some
people would argue that one of those is better than the other but I will decline
getting involved in that argument. A STOP statement is customarily used
but not required, since the END statement will take care of it. Thus we can
fall off the end of the program (hit the END statement) and the program also
halts.
COBOL
uses STOP RUN to
terminate a program, which illustrates the notion that COBOL programmers will
always use more words if they can. Like its similar cousin in FORTRAN we can
have several STOP RUN statements and if we have
none, the program will still cease after processing the last statement.
FORTRAN
I allowed an octal integer after the STOP statement, as follows:
STOP 4
The
octal integer, called a return code, would display on the IBM 704 console in the address field of the
storage register and the programmer could see which STOP halted the program. This
was a LONG time before time-sharing. Then you could look at the console and see
what number was there and know why the program stopped. Only one program could
execute at a time, so that programmer got the machine and the console. It is
difficult to understand why a short print statement indicating the problem
might not be more useful. While this may nowadays seem like a quaint use for STOP statements, we can see how it has evolved into
similar uses.
This
use is more than a historical note, since IBM Job Control Language uses
condition codes and the C family of languages uses an
integer in their return statements to indicate the
success or failure of program execution.
The
custom in the C family of languages is to return a value zero if the program
executed successfully. Thus we use:
return(0);
A
non-zero value, indicates a problem or non-successful
program execution. Thus we could use something like this:
if (x < 0) return(1);
Different
integers could be used to indicate the type of error. This type of information
is useful, since often one program calls another program and the first program
needs to know if the second program successfully executed. For example, one
program could process and prepare data, and then request a sort program to sort
the data file. If the sort worked correctly, then a third program could be
called to print the data. These are all separate programs.
IBM Job Control Language (JCL) used condition code to indicate the relative success of the jobstep. A condition code of zero may indicate a successful
run. IBM designated certain condition code numbers that normally indicate some
kind of problem and should not be ignored. These numbers are in multiples of
four: 0004, 0008, 0012, 0016, 0020, and 0024. The different codes had a
suggested meaning. Codes 0001-0003 usually indicated successful run. Code 0004 (or
higher) was used for a possible error but execution was possible. Code 0008 (or
higher) is a serious error, and each higher number from the above list
indicates a more serious error.
PHP
has the exit and return commands that do the normal things, but also has
the die() function. The die() function will stop
executing the program and return the expression to the browser just before
aborting the script. Here is some PHP code:
$file = fopen($filename, ‘r’) or
die(“unable
to open $filename”);
This
die() function goes beyond an exit or return since it can return an
expression such as a character string before terminating the program.
Perl
has a similar die function that is also often
used in the right side of a logical or, as follows:
open(FILE,
“myfile”) or die ”Can’t open myfile\n;
The
output from die is sent to standard error
and the program is terminated. Perl has a less disruptive function called warn, which also sends messages
out to standard error, but the program does not terminate. While die is often used on the right side of an open command, it can be used many other places. The Perl die command also has access to the special variable $! which contains the most recent system
error message.
FORTRAN
had a PAUSE statement. It was used to halt the
computer in such a way that execution can be resumed. This was necessary so special
paper (paychecks) or magnetic tape could be loaded on the
machine for the next part of the job processing. One variation of the PAUSE
statement might look as follows
PAUSE 'MOUNT THE NEXT TAPE'
I
guess it is time to stop (0) or pause on this topic. I bet some
of you did not know all the ways to stop a program smoothly. In COBOL the JCL
was used to tell us to mount tape or change paper for the printer.
In this section on ending the
program, I first separate the logical end and the physical end of the program.
The physical end of the program is the last curly brace in many languages, but
other languages use a special command such as an end statement.
The logical end of the
program is the command that stops the execution of the program and this end can
be placed any place in the program. There is a wide variety of commands to
terminate program execution, including stop, exit, and return statements. And many languages can return an exit code
when stopping the program. Readers interested in the topics covered in this
section should also look at the return statement in the Function chapter.
It
is surprising how often a programming instruction, command, or word is needed
that does nothing. There are several variations, which include null statements,
dummy commands, and noise words. The obvious usefulness of a dummy or null statement
is similar to the history of mathematics, where they “discovered”
that zero would be an interesting number to have. Noise (unnecessary) words are
used to make statements easy to read, or help programmers coming from a different
language.
Here
is an example where a null statement lets us avoid some serious thinking or
making a bad logic error:
if (age
< 21 && sex != ‘m’ || rate <= 25)
; /* null
statement, do nothing here. */
else
countx = countx + 1;
In
this example we do not want to do anything when the condition is true, but we
do want to increment countx when the condition is
false. In the above example if we did not have a null statement I would have to
figure out how to reverse the comparison in the above if statement, and the likelihood
of getting that correct is about as likely as me being elected Governor.
Instead, we just use a null statement.[1]
Null
statements are also use for the loop body when all the work is done in the
expressions. For example, here is some JavaScript code:
for(k = 0; k <
codes.length;
codes[k++] = 0)
; // null
statement here.
In
the above statement, I am setting all the elements of array codes to zero, by incrementing
the array index (k++) in the last part of the for statement.
Null statements can be used to avoid a dangling else, especially in a nested if statement. Here is some pseudocode:
if (condition-1) then
if (condition-2) then statement-1
else ; //null statement
else statement-2
The
first else has a null statement, and
then the last else can be used to match the first if instead of the second if statement.
Here
are some null statements in various languages:
Language |
Null statement |
Java/C++ |
; |
FORTRAN |
continue |
COBOL |
exit |
Assembly |
nop |
BASIC |
: |
|
null |
Python |
pass |
Null
Statements by Language
Table x.1
Most
languages have a null statement so it must have a purpose.
Dummy
or null statements are used as placeholders where a statement has been taken
out or will be added later. In other situations they are a useful place to
branch to where we want nothing to happen, such as the bottom of a loop. Their
use as a branch point is covered with the BASIC next command and the FORTRAN continue command later in this
section on “Loop Closings.” Another reason for using dummy
statements is to trick or satisfy the compiler. The compiler requires a
statement, but we do not want to do anything, so we insert a dummy or null
statement.
The
do nothing statement is as old as programming
languages. Assembly language and Rexx have their nop (no operation) statement. It had several purposes. A nop can be used as placeholder
where a statement has been taken out or statements will be added later. Also, nop can be used as a standard
null statement. Some languages use noop instead of nop for this command. Here is an example in Rexx:
if color = ‘BLUE’ then
nop /* null statement */
else
say ‘Why not blue?’
In this Rexx example, the nop is similar to the standard null semicolon used in modern languages. In Rexx the nop is useful as the target of a then or else clause.
In assembly language the nop instruction makes the CPU idle for one clock cycle. So if we need a delay of three clock cycles, we just insert three nop instructions. Thus the assembly language nop is slightly different than a standard null statement, since it actually does something, eating up some time.
COBOL
has the NEXT SENTENCE that is used as follows:
IF (AGE
< 21 AND SEX NOT = ‘M’ OR
RATE <= 25) THEN
NEXT SENTENCE
ELSE
MOVE ID-NO TO ID-NO-OUT.
The
COBOL NEXT SENTENCE seems to be used only with IF statements. ALGOL and C
improved this by adopting the semicolon for a null statement. It may surprise
you but the null statement was one of the important
contributions of ALGOL. I guess we can say ALGOL contributed nothing and it
was quite useful!
Noise words are redundant reserved (maybe) words that help programmers read statements and help the compiler find syntax errors. Thus, some times a noise word is an optional word and other times a required word. Another reason to use redundant words is to help programmers moving from another language to a new language. COBOL has a lot of noise words. The use of then with if statements is a good example of a useful noise word. Here is some pseudocode:
if (a <= 10) then
count =
count + 1;
Some
languages require the above then with if statements, some do not use
it, and others allow it but do not require it.
Ruby
requires then when if statements are all on one line. For example:
if age <= 21 then puts “under 21”
end
The
then is used to separate the
comparison from the statement. But then is optional when the if statement is on
multiple lines as follows:
if age <= 21 then # then not required here.
puts
“under 21”
end
The
end keyword terminates if statements.
The
C family illustrates why then should perhaps be a required word. For
example, here is a common C++ programming error:
if (count <=10);
cout
<< 1.0/count << endl;
Did
you notice the unwanted semicolon on the first line, at the end of the if? It is a null statement. So we may have a very tight
infinite loop, or some other logic error. If we had a language that required
the noise word then, this type of error would be more rare. For example, here is some pseudocode
for the same statement where a then has been used:
if (count <=10) then ; // much less likely to do
cout
<< 1.0/count << endl;
Some noise words are to prevent errors, but others are just for convenience, especially for programmers coming from other languages. For example, some languages require the word then after the comparison in an if statement and other languages forbid the use of then. So COBOL allows either:
if (count <= 10) then compute count = . . .
if (count <= 10) compute count = . . .
COBOL has other noise words. For example, COBOL wants all statements to start with a COBOL verb, so we cannot use the easy to understand:
count = count + 1.
but
must instead use:
compute count = count + 1.
So
in this statement compute is a required noise word.
Early BASIC required assignment statements to start with the reserved word LET. So in BASIC we would do something similar to
LET COUNT = COUNT + 1
Since
all BASIC statements started with a 2- or 3-letter keyword (rem,
let, if, for, …) it made it easy for small
compilers to process statements. As computers got bigger or compiler writers
got smarter we got to skip the LET command for assignment statements in BASIC.
COBOL
lets us use the word is, but does not require it in
the following COBOL phrase:
value is zero or
value zero
We
can also say:
on size error or
size error
leaving out the optional word on.
Other
COBOL noise words are is and than which are used in comparisons. We can write:
IF (AGE IS GREATER THAN 21) THEN . . .
or we can write:
IF (AGE GREATER 21). . .
There
are other examples of optional noise words in COBOL, maybe because they have so
many words to choose from. COBOL allows us to be as brief or verbose as we wish.
In Pascal, the use of then for if statements is not required. So we can have:
if a <= 0 then foundit
:= 0;
or
we can have
if a <= 0 foundit
:= 0;
which is much harder to read and do syntax checking (at least for me).
Parentheses
are not required around conditionals in Pascal. Several other languages,
including Ruby, do not require parentheses around conditionals in if statements. Some languages
that do not require parentheses around comparisons are COBOL and Pascal. But
parentheses are allowed, so parentheses are examples of useful "noise
items" in these languages. Java and Fortran
require us to use parentheses around comparisons.
Dummy
statements are commands that do nothing or execute no operation. They may serve
to place a label. The most common uses of dummy statements is for loop closing or
branch points where nothing happens. It is amazing how much we can make out of
nothing. FORTRAN has the CONTINUE statement and BASIC has the
NEXT statement. Both of these
are used to be the last statement of a loop, which can be also branched to and
nothing bad will happen.
The
C family has a similar situation where a statement must follow a label. But we
may want no statement if the label is at the bottom of a loop. For example:
{ . . .
go to done;
. . .
done: ; /* null statement here */ }
In
this example, we are required to have a statement after the label done, but do not need any statement, so we add the null
C statement. C++ has relaxed that requirement.
In
both BASIC and FORTRAN we use a noise statement to indicate the end of loops or
to have some place to branch to where nothing will happen. Here is an example
in FORTRAN:
do 10, k = 1, 8,
1
if
(a .le. 0.0) goto 10
. . .
10 read *, a
The above branch goes to another read statement, which we may not
want to do. So instead we use the dummy FORTRAN continue statement.
do 10, k = 1, 8,
1
if (
a .le. 0.0) goto 10
. . .
read
*, a
10 continue
A
similar situation occurs with BASIC for and next statements as follows:
10 for k = 1 to 8 step 1
20 if (a <= 0.0) then goto 40
30 . . .
40
next k
In
the following example, we skip dividing by zero, by branching to the continue statement.
c print inverses -5 to 5, skipping
zero.
do 10, k
= 1, 11
m = k - 6
if (m .eq. 0) goto 10
print
*, m, 1.0/m
10 continue
In FORTRAN we have another need for continue statements – to branch to the end of a nested loop.
do 10, k = 1, 8
do
10, m = 1, 5
if (
a .le. 0.0) then goto 10
. . .
10 continue
What problem do you see for the compiler in the
above code? There are nested loops, so it is not obvious if the goto statement is branching to the end of the inner loop
or outer loop. Fortran has a rule for this, but we may
not know the rule and assume the other loop is being ended. This discrepancy is
taken care of by using two continue statements.
do 10, k = 1, 8
do
5, m = 1, 5
if (
a .le. 0.0) then goto
10
. . .
5 continue
10 continue
In this example, the second continue statement is necessary. The
above could be done in BASIC using for and next, almost exactly the same.
In this section I provided examples of how null
statements and noise words are used in many languages. Some times they are used
to make the program more readable. In other cases a null statement was used to
avoid a syntax irregularity. For those of you interested in these topics, the
section on statement separator and statement terminator may also be of
interest.
$!
Perl......................................................................... 7
__END__
Ruby...................................................................... 2
{ open brace............................................................. 2
} closing brace.......................................................... 2
ALGOL
null statement.................................................... 10
assembly language
nop........................................................................ 9
brace
ending.................................................................... 4
COBOL
NEXT SENTENCE........................................... 10
compute
noise word.......................................................... 11
condition codes........................................................ 6
continue statement........................................ 13,
14
curly brace
see brase................................................................ 4
die
function................................................................. 6
do nothing commands............................................ 8
dummy commands................................................. 8
dummy statements............................................... 13
end
labeled................................................................... 2
program................................................................. 4
end period................................................................. 2
END statement......................................................... 2
execution
stopping................................................................. 4
exit
function................................................................. 4
falling off the end................................................ 4,
5
greater than........................................................... 12
IBM JCL................................................................... 6
if
use of then....................................................... 10
is
noise word.......................................................... 12
JCL............................................................................. 6
Job Control Language............................................ 6
labeled end................................................................ 3
logical end................................................................. 3
loop closings........................................................... 13
magnetic tape
pause................................................................... 7
nested loop
branch to............................................................ 14
next
BASIC................................................................. 14
NEXT SENTENCE................................................. 10
no operation............................................................. 9
noise words............................................................. 10
noop, see nop......................................................... 9
nop............................................................................ 9
null statement........................................................... 8
ALGOL contributed.......................................... 10
on
noise word.......................................................... 12
PAUSE....................................................................... 7
paychecks
pause................................................................... 7
physical end.............................................................. 1
PL/I
program ends....................................................... 1
politically correct..................................................... 4
program end............................................................. 1
redundant words.................................................... 12
return.................................................................... 4
return code................................................................ 5
Rexx
nop....................................................................... 10
STOP RUN
COBOL................................................................. 5
STOP statement....................................................... 2
than
noise word.......................................................... 12
then
noise word.......................................................... 10
verbose
COBOL............................................................... 12
warn
function................................................................. 7
= =
PL/I
has end, exit, stop, and return statements.
do
I want to do anything with UNIX exit.
This file is from www.gavilan.edu/csis/dvantassel/history/end-stop.html
Date last revised Feburary 17,
2008.
Copyright Dennie Van Tassel, 2004.
Send comments or suggestions to dvantassel@gavilan.edu
I am especially interested in errors or omissions and I have
other chapters on History of Programming Languages.
This work is licensed under a
Creative Commons Attribution-No Derivative Works 3.0 United States License.
[1] Some of you may have observed that I could negate the whole comparison, but that is in a different chapter, and I would lose this nice example.