Category : Miscellaneous Language Source Code
Archive   : FORTRAN.ZIP
Filename : SBM.LST

 
Output of file : SBM.LST contained in archive : FORTRAN.ZIP





















S B M F O R T R A N

A FORTRAN answer to 'C'





The best road is designed by the traveller.






Copyright (c) 1989-1991 by

DUKE DAIGH

Pine Bluffs, Wyoming 82082-0631





DISCLAIMER



This is the initial release of SBM FORTRAN. It is probable that there
are bugs. It may NEVER be totally bug-free. For this reason we make
the following statement.

This program is supplied as-is. The author disclaims all warranties,
expressed or implied. The author assumes no liability for damages which
might result from the use of this program.

You are encouraged to freely distribute this package. Mail copies to
friends. Put it up on other boards. We only request that you
distribute only unmodified copies.


Direct all inquiries, suggestions, etc. to:

Duke Daigh
P.O. Box 631
Pine Bluffs, Wyoming 82082-0631




CONTENTS

Introduction to SBM fortran. . . . . . . . . . . . . . . . . . . . iii
Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iv
Current status . . . . . . . . . . . . . . . . . . . . . . . . . . v

Fortran statements . . . . . . . . . . . . . . . . . . . . . . . . 1-1
Statement lables . . . . . . . . . . . . . . . . . . . . . . . . . 1-1
Symbolic names and keywords . . . . . . . . . . . . . . . . . . . 1-1
Statement order . . . . . . . . . . . . . . . . . . . . . . . . . 1-1

Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2
Include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-2

Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3
Byte, Character, Integer*1, Logical . . . . . . . . . . . 1-3
Word, Integer, Integer*2 . . . . . . . . . . . . . . . . 1-3
Doubleword, Integer*4 . . . . . . . . . . . . . . . . . . 1-3
Character strings, ASCIIZ . . . . . . . . . . . . . . . . 1-3

Quoted strings . . . . . . . . . . . . . . . . . . . . . . . . . . 1-4
Data declaration and initialization . . . . . . . . . . . . . . . 1-5
Data statement . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5

OPEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-1
UNIT (5-255). . . . . . . . . . . . . . . . . . . . . . . 2-1
IOCB names . . . . . . . . . . . . . . . . . . . . . . . 2-1
FILE . . . . . . . . . . . . . . . . . . . . . . . . . . 2-1
ALIAS (alternate name for io unit). . . . . . . . . . . . 2-1
STATUS (old, new, append) . . . . . . . . . . . . . . . . 2-1
RECL . . . . . . . . . . . . . . . . . . . . . . . . . . 2-1

READ STATEMENTS . . . . . . . . . . . . . . . . . . . . . . . . . 2-2
Unformatted . . . . . . . . . . . . . . . . . . . . . . . . 2-3
formatted . . . . . . . . . . . . . . . . . . . . . . . . . 2-4
List directed . . . . . . . . . . . . . . . . . . . . . . . 2-4

Next character from keyboard (NEXCHAR). . . . . . . . . . . 2-4

WRITE STATEMENTS . . . . . . . . . . . . . . . . . . . . . . . . . 2-5
Unformatted . . . . . . . . . . . . . . . . . . . . . . . . 2-5
formatted . . . . . . . . . . . . . . . . . . . . . . . . . 2-5
List directed . . . . . . . . . . . . . . . . . . . . . . . 2-6

SHOW_CHAR (display a character on screen) . . . . . . . . . 2-6
CRLF (write cr,lf to specified IOCB) . . . . . . . . . . . 2-6

FORMAT STATEMENTS . . . . . . . . . . . . . . . . . . . . . . . . 2-7
Field and edit descriptors. . . . . . . . . . . . . . . . . 2-7

ARITHMETIC EXPRESSIONS . . . . . . . . . . . . . . . . . . . . . . 3-1
INC, DEC (incrementing and decrementing variables. . . . . 3-1
ADD, SUB (adding to, or subtracting from variables . . . . 3-1
Subscripts . . . . . . . . . . . . . . . . . . . . . . . . 3-2





CONTROL STATEMENTS
TEST, TEST Numeric. . . . . . . . . . . . . . . . . . . . . 4-1
Control flags . . . . . . . . . . . . . . . . . . . . . . . 4-1
Conditional transfers . . . . . . . . . . . . . . . . . . . 4-1

Compare variable to constant, CMP . . . . . . . . . . . . . 4-2
Compare string to string . . . . . . . . . . . . . . . . . 4-2
Unconditional transfers, GOTO, JMP . . . . . . . . . . . . 4-2
WAIT . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2
PAUSE . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2
STOP, CALL EXIT . . . . . . . . . . . . . . . . . . . . . . 4-2

TABLE_LOOKUP . . . . . . . . . . . . . . . . . . . . . . . 4-3

IF statements . . . . . . . . . . . . . . . . . . . . . . . 4-4
Block IF . . . . . . . . . . . . . . . . . . . . . . . . . 4-5
Do-loops . . . . . . . . . . . . . . . . . . . . . . . . . 4-8

RESERVED WORDS AND ARRAYS. . . . . . . . . . . . . . . . . . . . . 5-1
The command line (command tail) . . . . . . . . . . . . . . 5-1
Useful program constants . . . . . . . . . . . . . . . . . 5-1


Miscellaneous Intrinsics . . . . . . . . . . . . . . . . . . . . . 6-1
COPY Array_1 to Array_2 . . . . . . . . . . . . . . . . . . 6-1
FIND_CHAR 'c', Array . . . . . . . . . . . . . . . . . . . 6-1
END Ignored by the compiler. . . . . . . . . . . . . . . . 6-1
Masking operations. AND, XOR, OR . . . . . . . . . . . . . 6-1
SHIFT Shift a variable. . . . . . . . . . . . . . . . . . . 6-1
PARSE String, Keword . . . . . . . . . . . . . . . . . . . 6-1
PARSE_ONLY String, Keword, 'char' . . . . . . . . . . . . . 6-1
LDA. Load address . . . . . . . . . . . . . . . . . . . . 6-2
UPCASE. Convert string to upper case . . . . . . . . . . . 6-2

SYSTEMS STUFF . . . . . . . . . . . . . . . . . . . . . . . . . . 6-3
EXCLUDE_RTL . . . . . . . . . . . . . . . . . . . . . . . . 6-3
LABEL variable, word/byte. . . . . . . . . . . . . . . . . 6-3
PRESET data-type,variable . . . . . . . . . . . . . . . . . 6-3
SETFORM 'c' . . . . . . . . . . . . . . . . . . . . . . . . 6-3
SETIF 'c' . . . . . . . . . . . . . . . . . . . . . . . . . 6-3


Ramdisk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-1

Known bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-1





INTRODUCTION TO SBM FORTRAN

This manual describes SBM FORTRAN. SBM is based on American National
Standards Institute FORTRAN 77 language. It is assumed that the reader
has knowledge of an existing FORTRAN language and is familiar with MSDOS
or PCDOS operating system. This manual is not intended to teach
FORTRAN, but is intended to be used as reference material only.

The original intention of SBM fortran was the author's answer to the 'C'
language. The cryptic nature of 'C', while appealing to many
programmers, leaves me cold. While I fully appreciate the power of the
'C' language (as with assembler), I felt that there was needed something
that would better suit my style.

I also remember when I brought my first XT home. There were many
fortran-written utilities that I had on the Z-80 without which I felt
very helpless. By the time I had rounded up the money to buy the system,
I had none left for the software that I very sorely needed. An
affordable compiler of an easily learned language seemed to the the
answer. A good reason for someone, such as I, to write SBM fortran.

The powerful fortran systems that are now on the market are designed with
the high-level user in mind. Program size is not important. I needed
something that would generate about the same code as if I wrote the it in
assembler.

This compiler operates by converting FORTRAN source code into assembler
instructions, which are then converted into machine code using WASM, an
assembler written by ERIC TAUK, of Merengo, IL. The result is a COM
file, which can then be run on any MSDOS based system.

THIS IS VERSION 1.00. To most of us this means a system that works well
enough for the author, but sometimes awkward for the user. Here is a
problem. I am in the process of moving to Wyoming. Here in Denver, I
have access to many excellent bulletin boards. In Wyoming, that will
not be the case. I must therefore release this version knowing that
there may be bugs. Since I will no longer have easy access to the
boards, I will not longer have easy access to you, the user. I must
therefore go to a 'shareware' mode.

To provide this connection, You must send me your name and mailing
address. That will make you a registered user. To receive ANY updates of
this compiler, you MUST be a registered user. At a minimum, I will
upgrade to provide some of the functions that I need. Registered users
will receive the first (or most recent) update. I most certainly need
your suggestions for improvements and bug removal. If you like this
compiler as I believe you will, your $20 contribution will be
appreciated. Since I will no longer have access to the boards, that's
the only way that you can receive the update.



MSDOS is a registered trademark of Microsoft Corporation.
PCDOS is a registered trademark of IBM Corporation.





iii





FEATURES OF SBM FORTRAN

It is a compiler compiler. It was conceived as a bootstrap system to
compile parts of itself. That's why I refer to it as my answer to 'C'.

You can insert assembler coding and macros. You can invoke the standard
interrupts. In other words, you can do anything with this compiler that
you can do in assembler. In fact, some of the more complex modules of
the compiler are WRITTEN IN FORTRAN. Any future refinements will be
written in fortran.

The executable module is very compact and efficient compared to other,
higher-level compilers.

It combines the simplicity of fortran coding with the power of the
assembler.

You can operate it as you would any other F77 compiler and end up with
code that will usually run on any other F77 compiler.

You can place more than one statement on each record.

You can append comments to each statement.

The compiled module uses buffered input, making it very fast.
Pathnames are used so that you can access data on other drives and
in other directories.

All console/keyboard i/o can be re-directed.

It has many powerful intrinsic operations, such as: PARSE, COPY,
TABLE-LOOKUP, COMPARE, etc..

You can do masking operations, such as AND, OR, XOR.

You can shift variables left or right, by the number of bits that you
specify.

















iv





CURRENT STATUS OF SBM FORTRAN

BE VERY CAUTIOUS USING ANY SORTWARE! Do not trust it! Even if you
have been using it for awhile, mentally EDIT the output. Does it look
reasonable? You are the best judge.

SBM fortran is not a scientific compiler. i.e., it does not have
floating point.

Integer*4 is there, but needs more hooks before it can be used.

Arithmetic expressions are primitive, but gramatically correct and
transportable. This feature will be upgraded to some extent.

Needs more diagnostic messages. SBM fortran is not just forgiving. It's
actually permissive.

But, on the other hand, if you accept the above limitations, and write a
program using standard fortran coding techniques, it will work, and the
code can be put up and run under most other F77 compilers, without
modification.




FUTURE OF SBM FORTRAN

SBM fortran was not, and is not intended to be a full-blown fortran
compiler. It is not intended to compete with the more powerful
systems.

Integer*4 is one feature that will certainly be implememted. With large
integers, you can do quite a lot. Accounting work and other related
types of work require precise calculations. Large integers makes that
precision possible. Instead of dollars and cents, you can carry
everything in total cents. i.e. $156.25 is 15625 cents. For output,
the format statement can direct that a decimal point be inserted (this
feature is already installed, but not yet usable).

The compiler needs compile time and runtime error detection that it does
not now have. Some errors simply lock up the system. That is something
that must be addressed in the first update.

The direction of its future is mostly up to you. I have some floating-
point routines that could be implemented, but I will probably not work in
that direction unless there's enough response. The routines are in
another fortran compiler of mine which I chose not to release at this
time.


There's another feature, TONTO (trace-on, trace_off), that might also be
moved from my other compiler.

v



1-1

FORTRAN STATEMENTS

There are two types of statements, executable and non-executable.

Non-executable statements are used to describe the characteristics and
format of data.

Executable statements specify actions that the program is to take
against, or for the welfare of the data, such as READ, WRITE, etc..

Each source input line can be as long as 80 characters. Statement
Continuations are permitted only on certain statements. they are:
OPEN, FORMAT, data initialization.

You can use statement labels to identify and reference individual
statements in a program. You can label any statement but only labled
statements can be referenced.


SYMBOLIC NAMES AND KEYWORDS

Symbolic names, chosen by the programmer, identify program variables and
statement lables. A keyword is a pre-assigned identifier that you use to
specify a particular action that the program is to take. Keywords are
also known as RESERVED WORDs (see 5-1).

A symbolic name is a sequence of one to 31 alphanumeric characters.

When used to identify program variables, the first character must not be
numeric. The name may consist of just about any printable character
except for + - * / ( ) ; | apostrophy or comma. You cannot use reserved
words to identify program variables.

Standard fortran labels consist of numeric lables only. SBM fortran
allows either, except for lables of format statements, which must begin
with a numeric digit 0-9. Lables cannot begin with + - * ; |. Lables
cannot use ( ) [ ] apostrophy or comma. Reserved words may be used as
lables.

Statement lables must begin in column 1. All other statements must begin
in any column other than 1. By all means use column 7 if you wish to
adhere to an accepted standard.

You can assign more than one lable to a statement if you wish. In doing
so, you can refer to it by either label.


More than one statement may appear on each source input record by
terminating each (except the last) with the marker code '|'. (on most
keyboards this is uppercase backslash) The format of the additional
statements is no different than the first, so don't forget to follow the
marker with at least one blank, unless it is to be a label.



STATEMENT ORDER

Doesn't matter. mix or match. the compiler will sort them out.



1-2

COMMENTS - You can use a semi-colon(;), an asterisk(*) or hyphen (-) in
column 1 to specify that the line is a comment. In addition, if you place
a ';' anywhere in the statement portion of a source line, the rest of
that statement will be treated as a comment. A blank line is also
considered to be a comment.

Individual assembler code statements can be inserted anywhere by placing
a plus (+) in column 1.


INCLUDE

Blocks of fortran statements, assembler code, and macros may be inserted
using the INCLUDE option.

Syntax: INCLUDE pathname Pathname can name any file that is
currently on line, on any disk.

To include assembler code or macros, the statement must have a '+' in
column 1 and the pathname must be in quotes.

Example: + include 'maclib.asm'


A small macro library is provided to generate some of the code that the
compiler needs. You may build one of your own choosing and insert it
using the + INCLUDE option.




1-3

DATA TYPES

* SBM provides three data types: BYTE, WORD and Doublewords.

BYTE data occupies 8 bits (one byte) of memory and is normally only used
for ascii characters and strings, or logical variables, such as
programmer-specified switches and flags. You can use this data type for
numerical values, up to 255.

WORD data are numbers that are whole positive, negative or zero-value
numbers. WORD data values occupy 16 bits (two bytes) of memory and can
contain numbers from -32,768 to 32,767. Although a word can hold a number
as large as 65,635, this implementation provides no standard way to
output the larger numbers.

* DOUBLEWORDs are 32-bit (integer*4) integers. The may contain numbers
within the range -2,147,483,648 to +2,147,483,647. Integer*4 data is very
useful for accounting applications where larger numbers are involved and
precision is required in transactions. For example, monitary amounts can
be set into integer*4 variables using total cents, rather than dollars
and cents. When the results are to be printed, a special feature of
integer*4 values allows you to insert decimal points where applicable.


In SBM FORTRAN, the following mean the same:

CHARACTER, BYTE, INTEGER*1, LOGICAL 8-bit data.

INTEGER, WORD, INTEGER*2 16-bit data.


CHARACTER strings appear in memory as a collection of ASCII characters
terminated by a binary zero. This zero terminator controls all
operations in which this data type is manipulated, such as compares,
copys, input-output, etc.. With the terminator, this is known as as
an ASCIIZ string.




* Integer*4 is not totally implemented. Some parts of it are. Some not.
I wouldn't recommend that you try it yet. It will be implemented in the
next update.



1-4

QUOTED STRINGS

Over the years, we programmers have created a standard that would not be
acceptable to people other than programmers. That is, calling an
apostrophy a quote! When we think of quoted strings, we think of an ascii
string enclosed in apostrophies, not quotes. Don't know how this started,
but we all do it. Anyway, format statements sometimes require us to
specify a 'quoted' string for output. With this in mind, in this manual,
when we talk of a quoted string, we mean a string that is enclosed in
apostrophies.

When entering a quoted string that we wish wish to contain an imbedded
quote, SBM FORTRAN requires that you use an ACTUAL quote("). Standard
fortran wants you to use two apostrophies in a row. We do it differently
here.



example: standard fortran requires:

FORMAT('We sometimes don''t follow standards')



We do it this way:

FORMAT('We sometimes don"t follow standards')






1-5

DATA DECLARATION and INITIALIZATION


There are two modes in which you can declare variables, (1) declare and
(2) declare/initialize.

(1) Declare. The 'standard' declaration in which you specify the size
of individual elements and optionally set aside a specific amount of
memory to contain these elements in an array.

Example: INTEGER ELEV(20), DIST(20), SLOPE, DELTA(3)

(2) Declare/initialize. This mode allows you to declare a variable or an
array and establish it's initial value(s). When initializing arrays, only
as much memory as needed to contain the given data will be allocated.
This statement can be continued. When used, this option must be the last
(or only) declaration on the source statement. You can, of course, put
multiple statements on one physical record. Examples:

integer day/5/| integer month/12/| integer year/1948/

integer*1 level(4), mace/3/

character pathname/'c:sales.jan',0/


This statement is tricky. If you forget the closing '/', the compiler
will search the rest of your source looking for one.

Here's another example, taken right out of the compiler itself:

character registers/
'AX',0,'BX',0,'CX',0,'DX',0,'SI',0,'DI',0,'BP',0
'AL',0,'BL',0,'CL',0,'DL',0,'AH',0,'BH',0,'CH',0
'DH',0,'[SI]',0,'[DI]',0,'[BX]',0,'[BP]',0,'$'/

If you want to declare an array of a certain size but initialize only the
first portion, here's another example from the compiler:

character outbuf(80)
data outbuf/'e:sbm.t$$',0/



THE DATA STATEMENT

This is an executable statement! Most fortran reference manuals don't
admit it but it is. Because of this fact, it can be used anywhere in
the program. As you see above, you can initialize a variable or an
array with it. You can also change data values on the fly. Over and
over.

Here's a handy use of this feature:

If(code.eq.4) DATA table/1,2,3,4,5/
If(code.eq.5) DATA table/6,7,8,9,0/



2-1

OPEN statement

The OPEN statement establishes the connection between a fortran UNIT and
a file or device. You must issue this statement before any diskfile I/O
can be used. Note: you cannot close a file and re-open.

syntax:

OPEN(UNIT,ALIAS=buff-name,FILE='filespec',status='old/new/append',
RECL=nnn)

where:

UNIT is a numeric constant, in the range of 5-255.

The unit number is converted to a control block name by appending the
number to 'IOCB_'. The unformatted input record can be referenced by this
name (as well as any alias that you may specify). Unit 10, for example
may be referenced by the name 'IOCB_10'. An example of this can be found
under UNFORMATTED READ.

ALIAS is an alternate name by which the file can be addressed when
reading unformatted (raw) data. Raw mode, when used instead of formatted
or list-directed input results in much faster i\o. Unformatted i/o is
discussed more fully in READ statements. This parameter is optional.


FILE='filespec'. Pathnames can be used here. You may name a file that is
to be used, or specify a character array which contains an ASCIIZ
filespec. If the name itself is used here, it must be enclosed in quotes.
If an array containing the filespec is used, it must not be quoted.


STATUS='old/new/append'. If the file is to be created, use 'new'. If the
file is to be read/write, use 'old'. If you have an existing file that is
to be enlarged, use 'append'. If you use 'new', any existing file by that
name will be replaced. If you omit this parameter, 'old' is assumed. The
quotes are optional, for compatability.


RECL=nnn. SBM uses a buffered input system, resulting in very high-speed
input. The buffering system uses two arrays. one for the input buffer,
(into which is loaded blocks of non-predictable pieces) and the record
buffer which will contain only the individual record. It is from the
record area that formatting takes place. You can use the RECL option to
insure that no record exceeds a given size. If this option is omitted,
record length defaults to 80.



2-2

READ STATEMENTS

READ statements transfer data from a specified I/O unit to memory. You
can reference both external and internal files. The input data may be
any ASCII stream.

Syntax: READ(UNIT [,FMAT]) list


UNIT is one of:

(1) An integer constant in the range of 5 to 255 that identifies an
external unit previously referenced in an OPEN statement.

(2) An asterisk (*) specifying the default I/O unit (console).
May be redirected.

(3) The name of an internal array (such as the input buffer)
containing data. This is the manner by which you can re-read
a data record. explanation: on any read, the data is read into
the input buffer as raw data. If a format has been specified,
the record is transformed into the corresponding input fields.
But: even after formatting, the raw data is still in the input
buffer.

FMAT is a parameter that specifies whether explicit or list-directed
formatting is to be applied. It may take either of the following
forms.

(1) A statement label of a format statement. The statement label
must begin with a numeric character 0-9. The rest of the label
can be anything of your own choosing.

(2) '*' that specifies list-directed formatting.


If FMAT is omitted, a 'null' read is performed, effectively passing over
an input record. The unformatted contents of the record are not lost,
however, but are preserved in the input-output control buffer (IOCB).
The string is available by its IOCB name, and may be treated as any
other character array.


LIST names the variables, arrays, array elements and character strings
to which data will be transferred.

If end of file is sensed, the logical variable 'EOF' is set to TRUE.



2-3

UNFORMATTED READ


Syntax: READ(UNIT) list

This is the most simple of the input statements. It transfers one
record of binary data to the array 'list'. No conversion takes place.
(A typical file of data information is stored as ASCII characters. No
conversion is required if all you want to do is to examine it. It is
considered to be binary data)


If 'list' is omitted, one record is by-passed. For that reason it is
sometimes referred to as a 'null' read, or 'by-pass' read.

The contents of the record are available in the IOCB or under the ALIAS
that was specified in the 'open'.

Here's an example of how you might use it to read and display a file.


open(5,file='reform.for')
1000 read(5)
if(eof) stop
write(*) iocb_5
goto 1000
end

Type this one in and try it. It will make your hair stand on end! If you
were to try this example on a large file, you can see that it wouldn't do
you much good. The output would fly by so fast that you couldn't read
most of it.



2-4

FORMATTED READ

Syntax: READ(UNIT,FMAT]) list

This is a two-step operation.

Step 1 reads the record into the IOCB (an unformatted read).

Step 2 applies the formatting and transforms the ascii data into the
various input fields.




LIST-DIRECTED READ

Syntax: READ(UNIT,*) list

Read statements are either unformatted or formatted. The difference in a
list-directed read is that the compiler is going to create a format for
itself, based on what kind of data we have in the 'list'.

This is a two-step operation.

Step 1 reads the record into the IOCB (an unformatted read).

Step two applies the compiler-designed formatting and transforms the
ascii data into the various input fields.





NEXCHAR

Reads a character from the keyboard. Does not echo to the console. If
no character is ready, waits for operator to enter one. The character
is available to the program in register AL. Execution resumes.

See 'testall.for' for a practical example. (NEXCHAR and WAIT are same)



2-5

WRITE STATEMENTS

WRITE statements transfer data from memory to a specified I/O unit. You
can reference both external and internal files.

Syntax: WRITE(UNIT [,FMAT]) list





UNFORMATTED WRITE


Syntax: WRITE(UNIT) list

This statement transfers one record of ascii data to UNIT. The data must
be terminated by a binary zero. No formatting takes place.

If 'list' is present, it must be the name of an array. If omitted, the
formatted contents of the IOCB is written.

This is the form of output that you should use to insert control
characters, such as escape-sequences, extra line feeds, backspaces, etc.

Example, from 'testall.for'

data outbuf/esc,'[2J',0/
write(*) outbuf ; clear the screen





FORMATTED WRITE

Syntax: WRITE(UNIT,FMAT]) list

This is a two-step operation and is the revese of formatted read.

Step 1 formats the specified data fields from binary to decimal as
required and copies ascii data or quoted strings into the IOCB.

Step 2 writes the contents of the IOCB to the specified UNIT.




2-6

LIST-DIRECTED WRITE

Syntax: WRITE(UNIT,*) list

In a list-directed write, a format is constructed by the compiler based
upon the data type of the various fields. Other than that, it is exactly
like the formatted write.

While most compilers require that the first character of an output record
be used for carriage control, SBM fortran does not. When output is to be
directed to a printer, feel free to insert ascii control codes, 0Ch for
eject, 0Dh for double space.




SHOW_CHAR

Display the character that is in the AL register. You can use this
statement immediately after NEXCHAR.




SHOW_CHAR 'char'

Display specific character. The character can be a printable
character enclosed in quotes, or a hex constant.
Example: show_char 8 gives us a back-space on the console.




2-7

FORMAT STATEMENTS

Format is a labled non-executable statement that specifies the format of
data being transferred between memory and i/o devices. It may appear
anywhere in the program. The first character of the label must be
numeric. The method by which formatting takes place is by the use of
field and edit descriptors with which the type and size of the various
data fields is specified and quoted strings for constant ascii data.

Each field descriptor consists of letter which identifies the type of
data, followed by a number indicating the width of the data field. In
some cases the width is optional.

Format control proceeds from left to right, matching each field
descriptor with each item in the i/o list.

SBM uses 3 field descriptors, A, I, X

Character data.
The 'A' field descriptor transfers character data. It has the form

A[w]

If W is present the field width is w-characters. If omitted, the field
width is the size of the data item in the i/o list. The name in the list
can be any data type, character, logical or integer. On input, any
existing data is simply overlayed.


Integer data I[w]

If the output binary number, when converted to decimal, exceeds the
allocated space, the number will back-flow into the previous field,
replacing whatever the formatter just put there. (not like standard
fortran, which would fill the output field with asterisks. If enough of
you complain, I will comply with the standard).


Skip [w]x

Quoted strings.


Dollar sign descriptor $

Normally, all output records are terminated by a carriage return. The
dollar sign descriptor inhibits this action. The option is intended for
interactive I/O and is valid only for output statements. It permits user
response to appear on the same line as a prompt.

example: WRITE(*,*) 'Enter project number: ',$
READ(*,*) PROJ

When used, the dollar sign descriptor must the the last item of the
output statement.



3-1

ARITHMETIC EXPRESSIONS

SBM fortran does not yet support more than a simple one-function
expression. The simpler form of an expression, while requiring more
statements to complete some calculations, still maintains compatability
with higher-level compilers.

Thus, we are limited to such statements as:

counter=counter+1
range=limit-base
etc..

String expressions allow a little more versatility, such as:

filespec='c:modemuf.asm'
letter='A'
etc..


In addition to the above arithmetic statements, SBM fortran also supports
the following statements:

INC, DEC Add or subtract 1 from an integer variable. This is the
most efficient way to add or subtract the constant 1 from
a variable.

example: inc counter ; add one to 'counter'
dec tally ; subtract one from 'tally'



ADD, SUB Add or subtract constant or value from register from an
integer variable. This is much faster than standard
fortran and uses less code.

example: add index,10 ; add 10 to index.

index=index+10 ; the usual, less
; efficient way.






3-2

SUBSCRIPTING


Any variable may be accessed by using the variable name in a fortran
statement. To access variables in positions other than the first, you
must (1) use an integer offset or (2) use a subscript.

An integer offset may be used by simply appending the variable name with
a plus-or-minus constant. Example: 'ARRAY+4' points to the fifth
position of a integer*1 or character array. If the array was integer*2,
it would point to the third position, since each element in an integer*2
array requires two positions. While this is not a standard fortran
method of accessing data, it is by far the most efficient.

Subscripts, on the other hand, indicate the position of an element by
enclosing a subscript expression within a pair of parentheses.

The subscript expression can be an integer constant, and integer
variable, or an integer variable plus-or-minus an integer constant.

Examples: array(k), date(m+2), etc..

Other informative examples can be found in the program 'TESTALL.FOR'.


A word of caution: Do not allow the expression to go negative. You will
access something, but who knows what...



4-1

CONTROL STATEMEMTS

There's no point in writing a program if you can't control what it does.
Without flow control, a program would sequentially execute each of your
statements and then blow up. That would be tacky.

Fortran flow control statements provide a means of modifying the normal
sequemntial flow of execution.

Flow control statements are: TEST, COMPARE, CMP, DO, CONTINUE, GOTO,
JMP, STOP and CALL EXIT. Some of these are not standard but all are
handy.



TEST

Usage: TEST VARIABLE, MASK
or TEST VARIABLE, NUMERIC

You can test a variable using a mask, or TEST NUMERIC.

When a TEST is performed, control flags are set, depending upon
the results of the test. You must then use an if-statement or
conditional jump. Control flags are: equal, not equal, zero,
not zero, carry and not carry.

(EQ), (NE), (ZR), (NZ), (CY), (NC), (NUMERIC), (NOT.NUMERIC)

CONDITIONAL JUMPs are JNC, JC, JZ, JNZ

Using a MASK, you can see if a particular bit or any one of a group
if bits is set. It does this with a logical AND, and sets flags but
changes nothing in memory.

Example: see if an integer is odd or even.
test(answer,1)
if(zr) goto even
(or) jz even


To test an individual ascii character to determine whether it is
numeric or not, use the following syntax:

TEST VARIABLE, NUMERIC

This checks an ascii character to see if it is within the range of
'0' - '9'. As a result of this test, the logical variable 'numeric'
is set to either true or false.

Example: test(inbuf(1),numeric)
if(not.numeric) goto alpha



4-2

CONTROL STATEMEMTS


CMP variable, constant

Compare a variable to a known value. This statement is identical to it's
ASM equivalent. Subscripts are not permitted, but offsets can be used.

Usage: CMP Name, 'A'
CMP Name+2,'B'
CMP Year, 99

This statement essentially subtracts the constant from the variable, does
not change any values in memory but, sets the control flags. You must
then use a conditional jump for program control.





COMPARE

Compare a string of characters against a model. Not case sensitive,
'TOKEN' should be upper case.

Usage: COMPARE KEWORD, 'TOKEN'


Example, from the compiler.

- see if prefix 'byte' or 'word'
compare keword,'BYTE' ;
if(eq) goto destin_ok ; if 'byte' or 'word',
compare keword,'WORD' ; accept it as-is.
if(eq) goto destin_ok ;


GOTO Unconditional transfer of control.
JMP Same as GOTO



WAIT

Wait for operator. Program execution stops. When operator has pressed
any key, execution resumes.



PAUSE ['message']

Stops, waits for operator. If message included, displays the message.
Otherwise, displays the phrase 'FORTRAN PAUSE'. Execution of the program
will continue with the press of any key.


STOP, CALL EXIT

Use either to close all files, update directory and return control
to the operating system.



4-3

TABLE_LOOKUP

Given a character string, tests to see if the string exists in a
specified table. Each entry in the table must be enclosed within quotes
and must be in upper case. each entry must be followed by binary zero.
The table must be terminated by a '$'.

If the given string is found to be present in the table, register CX
indicates it's relative position in the array. i.e., in the table
below, AX=1, BX=2, CX=3, etc.

If the string cannot be found, CX=0 and carry-flag is set.

Here's a sample table.

character registers/
'AX',0,'BX',0,'CX',0,'DX',0,'SI',0,'DI',0,'BP',0
'AL',0,'BL',0,'CL',0,'DL',0,'AH',0,'BH',0,'CH',0
'DH',0,'[SI]',0,'[DI]',0,'[BX]',0,'[BP]',0,'$'/

The following example wants to see if the character string that is in
the array 'keword' is any of the entries in the table 'registers'.

- see if a destination is register.
table_lookup keword,registers
if(nc) goto destin_ok




TABLE_ADD

Following a table-lookup operation, adds a string to a given table.
While this is not a control statement, it is included here because it
is frequently used immediately following a non-successful table_lookup.

Example: install the string in the array 'keword' in the table.

- new symbol, put it in table.
table_add keword




4-4

IF statements

An IF statement conditionally executes one statement or a block of
statements.

The IF statement has the form:

IF (exp) stmt

Where exp is a logical or relational expression.



In a LOGICAL IF statement, we have, as the result of a TEST or
input/output operation, a condition of true(non-zero) or false(zero). The
statement, or block of statements, will be executed only if the condition
is true. In a logical IF, exp simply names the logical variable. In
addition to the normal variable names, SBM fortran also allows the
following:

(EQ), (NE), (ZR), (NZ), (CY), (NC)

or (EOF), (NOT.EOF), (NUMERIC), (NOT.NUMERIC)

stmt can be any non-labled executable statement, but not another IF.


The RELATIONAL IF statement performs an on-the-fly comparison of a
variable to a known value.

Character-strings can be compared, no matter what their length, but only
for EQ or NE. Other operators may be used, but use with caution. The
comparison is NOT case sensitive.

The relational IF has the following syntax:

IF (VARIABLE.OP.Constant) stmt

where OP will be EQ, NE, LT, GT, LE, GE

Constant may be (1) numeric,
(2) Ascii character (excluding ';' and '|') , or
(3) AsciiZ string.



4-5

There are two types of IF statements:

o The single IF

o The block IF

(The arithmetic IF is not supported by SBM fortran)

The single IF statement conditionally executes a single statement. It
has the form

IF (exp) stmt

where:
exp is a logical expression.

stmt is a single, not continued, fortran statement.



4-6


The block IF conditionally executes blocks of statements. It has the
following form:

IF (exp) THEN
block

ELSE
block

ENDIF

where:
exp is a logical expression.

THEN must appear on the same line.

block is a series of statements, none of which can be another block-IF.

The ENDIF terminates the block-IF construct.






4-7


There are two types of data which can be compared in an IF statement,
numeric or literal. Literals are recognized by the presence of quotes.
Here are some examples:


* Author used the following program to test out and debug IF statements.
integer ibuf
write(*,*) 'enter a number: ',$
read(*,*) ibuf
if(ibuf.eq.100) then
write(*,*) '---------------'
write(*,*) 'number is equal'
else
write(*,*) 'number is NOT equal'
endif
if(ibuf.lt.100) write(*,*) 'number is LT 100'
if(ibuf.le.100) write(*,*) 'number is also LE 100'
if(ibuf.gt.100) write(*,*) 'number is GT 100'
if(ibuf.ge.100) write(*,*) 'number is also GE 100'
stop

- - - - - - - - - - - - - - - - - - - - - - - -

; this program reformats a WASM LST file to straight ASM format. You
; might want to do this to have a source that has the macros expanded.

open(5,file=infile,status='old',recl=132,alias=inbuf)
loupe read(inbuf)
if(eof) stop
if(inbuf.eq.20h) goto loupe
if(inbuf.eq.'L') goto loupe
if(inbuf+22.eq.20h) goto loupe
write(1) inbuf+26
jmp loupe




4-8


DO Statement

Here you can specify that a block of statements be executed for a
specific number of times.


Syntax: DO label index=first,last

where: label is a numeric statement label of a CONTINUE statement which
is forward from this statement.

index is an integer*2 variable that will be set, and then
incremented.

first is an integer constant.

last is an integer constant.




CONTINUE statement

Used only in conjunction with the DO statement, this statement is labled
and is used as the terminator of the block of statements to be executed.


Example: from "testall.for"

do 809 counter=1,10
write(16,309) counter
309 format('test output record',i3)
809 continue



5-1

RESERVED KEYWORDS and ARRAYS

FORTRAN has many keywords that are meaningful to the compiler, such as
IF, READ, WRITE, etc.. In addition to the standard list of reserved
keywords, SBM fortran includes some options not provided in other

systems:


LDA, EXCLUDE, WAIT, JMP, JNC, JC, JZ, JNZ, AND, XOR, OR, SHIFT,
SETFORM, SETIF, SHOW_CHAR, INCLUDE, UPCASE, INC, DEC, TEST,
ADD, SUB, CMP, LABEL, PARSE, COPY, NEXCHAR, TABLE_LOOKUP, TABLE_ADD,
COMPARE, FIND_CHAR, CRLF, PRESET.

YOU CANNOT USE RESERVED WORDS AS VARIABLE NAMES, although any of them
may be used as statement lables.


In addition to the above reserved words, we also have the following
arrays, which are considered as reserved words:

COMMAND, CONSOLE, INFILE, WORKBUF, OUTFILE, WORKBUF2.



THE COMMAND LINE

One of the problems facing the high-level programmer is how to access the
data that we entered at the system prompt. SBM fortran sets this data
where it can be easily used. The command tail can be located in the
character array COMMAND. From there it can be parsed or otherwise used
just like any other character array. In addition, the first two tokens
are parse into INFILE (alias WORKBUF) and OUTFILE (alias WORKBUF2) and
may be used as filenames in the OPEN statement.

The advanced programmer will find these options to be of significant
value.


PROGRAM CONSTANTS


Rather than using numerical equivalents for commonly needed constants,
you may choose from the following list of pre-assigned symbolic names.

CR Carriage return. Use instead of 0Dh, 13 decimal.
LF Line feed. Use instead of 0Ah, 10 decimal.
ESC Escape. For ansi screen control, 1Bh, 27 decimal.
FF Form feed. To eject the page in printer files.
TAB
BS Back space.
COMMA Equivalent to 2Ch.
QUOTE Equivalent to 27h.
QUOTES Equivalent to 22h.
False Equivalent to binary zero.
True Equivalent to binary 1.



6-1
MISCELLANEOUS INTRINSIC FUNCTIONS



COPY Array_1, Array_2

Copies a character string to another array. Can be indexed.




FIND_CHAR 'c', Array

Searches a character string until the specified character is located.


END Optional for compatability. Ignored by the compiler.



AND, XOR, OR Masking operations

Usage: AND variable,mask. Mask is hex constant, register, memory.




SHIFT Shift a variable, left or right.

Usage: SHIFT VARIABLE [,nbits]

Shifts the variable the number of bits specified. If nbits absent, shift
the variable one bit right. Otherwise you must specify the number of
shifts. If nbits is preceded by a minus sign, shift is to the left.

Example: shift 'number' one bit right.
SHIFT NUMBER

nother: shift 'number' 3 bits left.
SHIFT NUMBER,-3

If you wish to shift only one bit left, it can be more efficiently
done by adding the number to itself. It accomplishes the same result.

Example: ibuf=ibuf+ibuf

or better yet: ax=ibuf
add ibuf,ax



6-2

MISCELLANEOUS INTRINSIC FUNCTIONS




PARSE STRING, KEY [, 'delims']

Given the ascii STRING, isolate the first token. Copy the isolated token
to KEY and shift STRING left to remove the token KEY. Delimiters are
blank, comma or equals. Carry is set if no data available to parse (EOR).

You can specify an additional list of delimiters to be used.

Example: Consider the string 'now is the-time'

parse string,keword,'(/-+'

After the parse, keword will be 'now'
string will be 'is the-time'

carry is not set.


PARSE_ONLY String, Keword, 'char'

Parse until a specific character is found. We ignore the standard
delimiters. In fact, the standard delimiters (including blanks) are
passed to the 'keword' array.

Example: As above, the string 'now is the-time'

parse_only string, keword,'-'

After the parse, keword will be 'now is the'
string will be 'time'



LDA Load address to a register: LDA VARIABLE, REG


UPCASE Convert a character string to upper case.

Usage: UPCASE String



6-3
SYSTEMS STUFF

Things on this page are of no value to users. They are included here
only for Author's convenience.


LABEL variable, word/byte. Allows alias in system modules. Must be
issued immediately before the data decalaration statement.

PRESET data-type,variable Establish name and type in symbol
table for external variable. data type is byte/word.

SETFORM 'c' Change default character in format name. Normally
fmt_nnn. Changes the 't'. Sample: fma_001.

SETIF 'c' Change default character in if-labels. Normally
true_000. Changes first '0'. Sample: true_a01.

Example of the above two. SETFORM a| SETIF a



7-1

Greater speed can be realized by using a ramdisk. To take advantage
of this feature, include in your autoexec.bat file the following:

SET RAMDISK=d

Where 'd' is your ramdisk drive. i.e. SET RAMDISK=E



In the batch files, notice the commands SET BATCH=TRUE and
SET BATCH=.

These two commands are used by the compiler to determine the course
or action when the requested source file cannot be found. They are of
no concern for normal operations and should not be disturbed.




8-1
KNOWN BUGS

I am aware of the following bugs. If I take time to correct them
now, I may not get this system on the boards before I move to Wyoming.
They will be addressed in the next update.


1. If you re-define a variable, you get no error message but all
sorts of seemingly unrelated problems.


2. if(inbuf.eq.';') SBM.ASM(get_record)
Input takes the ';' as begin comment, thereby truncating the statement.