home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
MBUG
/
MBUG066.ARC
/
PPC.DOC
< prev
next >
Wrap
Text File
|
1979-12-31
|
10KB
|
223 lines
PPC Users Manual
How to use the compiler
=======================
If you have a file named dog.pas and you want to compile it, you'd
just type
submit pc dog
The compiler will ask "LISTING?". You reply with a single character;
carriage return means no listing, any other character means yes listing.
The listing will be sent to the console as the compilation proceeds.
Any errors detected in the compilation are flagged in this listing.
At some point (hopefully reasonably near to the point of infraction)
the error number will be inserted into the listing, enclosed in ">>"
and "<<". The line following an error will start with "********"
and otherwise be blank to call attention to the error. The compiler
will also wait for a single character from the console before
compilation continues. This is so people with crt's can see the
error. Error numbers should be looked up in Jensen and Wirth (see
below). Error number 99 is pound sign ("#") expected.
The compiler should work with a 32k CP/M and might work in 24k, but
there are no memory overflow checks. If it hangs or something, you
probably don't have enough memory.
On good sized programs, the compiler manages to get about 300-400
lines of Pascal translated to object per minute. These figures were
taken on my system with 2mHz Z-80, 8" disk, running under SPEED.
Compilation speed will fall to less than half this rate without SPEED,
thus SPEED is strongly recommended. This is particularly true if
you use the submit file to do the compilation. The run time package
does only single sector disk buffering and this too makes SPEED
very important.
How it all works
================
The program PPC.COM takes your Pascal source and makes a single pass
over it translating it to a sort of p-code as it goes. This p-code is
written to disk. PFET.COM reads the p-code file on its first pass,
assigning 8080 addresses to all p-code labels and storing the p-code
in memory for the second pass. On its second pass, PFET reads the
p-code from memory and generates the actual 8080 object code. This
code is written to a disk file. The last step in compilation is to
link the generated object code to the run time package. This is done
by simply using PIP to concatenate the run time package and the object
file from PFET to produce an executable .COM file. The compiler (PPC)
is written in Pascal, as is the p-code translator (PFET). The run time
package is written in assembler.
Differences from "standard" Pascal
==================================
This section will detail the ways in which ppc deviates from standard
Pascal as defined in "Pascal User Manual and Report", second ed., K.
Jensen and N. Wirth.
Two additional reserved words have been defined: get and put.
The following words are not now considered reserved, but are
in standard Pascal, so they should be avoided: file, goto, in, label,
nil, packed, set, and with.
The ASCII tab character is an acceptable white space character.
Comments are begun with the sequence "(*" and ended with "*)".
Identifiers may be very long, but only the first 8 are significant.
The data type Boolean is not supported. Relational and logical
operators may be used only in if statements. The boolean constant
identifiers true and false are not defined. The not operator is
not implemented. These are the legal relational and logical
operators: =, <>, <, <=, >=, >, and, and or.
The data type integer is available. Values must be in the range -32768 to
32767. There are no standard functions such as abs, sqr, trunc, etc.
The constant maxint is not defined by the compiler. The type integer is
identical to type word. The following operations are defined on integers:
* multiply
/ divide and truncate (why use div? int's are all you've got!)
+ add
- subtract
Multiplication and division are presently implemented with repeated
addition and subtraction (gag!). This makes the order of the operands
critical. If one operand is likely to be less than the other, put the
lesser operand on the left of the multiplication symbol for best speed.
Dividing a large number by one takes a long time -- dividing it by zero
takes forever! (It's not that I'm not aware of the shiftng methods
of division and multiplication, it's just that I wanted something quick
and didn't feel like looking up the good routines. I've never felt
the need to replace these routines with the good ones.)
Also note that there is no integer negation. If you want negative one,
write it as 0-1.
The type real is not supported.
The type char is not supported, but see type alfa below.
The type alfa can hold eight characterers. Alfas can be assigned and
compared just like integers (just don't try to do math on them!).
All relational operators are defined using the ASCII collating sequence.
Length can't enter into the compariosn because alfas are always eight
characters long (it's up to you to supply padding). Alfas may be passed
as parameters.
Since files are not supported, the program heading is not needed, and
in fact, is not allowed. The first thing the compiler expects to see
are the global constant declarations.
Goto statements are not supported, therefore label declarations are not
needed and not permitted.
Constant declarations are pretty much the same as in regular Pascal,
except that leading signs are not allowed and character constants
can be only one character in length. A minor extension is that I put
in limited compile time constant expressions to make coding the
translator easier. See the syntax graphs to see where these can be
used.
Variable declarations have the restriction that the type must be
a type identifier and may not be a complex type. Thus
var months : array [ 1 .. 12 ] of integer;
is illegal, while
type mtharray = array [ 1 .. 12 ] of integer;
var months : mtharray;
is legal.
In this implementation, functions can return only integer values.
This makes it unnecessary (and illegal) to give a function return type
in the function declaration.
The case statement is limited in that it cannot accept multiple case
labels on the same statement. On the other hand, it has been extended
to allow an else statement which is executed when none of the case
labels match the expression value. See the syntax graphs for the syntax.
Single dimensional arrays of integers and alfas (the two "built-in" types)
are allowed. You can also declare arrays of subrange or enumerated types,
but these are treated as arrays of integers and take the same amount of
storage. Of course, arrays of arrays are not allowed, as that would
be more than one dimension.
If a simple alfa variable appears with a subscript after it, it is
treated as though it were an array of integers. This fact can be used
to get at the individual characters of an alfa variable. For example,
if "a" is a simple (not an array) alfa variable, then a[0] refers to
the first two characters. The least significant eight bits would
contain the first character and the most significant eight bits would
contain the second character.
Record types are not allowed. Therefore, there is no need for a with
statement.
There is no set type. (However, it shouldn't be too hard to implement
a 64-bit set type using the p-instructions already around for alfa
variables . . . ).
There are no pointer types, and consequently, no new function.
There are no files and no read or write statements. All input and
output is done with the put and get statements. These are only vaguely
similar to the standard Pascal put and get. GET#0 gets one character
from the input file. PUT#0 sends its output to the output file. PUT#1
sends its output unconditionally to the console. The arguments to the
put statements consist of a series of expressions separated by commas.
If an expression evaluates to an alfa, all eight characters of the alfa
are printed. Integer expressions followed by a pound sign ('#') will
print the decimal value of the expression. If no pound sign follows
the expression, the low eight bits of the expression are sent as one
character. The input and output files mentioned above can be either
disk files or console input and output. Which is used depends on what
is typed on the command line following the compiled .com file when it
is executed. If the first filename following the .com file name is
blank or '*', then input characters are taken from the console. If
it is the name of a disk file, then input comes from that disk file.
A similar rule applies to the second filename following the command
and the destiny of the output characters.
Var parameters are different in that if one parameter to a procedure
is to be var, then all parameters must be var parameters. This is
a silly restriction that should be easily removed by any talented
compiler hacker. There is a also a small kludge to make the compiler's
job easier; the word var must appear in the call to all procedures
with var parameters, as well as in the declaration. This is very
easy to forget an a real nuisance at times. Somebody please fix.
It is possible to forward declare procedures an functions, but as
with var parameters, there is a minor syntactic kludge to make the
compiler's life easier. The forward part is handled in the normal
way except that you D-O-N-'-T give the parameter list (the compiler
never checks procedure calls against their declarations anyway!).
When you actually want to declare the procedure, use the form
procedure foo(<real parameter list>); backward;
This gives the compiler a hint it can't miss that this procedure
was forward declared earlier!