home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
fortran
/
compiler
/
sbm
/
sbm.ls1
< prev
next >
Wrap
Text File
|
1991-01-10
|
34KB
|
897 lines
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
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
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
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-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-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-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-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-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.
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-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-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-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
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-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.