fixup commit for tag 'distr3'
This commit is contained in:
parent
81b1d21c35
commit
42e84d8dd2
|
@ -1 +0,0 @@
|
|||
exec sh TakeAction distr distr/Action
|
35
Makefile
35
Makefile
|
@ -1,35 +0,0 @@
|
|||
cmp: # compile everything and compare
|
||||
(cd etc ; make cmp )
|
||||
(cd util ; make cmp )
|
||||
(cd lang ; make cmp )
|
||||
(cd mach ; make cmp )
|
||||
|
||||
install: # compile everything to machine code
|
||||
(cd etc ; make install )
|
||||
(cd util ; make install )
|
||||
(cd lang/cem ; make install )
|
||||
(cd mach ; make install )
|
||||
(cd lang/pc ; make install )
|
||||
|
||||
clean: # remove all non-sources, except boot-files
|
||||
(cd doc ; make clean )
|
||||
(cd man ; make clean )
|
||||
(cd h ; make clean )
|
||||
(cd etc ; make clean )
|
||||
(cd util ; make clean )
|
||||
(cd lang ; make clean )
|
||||
(cd mach ; make clean )
|
||||
|
||||
opr: # print all sources
|
||||
make pr | opr
|
||||
|
||||
pr: # print all sources
|
||||
@( pr Makefile ; \
|
||||
(cd doc ; make pr ) ; \
|
||||
(cd man ; make pr ) ; \
|
||||
(cd h ; make pr ) ; \
|
||||
(cd etc ; make pr ) ; \
|
||||
(cd lang ; make pr ) ; \
|
||||
(cd util ; make pr ) ; \
|
||||
(cd mach ; make pr ) \
|
||||
)
|
12
distr/Action
12
distr/Action
|
@ -1,12 +0,0 @@
|
|||
name "Installation manual"
|
||||
dir doc
|
||||
end
|
||||
name "Pascal bootstrap files"
|
||||
dir lang/pc/pem
|
||||
end
|
||||
name "LLgen bootstrap files"
|
||||
dir util/LLgen
|
||||
end
|
||||
name "ego share pop_push file"
|
||||
dir util/ego/share
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
name "m68k2/cg bootstrap files"
|
||||
dir mach/m68k2/cg
|
||||
end
|
||||
name "vax4/cg bootstrap files"
|
||||
dir mach/vax4/cg
|
||||
end
|
||||
name "m68020/ncg bootstrap files"
|
||||
dir mach/m68020/ncg
|
||||
end
|
|
@ -1,26 +0,0 @@
|
|||
-- ./doc/install.pr no RCS file
|
||||
-- ./h/em_mnem.h no RCS file
|
||||
-- ./h/em_pseu.h no RCS file
|
||||
-- ./h/em_spec.h no RCS file
|
||||
-- ./lang/basic/src/y.tab.c no RCS file
|
||||
-- ./lang/basic/src/y.tab.h no RCS file
|
||||
-- ./lang/pc/pem/pem22.m no RCS file
|
||||
-- ./lang/pc/pem/pem24.m no RCS file
|
||||
-- ./lang/pc/pem/pem44.m no RCS file
|
||||
-- ./lib/LLgen/incl no RCS file
|
||||
-- ./lib/LLgen/rec no RCS file
|
||||
-- ./mach/m68k2/cg/tables1.c no RCS file
|
||||
-- ./mach/m68k2/cg/tables1.h no RCS file
|
||||
-- ./mach/m68020/ncg/tables1.c no RCS file
|
||||
-- ./mach/m68020/ncg/tables1.h no RCS file
|
||||
-- ./mach/vax4/cg/tables1.c no RCS file
|
||||
-- ./mach/vax4/cg/tables1.h no RCS file
|
||||
-- ./util/LLgen/src/parser no RCS file
|
||||
-- ./util/LLgen/src/LLgen.c no RCS file
|
||||
-- ./util/LLgen/src/Lpars.c no RCS file
|
||||
-- ./util/LLgen/src/Lpars.h no RCS file
|
||||
-- ./util/LLgen/src/tokens.c no RCS file
|
||||
-- ./util/data/em_flag.c no RCS file
|
||||
-- ./util/data/em_mnem.c no RCS file
|
||||
-- ./util/data/em_pseu.c no RCS file
|
||||
-- ./util/ego/share/pop_push.h no RCS file
|
74
distr/How_To
74
distr/How_To
|
@ -1,74 +0,0 @@
|
|||
How to make a fresh distribution:
|
||||
For a distribution you need ".distr" files and RCS files.
|
||||
The EM home directory contains a file called ".distr". It contains
|
||||
the names of all the files and directories you want to have in the distribution.
|
||||
The directories should contain .distr files, the other files should
|
||||
be placed under RCS.
|
||||
The current RCS revision name is "distr3".
|
||||
The are files that derive from other files and yet should be placed
|
||||
in the distribution.
|
||||
These files should not be placed under RCS.
|
||||
The file "Exceptions" in this directory contains the current list of
|
||||
these files.
|
||||
|
||||
When all this is correct, use the shell script mktree the extract
|
||||
the distribution from the EM tree.
|
||||
cd /usr/em ; sh distr/mktree destination_tree >distr/f.attf 2>&1
|
||||
Make sure that the destination tree exists and is empty!
|
||||
Failing to do that will almost certainly result in a welter of
|
||||
error messages.
|
||||
The file f.attf contains mktree error messages and should be compared
|
||||
to Exceptions.
|
||||
The actions of mktree are quite complicated. It starts in the current
|
||||
directory reading the ".distr" file, after copying that file to the
|
||||
destination tree.
|
||||
For each file mentioned there it performes certain actions:
|
||||
1- Directory Change to that directory and call yourself recursively.
|
||||
2- File
|
||||
a- Try to do "co -rdistr3 destination_tree/path/destination_file"
|
||||
on succes "chmod +w destination_file"
|
||||
else
|
||||
b- Try to do "co destination_tree/destination_file"
|
||||
on succes "chmod +w destination_file" and
|
||||
give message that says "Missing distr3 entry" (or some such).
|
||||
else
|
||||
c- I Does a file LIST exist in this directory AND
|
||||
is the first line of LIST equal to the name of the
|
||||
destination file? If so, try to extract all the files
|
||||
named in the rest of the LIST file and call the program
|
||||
arch to create a library "arch cr `cat LIST`".
|
||||
In this manner libraries can be distributed whose members
|
||||
have their own RCS file!
|
||||
else
|
||||
II try to do "cp file destination_tree/path/destination_file"
|
||||
on succes give message that says "Missing RCS entry"
|
||||
(or some such).
|
||||
else
|
||||
d-
|
||||
give message that says "Missing entry" (or some such).
|
||||
|
||||
Now you have the tree but not everything is kosher yet.
|
||||
Some files derive from other files in the tree, those derivations should
|
||||
be done with the use of an already installed distribution.
|
||||
The files Action and Action1 in this directory contain the actions
|
||||
we now take. (Confession: most of the time we use /usr/em)
|
||||
|
||||
After running these re-derivation programs the distrubtion tree starts
|
||||
to look like the tree you need.
|
||||
There are too many files there though, especially the files created by
|
||||
the derivation process.
|
||||
That is why we now give the command:
|
||||
dtar cdf distr3 .
|
||||
The file distr3 is the one you should put on tape!
|
||||
But,.... before doing that: Try it out!
|
||||
Repeat the process described in the installation manual.
|
||||
Only if that succeeds you are sure that you included the files needed,
|
||||
and gave all other files the correct "distr3" RCS id.
|
||||
After you sent the tape away, forbid ANYBODY to touch the distr3 id
|
||||
in your RCS files.
|
||||
Good Luck,
|
||||
Ed Keizer, 85/4/15.
|
||||
|
||||
Updated for 3rd distribution by Ceriel Jacobs, 87/3/11.
|
||||
And again,
|
||||
Good Luck!
|
25
distr/dwalk
25
distr/dwalk
|
@ -1,25 +0,0 @@
|
|||
: ${CDIR=.}
|
||||
if test ! -r .distr
|
||||
then
|
||||
echo ++ no .distr in $CDIR
|
||||
exit 0
|
||||
fi
|
||||
${DS-:} $CDIR
|
||||
for i in `cat .distr`
|
||||
do
|
||||
if test -d $i
|
||||
then
|
||||
( if cd $i
|
||||
then
|
||||
${DD-:} $CDIR $i
|
||||
CDIR=$CDIR/$i
|
||||
export CDIR
|
||||
exec /usr/em/distr/dwalk
|
||||
else
|
||||
echo ++ Could not access $CDIR/$i
|
||||
fi
|
||||
)
|
||||
else
|
||||
${DF-:} $CDIR $i
|
||||
fi
|
||||
done
|
|
@ -1 +0,0 @@
|
|||
echo $1/$2
|
42
distr/f.attf
42
distr/f.attf
|
@ -1,42 +0,0 @@
|
|||
-- ./bin/em.pascal no RCS file
|
||||
-- ./doc/em.doc/doc.pr no RCS file
|
||||
-- ./doc/install.pr no RCS file
|
||||
-- ./h/em_mnem.h no RCS file
|
||||
-- ./h/em_pseu.h no RCS file
|
||||
-- ./h/em_spec.h no RCS file
|
||||
-- ./lang/basic/src/y.tab.c no RCS file
|
||||
-- ./lang/basic/src/y.tab.h no RCS file
|
||||
-- ./lang/pc/pem/pem22.m no RCS file
|
||||
-- ./lang/pc/pem/pem24.m no RCS file
|
||||
-- ./lib/LLgen/incl no RCS file
|
||||
-- ./lib/LLgen/rec no RCS file
|
||||
-- ./lib/ix/head_em no RCS file
|
||||
-- ./lib/ix/head_i no RCS file
|
||||
-- ./lib/ix/tail_em no RCS file
|
||||
-- ./lib/ix/tail_em.vend no RCS file
|
||||
-- ./lib/ix/tail_mon no RCS file
|
||||
-- ./mach/6500/libem/tail_em.ve.s.a no RCS file
|
||||
-- ./mach/vax2/cg/tables1.c no RCS file
|
||||
-- ./mach/vax2/cg/tables1.h no RCS file
|
||||
-- ./mach/vax4/cg/tables1.c no RCS file
|
||||
-- ./mach/vax4/cg/tables1.h no RCS file
|
||||
-- ./mach/z80/int/libpc/pc_tail.c.a no RCS file
|
||||
-- ./mkun/pubmac no distr2 yet
|
||||
-- ./mkun/tmac.q no distr2 yet
|
||||
-- ./mkun/tmac.q1 no distr2 yet
|
||||
-- ./mkun/tmac.q2 no distr2 yet
|
||||
-- ./mkun/tmac.q3 no distr2 yet
|
||||
-- ./mkun/tmac.q4 no distr2 yet
|
||||
-- ./mkun/tmac.q5 no distr2 yet
|
||||
-- ./mkun/tmac.q6 no distr2 yet
|
||||
-- ./mkun/tmac.q7 no distr2 yet
|
||||
-- ./mkun/tmac.q8 no distr2 yet
|
||||
-- ./util/LLgen/src/parser no RCS file
|
||||
-- ./util/LLgen/src/LLgen.c no RCS file
|
||||
-- ./util/LLgen/src/Lpars.c no RCS file
|
||||
-- ./util/LLgen/src/Lpars.h no RCS file
|
||||
-- ./util/LLgen/src/tokens.c no RCS file
|
||||
-- ./util/data/em_flag.c no RCS file
|
||||
-- ./util/data/em_mnem.c no RCS file
|
||||
-- ./util/data/em_pseu.c no RCS file
|
||||
-- ./util/data/em_ptyp.c no RCS file
|
|
@ -1,10 +0,0 @@
|
|||
case $# in
|
||||
0) DIR=. ;;
|
||||
1) DIR=$1 ;;
|
||||
*) echo $0 [directory] ; exit 1 ;;
|
||||
esac
|
||||
DD=`pwd`/listall.d
|
||||
DW=`pwd`/dwalk
|
||||
export DD
|
||||
cd $DIR
|
||||
$DW
|
|
@ -1,2 +0,0 @@
|
|||
echo "<$1/$2>"
|
||||
ls -bCdx `cat .distr`
|
|
@ -1,10 +0,0 @@
|
|||
case $# in
|
||||
0) DIR=. ;;
|
||||
1) DIR=$1 ;;
|
||||
*) echo $0 [directory] ; exit 1 ;;
|
||||
esac
|
||||
DD=`pwd`/echod
|
||||
DW=`pwd`/dwalk
|
||||
export DD
|
||||
cd $DIR
|
||||
$DW
|
|
@ -1,9 +0,0 @@
|
|||
set -e
|
||||
for i in `tail +2 $DESTDIR/$1/LIST`
|
||||
do
|
||||
${DF-false} $1 $i
|
||||
done
|
||||
cd $DESTDIR/$1
|
||||
arch cr `cat LIST`
|
||||
: I do not remove the files constituating the library, because
|
||||
: they might be present in .distr
|
23
distr/mkf
23
distr/mkf
|
@ -1,23 +0,0 @@
|
|||
if co -q -rdistr3 $DESTDIR/$1/$2 >/dev/null 2>&1
|
||||
then
|
||||
chmod +w $DESTDIR/$1/$2
|
||||
elif co -q $DESTDIR/$1/$2 >/dev/null 2>&1
|
||||
then
|
||||
chmod +w $DESTDIR/$1/$2
|
||||
echo -- $1/$2 no distr3 yet
|
||||
elif grep LIST .distr >/dev/null 2>&1 &&
|
||||
(test "$2" = "`head -1 $DESTDIR/$1/LIST`") >/dev/null 2>&1 &&
|
||||
${DA-false} "$1" "$2"
|
||||
then
|
||||
: Fetched library contents one by one and put them together
|
||||
elif cp $2 $DESTDIR/$1/$2 >/dev/null 2>&1
|
||||
then
|
||||
echo -- $1/$2 no RCS file
|
||||
else
|
||||
echo ++ $1/$2 not present
|
||||
fi
|
||||
case $2 in
|
||||
LIST) if (test -r $DESTDIR/$1/`head -1 $DESTDIR/$1/LIST`) >/dev/null 2>&1
|
||||
then echo ++ LIST files must be in .distr before their libraries!!!
|
||||
fi ;;
|
||||
esac
|
15
distr/mktree
15
distr/mktree
|
@ -1,15 +0,0 @@
|
|||
case $# in
|
||||
1) ;;
|
||||
*) echo $0 directory ; exit 1 ;;
|
||||
esac
|
||||
DDIR=/usr/em/distr
|
||||
case $1 in
|
||||
/*) DESTDIR=$1 ;;
|
||||
*) DESTDIR=`pwd`/$1 ;;
|
||||
esac
|
||||
DS=$DDIR/mks
|
||||
DD=$DDIR/mkd
|
||||
DF=$DDIR/mkf
|
||||
DA=$DDIR/mka
|
||||
export DESTDIR DS DD DF DA
|
||||
$DDIR/dwalk
|
|
@ -1,26 +0,0 @@
|
|||
REV=
|
||||
FILE=
|
||||
while :
|
||||
do
|
||||
case $# in
|
||||
0) break ;;
|
||||
esac
|
||||
ARG="$1"
|
||||
shift
|
||||
case "$ARG" in
|
||||
-r*) REV=`echo "$ARG"| sed s/-r//` ;;
|
||||
-*) FLAGS="$FLAGS $ARG" ;;
|
||||
*) case x$FILE in
|
||||
x) FILE="$ARG" ;;
|
||||
*) echo todistr can only be done on one file at the time
|
||||
exit 1 ;;
|
||||
esac
|
||||
esac
|
||||
done
|
||||
case x$REV in
|
||||
x) REV=`rlog -h "$FILE"|sed -n -e '/head/s/^head:[ ]*//p'` ;;
|
||||
esac
|
||||
case x$REV in
|
||||
x) exit 2 ;;
|
||||
esac
|
||||
rcs -ndistr3:$REV $FLAGS $FILE
|
323
doc/cref.doc
323
doc/cref.doc
|
@ -1,323 +0,0 @@
|
|||
.\" $Header$
|
||||
.nr ID 4
|
||||
.de hd
|
||||
'sp 2
|
||||
'tl ''-%-''
|
||||
'sp 3
|
||||
..
|
||||
.de fo
|
||||
'bp
|
||||
..
|
||||
.tr ~
|
||||
. TITLE
|
||||
.de TL
|
||||
.sp 15
|
||||
.ce
|
||||
\\fB\\$1\\fR
|
||||
..
|
||||
. AUTHOR
|
||||
.de AU
|
||||
.sp 15
|
||||
.ce
|
||||
by
|
||||
.sp 2
|
||||
.ce
|
||||
\\$1
|
||||
..
|
||||
. DATE
|
||||
.de DA
|
||||
.sp 3
|
||||
.ce
|
||||
( Dated \\$1 )
|
||||
..
|
||||
. INSTITUTE
|
||||
.de VU
|
||||
.sp 3
|
||||
.ce 4
|
||||
Wiskundig Seminarium
|
||||
Vrije Universteit
|
||||
De Boelelaan 1081
|
||||
Amsterdam
|
||||
..
|
||||
. PARAGRAPH
|
||||
.de PP
|
||||
.sp
|
||||
.ti +\n(ID
|
||||
..
|
||||
.nr CH 0 1
|
||||
. CHAPTER
|
||||
.de CH
|
||||
.nr SH 0 1
|
||||
.bp
|
||||
.in 0
|
||||
\\fB\\n+(CH.~\\$1\\fR
|
||||
.PP
|
||||
..
|
||||
. SUBCHAPTER
|
||||
.de SH
|
||||
.sp 3
|
||||
.in 0
|
||||
\\fB\\n(CH.\\n+(SH.~\\$1\\fR
|
||||
.PP
|
||||
..
|
||||
. INDENT START
|
||||
.de IS
|
||||
.sp
|
||||
.in +\n(ID
|
||||
..
|
||||
. INDENT END
|
||||
.de IE
|
||||
.in -\n(ID
|
||||
.sp
|
||||
..
|
||||
.de PT
|
||||
.ti -\n(ID
|
||||
.ta \n(ID
|
||||
.fc " @
|
||||
"\\$1@"\c
|
||||
.fc
|
||||
..
|
||||
. DOUBLE INDENT START
|
||||
.de DS
|
||||
.sp
|
||||
.in +\n(ID
|
||||
.ll -\n(ID
|
||||
..
|
||||
. DOUBLE INDENT END
|
||||
.de DE
|
||||
.ll +\n(ID
|
||||
.in -\n(ID
|
||||
.sp
|
||||
..
|
||||
. EQUATION START
|
||||
.de EQ
|
||||
.sp
|
||||
.nf
|
||||
..
|
||||
. EQUATION END
|
||||
.de EN
|
||||
.fi
|
||||
.sp
|
||||
..
|
||||
. ITEM
|
||||
.de IT
|
||||
.sp
|
||||
.in 0
|
||||
\\fB~\\$1\\fR
|
||||
.ti +5
|
||||
..
|
||||
.de CS
|
||||
.br
|
||||
~-~\\
|
||||
..
|
||||
.br
|
||||
.fi
|
||||
.TL "Ack-C reference manual"
|
||||
.AU "Ed Keizer"
|
||||
.DA "September 12, 1983"
|
||||
.VU
|
||||
.wh 0 hd
|
||||
.wh 60 fo
|
||||
.CH "Introduction"
|
||||
The C frontend included in the Amsterdam Compiler Kit
|
||||
translates UNIX-V7 C into compact EM code [1].
|
||||
The language accepted is described in [2] and [3].
|
||||
This document describes which implementation dependent choices were
|
||||
made in the Ack-C frontend and
|
||||
some restrictions and additions.
|
||||
.CH "The language"
|
||||
.PP
|
||||
Under the same heading as used in [2] we describe the
|
||||
properties of the Ack-C frontend.
|
||||
.IT "2.2 Identifiers"
|
||||
External identifiers are unique up to 7 characters and allow
|
||||
both upper and lower case.
|
||||
.IT "2.3 Keywords"
|
||||
The word \fBvoid\fP is also reserved as a keyword.
|
||||
.IT "2.4.3 Character constants"
|
||||
The ASCII-mapping is used when a character is converted to an
|
||||
integer.
|
||||
.IT "2.4.4 Floating constants"
|
||||
To prevent loss of precision the compiler does not perform
|
||||
floating point constant folding.
|
||||
.IT "2.6 Hardware characteristics"
|
||||
The size of objects of the several arithmetic types and
|
||||
pointers depend on the EM-implementation used.
|
||||
The ranges of the arithmetic types depend on the size used,
|
||||
the C-frontend assumes two's complement representation for the
|
||||
integral types.
|
||||
All sizes are multiples of bytes.
|
||||
The calling program \fIack\fP[4] passes information about the
|
||||
size of the types to the compiler proper.
|
||||
.br
|
||||
However, a few general remarks must be made:
|
||||
.sp 1
|
||||
.IS
|
||||
.PT (a)
|
||||
The size of pointers is a multiple of
|
||||
(or equal to) the size of an \fIint\fP.
|
||||
.PT (b)
|
||||
The following relations exist for the sizes of the types
|
||||
mentioned:
|
||||
.br
|
||||
.ti +5
|
||||
\fIchar<=short<=int<=long\fP
|
||||
.PT (c)
|
||||
Objects of type \fIchar\fP use one 8-bit byte of storage,
|
||||
although several bytes are allocated sometimes.
|
||||
.PT (d)
|
||||
All sizes are in multiples of bytes.
|
||||
.PT (e)
|
||||
Most EM implementations use 4 bytes for floats and 8 bytes
|
||||
for doubles, but exceptions to this rule occur.
|
||||
.IE
|
||||
.IT "4 What's in a name"
|
||||
The type \fIvoid\fP is added.
|
||||
Objects of type void do not exist.
|
||||
Functions declared as returning void, do not return a value at all.
|
||||
.IT "6.1 Characters and integers"
|
||||
Objects of type \fIchar\fP are unsigned and do not cause
|
||||
sign-extension when converted to \fIint\fP.
|
||||
The range of characters values is from 0 to 255.
|
||||
.IT "6.3 Floating and integral"
|
||||
Floating point numbers are truncated towards zero when
|
||||
converted to the integral types.
|
||||
.IT "6.4 Pointers and integers"
|
||||
When a \fIlong\fP is added to or subtracted from a pointer and
|
||||
longs are larger then pointers the \fIlong\fP is converted to an
|
||||
\fIint\fP before the operation is performed.
|
||||
.IT "7.2 Unary operators"
|
||||
It is allowed to cast any expression to the type \fIvoid\fP.
|
||||
.IT "8.2 Type specifiers"
|
||||
One type is added to the type-specifiers:
|
||||
.br
|
||||
.IS
|
||||
void
|
||||
.IE
|
||||
.IT "8.5 Structure and union declarations"
|
||||
The only type allowed for fields is \fIint\fP.
|
||||
Fields with exactly the size of \fIint\fP are signed,
|
||||
all other fields are unsigned.
|
||||
.br
|
||||
The size of any single structure must be less then 4096 bytes.
|
||||
.IT "8.6 Initialization"
|
||||
Initialization of structures containing bit fields is not
|
||||
allowed.
|
||||
There is one restriction when using an 'address expression' to initialize
|
||||
an integral variable.
|
||||
The integral variable must have the same size as a pointer.
|
||||
Conversions altering the size of the address expression are not allowed.
|
||||
.IT "9.10 Return statement"
|
||||
Return statements of the form:
|
||||
.IS
|
||||
return ;
|
||||
.IE
|
||||
are the only form of return statement allowed in a function of type
|
||||
function returning void.
|
||||
.IT "10.1 External function definitions"
|
||||
The total amount for storage used for parameters
|
||||
in any function must be less then 4096 bytes.
|
||||
The same holds for the total amount of storage occupied by the
|
||||
automatic variables declared inside any function.
|
||||
.sp
|
||||
Using formal parameters whose size is smaller the the size of an int
|
||||
is less efficient on several machines.
|
||||
At procedure entry these parameters are converted from integer to the
|
||||
declared type, because the compiler doesn't know where the least
|
||||
significant bytes are stored in the int.
|
||||
.IT "11.2 Scope of externals"
|
||||
Most C compilers are rather lax in enforcing the restriction
|
||||
that only one external definition without the keyword
|
||||
\fIextern\fP is allowed in a program.
|
||||
The Ack-C frontend is very strict in this.
|
||||
The only exception is that declarations of arrays with a
|
||||
missing first array bounds expression are regarded to have an
|
||||
explicit keyword \fIextern\fP.
|
||||
.IT "14.4 Explicit pointer conversions"
|
||||
Pointers may be larger the ints, thus assigning a pointer to an
|
||||
int and back will not always result in the same pointer.
|
||||
The process mentioned above works with integrals
|
||||
of the same size or larger as pointers in all EM implementations
|
||||
having such integrals.
|
||||
When converting pointers to an integral type or vice-versa,
|
||||
the pointers is seen as an unsigned int.
|
||||
.br
|
||||
EM guarantees that any object can be placed at a word boundary,
|
||||
this allows the C-programs to use \fIint\fP pointers
|
||||
as pointers to objects of any type not smaller than an \fIint\fP.
|
||||
.CH "Frontend options"
|
||||
The C-frontend has a few options, these are controlled
|
||||
by flags:
|
||||
.IS
|
||||
.PT -V
|
||||
This flag is followed by a sequence of letters each followed by
|
||||
positive integers. Each letter indicates a
|
||||
certain type, the integer following it specifies the size of
|
||||
objects of that type. One letter indicates the wordsize used.
|
||||
.IS
|
||||
.sp 1
|
||||
.TS
|
||||
center tab(:);
|
||||
l l16 l l.
|
||||
letter:type:letter:type
|
||||
|
||||
w:wordsize:i:int
|
||||
s:short:l:long
|
||||
f:float:d:double
|
||||
p:pointer::
|
||||
.TE
|
||||
.sp 1
|
||||
All existing implementations use an integer size equal to the
|
||||
wordsize.
|
||||
.IE
|
||||
The calling program \fIack\fP[4] provides the frontend with
|
||||
this flag, with values depending on the machine used.
|
||||
.sp 1
|
||||
.PT -l
|
||||
The frontend normally generates code to keep track of the line
|
||||
number and source file name at runtime for debugging purposes.
|
||||
Currently a pointer to a
|
||||
string containing the filename is stored at a fixed place in
|
||||
memory at each function
|
||||
entry and the line number at the start of every expression.
|
||||
At the return from a function these memory locations are not reset to
|
||||
the values they had before the call.
|
||||
Most library routines do not use this feature and thus do not
|
||||
ruin the current line number and filename when called.
|
||||
However, you are really unlucky when your program crashes due
|
||||
to a bug in such a library function, because the line number
|
||||
and filename do not indicate that something went wrong inside
|
||||
the library function.
|
||||
.br
|
||||
Providing the flag -l to the frontend tells it not to generate
|
||||
the code updating line number and file name.
|
||||
This is, for example, used when translating the stdio library.
|
||||
.br
|
||||
When the \fIack\fP[4] is called with the -L flag it provides
|
||||
the frontend with this flag.
|
||||
.sp 1
|
||||
.PT -Xp
|
||||
When this flag is present the frontend generates a call to
|
||||
the function \fBprocentry\fP at each function entry and a
|
||||
call to \fBprocexit\fP at each function exit.
|
||||
Both functions are provided with one parameter,
|
||||
a pointer to a string containing the function name.
|
||||
.br
|
||||
When \fIack\fP is called with the -p flag it provides the
|
||||
frontend with this flag.
|
||||
.IE
|
||||
.CH References
|
||||
.IS
|
||||
.PT [1]
|
||||
A.S. Tanenbaum, Hans van Staveren, Ed Keizer and Johan
|
||||
Stevenson \fIDescription of a machine architecture for use with
|
||||
block structured languages\fP Informatica report IR-81.
|
||||
.sp 1
|
||||
.PT [2]
|
||||
B.W. Kernighan and D.M. Ritchie, \fIThe C Programming
|
||||
language\fP, Prentice-Hall, 1978
|
||||
.PT [3]
|
||||
D.M. Ritchie, \fIC Reference Manual\fP
|
||||
.sp
|
||||
.PT [4]
|
||||
UNIX manual ack(I).
|
488
doc/em/app.nr
488
doc/em/app.nr
|
@ -1,488 +0,0 @@
|
|||
.BP
|
||||
.AP "EM INTERPRETER"
|
||||
.nf
|
||||
.ta 8 16 24 32 40 48 56 64 72 80
|
||||
.so em.i
|
||||
.fi
|
||||
.BP
|
||||
.AP "EM CODE TABLES"
|
||||
The following table is used by the assembler for EM machine
|
||||
language.
|
||||
It specifies the opcodes used for each instruction and
|
||||
how arguments are mapped to machine language arguments.
|
||||
The table is presented in three columns,
|
||||
each line in each column contains three or four fields.
|
||||
Each line describes a range of interpreter opcodes by
|
||||
specifying for which instruction the range is used, the type of the
|
||||
opcodes (mini, shortie, etc..) and range for the instruction
|
||||
argument.
|
||||
.A
|
||||
The first field on each line gives the EM instruction mnemonic,
|
||||
the second field gives some flags.
|
||||
If the opcodes are minis or shorties the third field specifies
|
||||
how many minis/shorties are used.
|
||||
The last field gives the number of the (first) interpreter
|
||||
opcode.
|
||||
.N 1
|
||||
Flags :
|
||||
.IS 3
|
||||
.N 1
|
||||
Opcode type, only one of the following may be specified.
|
||||
.PS - 5 " "
|
||||
.PT -
|
||||
opcode without argument
|
||||
.PT m
|
||||
mini
|
||||
.PT s
|
||||
shortie
|
||||
.PT 2
|
||||
opcode with 2-byte signed argument
|
||||
.PT 4
|
||||
opcode with 4-byte signed argument
|
||||
.PT 8
|
||||
opcode with 8-byte signed argument
|
||||
.PE
|
||||
Secondary (escaped) opcodes.
|
||||
.PS - 5 " "
|
||||
.PT e
|
||||
The opcode thus marked is in the secondary opcode group instead
|
||||
of the primary
|
||||
.PE
|
||||
restrictions on arguments
|
||||
.PS - 5 " "
|
||||
.PT N
|
||||
Negative arguments only
|
||||
.PT P
|
||||
Positive and zero arguments only
|
||||
.PE
|
||||
mapping of arguments
|
||||
.PS - 5 " "
|
||||
.PT w
|
||||
argument must be divisible by the wordsize and is divided by the
|
||||
wordsize before use as opcode argument.
|
||||
.PT o
|
||||
argument ( possibly after division ) must be >= 1 and is
|
||||
decremented before use as opcode argument
|
||||
.PE
|
||||
.IE
|
||||
If the opcode type is 2,4 or 8 the resulting argument is used as
|
||||
opcode argument (least significant byte first).
|
||||
.N
|
||||
If the opcode type is mini, the argument is added
|
||||
to the first opcode - if in range - .
|
||||
If the argument is negative, the absolute value minus one is
|
||||
used in the algorithm above.
|
||||
.N
|
||||
For shorties with positive arguments the first opcode is used
|
||||
for arguments in the range 0..255, the second for the range
|
||||
256..511, etc..
|
||||
For shorties with negative arguments the first opcode is used
|
||||
for arguments in the range -1..-256, the second for the range
|
||||
-257..-512, etc..
|
||||
The byte following the opcode contains the least significant
|
||||
byte of the argument.
|
||||
First some examples of these specifications.
|
||||
.PS - 5
|
||||
.PT "aar mwPo 1 34"
|
||||
Indicates that opcode 34 is used as a mini for Positive
|
||||
instruction arguments only.
|
||||
The w and o indicate division and decrementing of the
|
||||
instruction argument.
|
||||
Because the resulting argument must be zero ( only opcode 34 may be used
|
||||
), this mini can only be used for instruction argument 2.
|
||||
Conclusion: opcode 34 is for "AAR 2".
|
||||
.PT "adp sP 1 41"
|
||||
Opcode 41 is used as shortie for ADP with arguments in the range
|
||||
0..255.
|
||||
.PT "bra sN 2 60"
|
||||
Opcode 60 is used as shortie for BRA with arguments -1..-256,
|
||||
61 is used for arguments -257..-512.
|
||||
.PT "zer e- 145"
|
||||
Escaped opcode 145 is used for ZER.
|
||||
.PE
|
||||
The interpreter opcode table:
|
||||
.N 1
|
||||
.IS 3
|
||||
.DS B
|
||||
.so itables
|
||||
.DE 0
|
||||
.IE
|
||||
.P
|
||||
The table above results in the following dispatch tables.
|
||||
Dispatch tables are used by interpreters to jump to the
|
||||
routines implementing the EM instructions, indexed by the next opcode.
|
||||
Each line of the dispatch tables gives the routine names
|
||||
of eight consecutive opcodes, preceded by the first opcode number
|
||||
on that line.
|
||||
Routine names consist of an EM mnemonic followed by a suffix.
|
||||
The suffices show the encoding used for each opcode.
|
||||
.N
|
||||
The following suffices exist:
|
||||
.N 1
|
||||
.VS 1 0
|
||||
.IS 4
|
||||
.PS - 11
|
||||
.PT .z
|
||||
no arguments
|
||||
.PT .l
|
||||
16-bit argument
|
||||
.PT .lw
|
||||
16-bit argument divided by the wordsize
|
||||
.PT .p
|
||||
positive 16-bit argument
|
||||
.PT .pw
|
||||
positive 16-bit argument divided by the wordsize
|
||||
.PT .n
|
||||
negative 16-bit argument
|
||||
.PT .nw
|
||||
negative 16-bit argument divided by the wordsize
|
||||
.PT .s<num>
|
||||
shortie with <num> as high order argument byte
|
||||
.PT .sw<num>
|
||||
shortie with argument divided by the wordsize
|
||||
.PT .<num>
|
||||
mini with <num> as argument
|
||||
.PT .<num>W
|
||||
mini with <num>*wordsize as argument
|
||||
.PE 3
|
||||
<num> is a possibly negative integer.
|
||||
.VS 1 1
|
||||
.IE
|
||||
The dispatch table for the 256 primary opcodes:
|
||||
.DS B
|
||||
0 loc.0 loc.1 loc.2 loc.3 loc.4 loc.5 loc.6 loc.7
|
||||
8 loc.8 loc.9 loc.10 loc.11 loc.12 loc.13 loc.14 loc.15
|
||||
16 loc.16 loc.17 loc.18 loc.19 loc.20 loc.21 loc.22 loc.23
|
||||
24 loc.24 loc.25 loc.26 loc.27 loc.28 loc.29 loc.30 loc.31
|
||||
32 loc.32 loc.33 aar.1W adf.s0 adi.1W adi.2W adp.l adp.1
|
||||
40 adp.2 adp.s0 adp.s-1 ads.1W and.1W asp.1W asp.2W asp.3W
|
||||
48 asp.4W asp.5W asp.w0 beq.l beq.s0 bge.s0 bgt.s0 ble.s0
|
||||
56 blm.s0 blt.s0 bne.s0 bra.l bra.s-1 bra.s-2 bra.s0 bra.s1
|
||||
64 cal.1 cal.2 cal.3 cal.4 cal.5 cal.6 cal.7 cal.8
|
||||
72 cal.9 cal.10 cal.11 cal.12 cal.13 cal.14 cal.15 cal.16
|
||||
80 cal.17 cal.18 cal.19 cal.20 cal.21 cal.22 cal.23 cal.24
|
||||
88 cal.25 cal.26 cal.27 cal.28 cal.s0 cff.z cif.z cii.z
|
||||
96 cmf.s0 cmi.1W cmi.2W cmp.z cms.s0 csa.1W csb.1W dec.z
|
||||
104 dee.w0 del.w-1 dup.1W dvf.s0 dvi.1W fil.l inc.z ine.lw
|
||||
112 ine.w0 inl.-1W inl.-2W inl.-3W inl.w-1 inn.s0 ior.1W ior.s0
|
||||
120 lae.l lae.w0 lae.w1 lae.w2 lae.w3 lae.w4 lae.w5 lae.w6
|
||||
128 lal.p lal.n lal.0 lal.-1 lal.w0 lal.w-1 lal.w-2 lar.W
|
||||
136 ldc.0 lde.lw lde.w0 ldl.0 ldl.w-1 lfr.1W lfr.2W lfr.s0
|
||||
144 lil.w-1 lil.w0 lil.0 lil.1W lin.l lin.s0 lni.z loc.l
|
||||
152 loc.-1 loc.s0 loc.s-1 loe.lw loe.w0 loe.w1 loe.w2 loe.w3
|
||||
160 loe.w4 lof.l lof.1W lof.2W lof.3W lof.4W lof.s0 loi.l
|
||||
168 loi.1 loi.1W loi.2W loi.3W loi.4W loi.s0 lol.pw lol.nw
|
||||
176 lol.0 lol.1W lol.2W lol.3W lol.-1W lol.-2W lol.-3W lol.-4W
|
||||
184 lol.-5W lol.-6W lol.-7W lol.-8W lol.w0 lol.w-1 lxa.1 lxl.1
|
||||
192 lxl.2 mlf.s0 mli.1W mli.2W rck.1W ret.0 ret.1W ret.s0
|
||||
200 rmi.1W sar.1W sbf.s0 sbi.1W sbi.2W sdl.w-1 set.s0 sil.w-1
|
||||
208 sil.w0 sli.1W ste.lw ste.w0 ste.w1 ste.w2 stf.l stf.W
|
||||
216 stf.2W stf.s0 sti.1 sti.1W sti.2W sti.3W sti.4W sti.s0
|
||||
224 stl.pw stl.nw stl.0 stl.1W stl.-1W stl.-2W stl.-3W stl.-4W
|
||||
232 stl.-5W stl.w-1 teq.z tgt.z tlt.z tne.z zeq.l zeq.s0
|
||||
240 zeq.s1 zer.s0 zge.s0 zgt.s0 zle.s0 zlt.s0 zne.s0 zne.s-1
|
||||
248 zre.lw zre.w0 zrl.-1W zrl.-2W zrl.w-1 zrl.nw escape1 escape2
|
||||
.DE 2
|
||||
The list of secondary opcodes (escape1):
|
||||
.N 1
|
||||
.DS B
|
||||
0 aar.l aar.z adf.l adf.z adi.l adi.z ads.l ads.z
|
||||
8 adu.l adu.z and.l and.z asp.lw ass.l ass.z bge.l
|
||||
16 bgt.l ble.l blm.l bls.l bls.z blt.l bne.l cai.z
|
||||
24 cal.l cfi.z cfu.z ciu.z cmf.l cmf.z cmi.l cmi.z
|
||||
32 cms.l cms.z cmu.l cmu.z com.l com.z csa.l csa.z
|
||||
40 csb.l csb.z cuf.z cui.z cuu.z dee.lw del.pw del.nw
|
||||
48 dup.l dus.l dus.z dvf.l dvf.z dvi.l dvi.z dvu.l
|
||||
56 dvu.z fef.l fef.z fif.l fif.z inl.pw inl.nw inn.l
|
||||
64 inn.z ior.l ior.z lar.l lar.z ldc.l ldf.l ldl.pw
|
||||
72 ldl.nw lfr.l lil.pw lil.nw lim.z los.l los.z lor.s0
|
||||
80 lpi.l lxa.l lxl.l mlf.l mlf.z mli.l mli.z mlu.l
|
||||
88 mlu.z mon.z ngf.l ngf.z ngi.l ngi.z nop.z rck.l
|
||||
96 rck.z ret.l rmi.l rmi.z rmu.l rmu.z rol.l rol.z
|
||||
104 ror.l ror.z rtt.z sar.l sar.z sbf.l sbf.z sbi.l
|
||||
112 sbi.z sbs.l sbs.z sbu.l sbu.z sde.l sdf.l sdl.pw
|
||||
120 sdl.nw set.l set.z sig.z sil.pw sil.nw sim.z sli.l
|
||||
128 sli.z slu.l slu.z sri.l sri.z sru.l sru.z sti.l
|
||||
136 sts.l sts.z str.s0 tge.z tle.z trp.z xor.l xor.z
|
||||
144 zer.l zer.z zge.l zgt.l zle.l zlt.l zne.l zrf.l
|
||||
152 zrf.z zrl.pw dch.z exg.s0 exg.l exg.z lpb.z gto.l
|
||||
.DE 2
|
||||
Finally, the list of opcodes with four byte arguments (escape2).
|
||||
.DS
|
||||
|
||||
0 loc
|
||||
.DE 0
|
||||
.BP
|
||||
.AP "AN EXAMPLE PROGRAM"
|
||||
.DS B
|
||||
1 program example(output);
|
||||
2 {This program just demonstrates typical EM code.}
|
||||
3 type rec = record r1: integer; r2:real; r3: boolean end;
|
||||
4 var mi: integer; mx:real; r:rec;
|
||||
5
|
||||
6 function sum(a,b:integer):integer;
|
||||
7 begin
|
||||
8 sum := a + b
|
||||
9 end;
|
||||
10
|
||||
11 procedure test(var r: rec);
|
||||
12 label 1;
|
||||
13 var i,j: integer;
|
||||
14 x,y: real;
|
||||
15 b: boolean;
|
||||
16 c: char;
|
||||
17 a: array[1..100] of integer;
|
||||
18
|
||||
19 begin
|
||||
20 j := 1;
|
||||
21 i := 3 * j + 6;
|
||||
22 x := 4.8;
|
||||
23 y := x/0.5;
|
||||
24 b := true;
|
||||
25 c := 'z';
|
||||
26 for i:= 1 to 100 do a[i] := i * i;
|
||||
27 r.r1 := j+27;
|
||||
28 r.r3 := b;
|
||||
29 r.r2 := x+y;
|
||||
30 i := sum(r.r1, a[j]);
|
||||
31 while i > 0 do begin j := j + r.r1; i := i - 1 end;
|
||||
32 with r do begin r3 := b; r2 := x+y; r1 := 0 end;
|
||||
33 goto 1;
|
||||
34 1: writeln(j, i:6, x:9:3, b)
|
||||
35 end; {test}
|
||||
36 begin {main program}
|
||||
37 mx := 15.96;
|
||||
38 mi := 99;
|
||||
39 test(r)
|
||||
40 end.
|
||||
.DE 0
|
||||
.BP
|
||||
The EM code as produced by the Pascal-VU compiler is given below. Comments
|
||||
have been added manually. Note that this code has already been optimized.
|
||||
.DS B
|
||||
mes 2,2,2 ; wordsize 2, pointersize 2
|
||||
.1
|
||||
rom 't.p\e000' ; the name of the source file
|
||||
hol 552,-32768,0 ; externals and buf occupy 552 bytes
|
||||
exp $sum ; sum can be called from other modules
|
||||
pro $sum,2 ; procedure sum; 2 bytes local storage
|
||||
lin 8 ; code from source line 8
|
||||
ldl 0 ; load two locals ( a and b )
|
||||
adi 2 ; add them
|
||||
ret 2 ; return the result
|
||||
end 2 ; end of procedure ( still two bytes local storage )
|
||||
.2
|
||||
rom 1,99,2 ; descriptor of array a[]
|
||||
exp $test ; the compiler exports all level 0 procedures
|
||||
pro $test,226 ; procedure test, 226 bytes local storage
|
||||
.3
|
||||
rom 4.8F8 ; assemble Floating point 4.8 (8 bytes) in
|
||||
.4 ; global storage
|
||||
rom 0.5F8 ; same for 0.5
|
||||
mes 3,-226,2,2 ; compiler temporary not referenced by address
|
||||
mes 3,-24,2,0 ; the same is true for i, j, b and c in test
|
||||
mes 3,-22,2,0
|
||||
mes 3,-4,2,0
|
||||
mes 3,-2,2,0
|
||||
mes 3,-20,8,0 ; and for x and y
|
||||
mes 3,-12,8,0
|
||||
lin 20 ; maintain source line number
|
||||
loc 1
|
||||
stl -4 ; j := 1
|
||||
lni ; lin 21 prior to optimization
|
||||
lol -4
|
||||
loc 3
|
||||
mli 2
|
||||
loc 6
|
||||
adi 2
|
||||
stl -2 ; i := 3 * j + 6
|
||||
lni ; lin 22 prior to optimization
|
||||
lae .3
|
||||
loi 8
|
||||
lal -12
|
||||
sti 8 ; x := 4.8
|
||||
lni ; lin 23 prior to optimization
|
||||
lal -12
|
||||
loi 8
|
||||
lae .4
|
||||
loi 8
|
||||
dvf 8
|
||||
lal -20
|
||||
sti 8 ; y := x / 0.5
|
||||
lni ; lin 24 prior to optimization
|
||||
loc 1
|
||||
stl -22 ; b := true
|
||||
lni ; lin 25 prior to optimization
|
||||
loc 122
|
||||
stl -24 ; c := 'z'
|
||||
lni ; lin 26 prior to optimization
|
||||
loc 1
|
||||
stl -2 ; for i:= 1
|
||||
2
|
||||
lol -2
|
||||
dup 2
|
||||
mli 2 ; i*i
|
||||
lal -224
|
||||
lol -2
|
||||
lae .2
|
||||
sar 2 ; a[i] :=
|
||||
lol -2
|
||||
loc 100
|
||||
beq *3 ; to 100 do
|
||||
inl -2 ; increment i and loop
|
||||
bra *2
|
||||
3
|
||||
lin 27
|
||||
lol -4
|
||||
loc 27
|
||||
adi 2 ; j + 27
|
||||
sil 0 ; r.r1 :=
|
||||
lni ; lin 28 prior to optimization
|
||||
lol -22 ; b
|
||||
lol 0
|
||||
stf 10 ; r.r3 :=
|
||||
lni ; lin 29 prior to optimization
|
||||
lal -20
|
||||
loi 16
|
||||
adf 8 ; x + y
|
||||
lol 0
|
||||
adp 2
|
||||
sti 8 ; r.r2 :=
|
||||
lni ; lin 23 prior to optimization
|
||||
lal -224
|
||||
lol -4
|
||||
lae .2
|
||||
lar 2 ; a[j]
|
||||
lil 0 ; r.r1
|
||||
cal $sum ; call now
|
||||
asp 4 ; remove parameters from stack
|
||||
lfr 2 ; get function result
|
||||
stl -2 ; i :=
|
||||
4
|
||||
lin 31
|
||||
lol -2
|
||||
zle *5 ; while i > 0 do
|
||||
lol -4
|
||||
lil 0
|
||||
adi 2
|
||||
stl -4 ; j := j + r.r1
|
||||
del -2 ; i := i - 1
|
||||
bra *4 ; loop
|
||||
5
|
||||
lin 32
|
||||
lol 0
|
||||
stl -226 ; make copy of address of r
|
||||
lol -22
|
||||
lol -226
|
||||
stf 10 ; r3 := b
|
||||
lal -20
|
||||
loi 16
|
||||
adf 8
|
||||
lol -226
|
||||
adp 2
|
||||
sti 8 ; r2 := x + y
|
||||
loc 0
|
||||
sil -226 ; r1 := 0
|
||||
lin 34 ; note the abscence of the unnecesary jump
|
||||
lae 22 ; address of output structure
|
||||
lol -4
|
||||
cal $_wri ; write integer with default width
|
||||
asp 4 ; pop parameters
|
||||
lae 22
|
||||
lol -2
|
||||
loc 6
|
||||
cal $_wsi ; write integer width 6
|
||||
asp 6
|
||||
lae 22
|
||||
lal -12
|
||||
loi 8
|
||||
loc 9
|
||||
loc 3
|
||||
cal $_wrf ; write fixed format real, width 9, precision 3
|
||||
asp 14
|
||||
lae 22
|
||||
lol -22
|
||||
cal $_wrb ; write boolean, default width
|
||||
asp 4
|
||||
lae 22
|
||||
cal $_wln ; writeln
|
||||
asp 2
|
||||
ret 0 ; return, no result
|
||||
end 226
|
||||
exp $_main
|
||||
pro $_main,0 ; main program
|
||||
.6
|
||||
con 2,-1,22 ; description of external files
|
||||
.5
|
||||
rom 15.96F8
|
||||
fil .1 ; maintain source file name
|
||||
lae .6 ; description of external files
|
||||
lae 0 ; base of hol area to relocate buffer addresses
|
||||
cal $_ini ; initialize files, etc...
|
||||
asp 4
|
||||
lin 37
|
||||
lae .5
|
||||
loi 8
|
||||
lae 2
|
||||
sti 8 ; mx := 15.96
|
||||
lni ; lin 38 prior to optimization
|
||||
loc 99
|
||||
ste 0 ; mi := 99
|
||||
lni ; lin 39 prior to optimization
|
||||
lae 10 ; address of r
|
||||
cal $test
|
||||
asp 2
|
||||
loc 0 ; normal exit
|
||||
cal $_hlt ; cleanup and finish
|
||||
asp 2
|
||||
end 0
|
||||
mes 5 ; reals were used
|
||||
.DE 0
|
||||
The compact code corresponding to the above program is listed below.
|
||||
Read it horizontally, line by line, not column by column.
|
||||
Each number represents a byte of compact code, printed in decimal.
|
||||
The first two bytes form the magic word.
|
||||
.N 1
|
||||
.IS 3
|
||||
.DS B
|
||||
173 0 159 122 122 122 255 242 1 161 250 124 116 46 112 0
|
||||
255 156 245 40 2 245 0 128 120 155 249 123 115 117 109 160
|
||||
249 123 115 117 109 122 67 128 63 120 3 122 88 122 152 122
|
||||
242 2 161 121 219 122 255 155 249 124 116 101 115 116 160 249
|
||||
124 116 101 115 116 245 226 0 242 3 161 253 128 123 52 46
|
||||
56 255 242 4 161 253 128 123 48 46 53 255 159 123 245 30
|
||||
255 122 122 255 159 123 96 122 120 255 159 123 98 122 120 255
|
||||
159 123 116 122 120 255 159 123 118 122 120 255 159 123 100 128
|
||||
120 255 159 123 108 128 120 255 67 140 69 121 113 116 68 73
|
||||
116 69 123 81 122 69 126 3 122 113 118 68 57 242 3 72
|
||||
128 58 108 112 128 68 58 108 72 128 57 242 4 72 128 44
|
||||
128 58 100 112 128 68 69 121 113 98 68 69 245 122 0 113
|
||||
96 68 69 121 113 118 182 73 118 42 122 81 122 58 245 32
|
||||
255 73 118 57 242 2 94 122 73 118 69 220 10 123 54 118
|
||||
18 122 183 67 147 73 116 69 147 3 122 104 120 68 73 98
|
||||
73 120 111 130 68 58 100 72 136 2 128 73 120 4 122 112
|
||||
128 68 58 245 32 255 73 116 57 242 2 59 122 65 120 20
|
||||
249 123 115 117 109 8 124 64 122 113 118 184 67 151 73 118
|
||||
128 125 73 116 65 120 3 122 113 116 41 118 18 124 185 67
|
||||
152 73 120 113 245 30 255 73 98 73 245 30 255 111 130 58
|
||||
100 72 136 2 128 73 245 30 255 4 122 112 128 69 120 104
|
||||
245 30 255 67 154 57 142 73 116 20 249 124 95 119 114 105
|
||||
8 124 57 142 73 118 69 126 20 249 124 95 119 115 105 8
|
||||
126 57 142 58 108 72 128 69 129 69 123 20 249 124 95 119
|
||||
114 102 8 134 57 142 73 98 20 249 124 95 119 114 98 8
|
||||
124 57 142 20 249 124 95 119 108 110 8 122 88 120 152 245
|
||||
226 0 155 249 125 95 109 97 105 110 160 249 125 95 109 97
|
||||
105 110 120 242 6 151 122 119 142 255 242 5 161 253 128 125
|
||||
49 53 46 57 54 255 50 242 1 57 242 6 57 120 20 249
|
||||
124 95 105 110 105 8 124 67 157 57 242 5 72 128 57 122
|
||||
112 128 68 69 219 110 120 68 57 130 20 249 124 116 101 115
|
||||
116 8 122 69 120 20 249 124 95 104 108 116 8 122 152 120
|
||||
159 124 160 255 159 125 255
|
||||
.DE 0
|
||||
.IE
|
||||
.MS T A 0
|
||||
.ME
|
||||
.BP
|
||||
.MS B A 0
|
||||
.ME
|
||||
.CT
|
376
doc/em/iotrap.nr
376
doc/em/iotrap.nr
|
@ -1,376 +0,0 @@
|
|||
.SN 8
|
||||
.VS 1 0
|
||||
.BP
|
||||
.S1 "ENVIRONMENT INTERACTIONS"
|
||||
EM programs can interact with their environment in three ways.
|
||||
Two, starting/stopping and monitor calls, are dealt with in this chapter.
|
||||
The remaining way to interact, interrupts, will be treated
|
||||
together with traps in chapter 9.
|
||||
.S2 "Program starting and stopping"
|
||||
EM user programs start with a call to a procedure called
|
||||
m_a_i_n.
|
||||
The assembler and backends look for the definition of a procedure
|
||||
with this name in their input.
|
||||
The call passes three parameters to the procedure.
|
||||
The parameters are similar to the parameters supplied by the
|
||||
UNIX
|
||||
.FS
|
||||
UNIX is a Trademark of Bell Laboratories.
|
||||
.FE
|
||||
operating system to C programs.
|
||||
These parameters are often called
|
||||
.BW argc ,
|
||||
.B argv
|
||||
and
|
||||
.BW envp .
|
||||
Argc is the parameter nearest to LB and is a wordsized integer.
|
||||
The other two are pointers to the first element of an array of
|
||||
string pointers.
|
||||
.N
|
||||
The
|
||||
.B argv
|
||||
array contains
|
||||
.B argc
|
||||
strings, the first of which contains the program call name.
|
||||
The other strings in the
|
||||
.B argv
|
||||
array are the program parameters.
|
||||
.P
|
||||
The
|
||||
.B envp
|
||||
array contains strings in the form "name=string", where 'name'
|
||||
is the name of an environment variable and string its value.
|
||||
The
|
||||
.B envp
|
||||
is terminated by a zero pointer.
|
||||
.P
|
||||
An EM user program stops if the program returns from the first
|
||||
invocation of m_a_i_n.
|
||||
The contents of the function return area are used to procure a
|
||||
wordsized program return code.
|
||||
EM programs also stop when traps and interrupts occur that are
|
||||
not caught and when the exit monitor call is executed.
|
||||
.S2 "Input/Output and other monitor calls"
|
||||
EM differs from most conventional machines in that it has high level i/o
|
||||
instructions.
|
||||
Typical instructions are OPEN FILE and READ FROM FILE instead
|
||||
of low level instructions such as setting and clearing
|
||||
bits in device registers.
|
||||
By providing such high level i/o primitives, the task of implementing
|
||||
EM on various non EM machines is made considerably easier.
|
||||
.P
|
||||
I/O is initiated by the MON instruction, which expects an iocode on top
|
||||
of the stack.
|
||||
Often there are also parameters which are pushed on the
|
||||
stack in reverse order, that is: last
|
||||
parameter first.
|
||||
Some i/o functions also provide results, which are returned on the stack.
|
||||
In the list of monitor calls we use several types of parameters and results,
|
||||
these types consist of integers and unsigneds of varying sizes, but never
|
||||
smaller than the wordsize, and the two pointer types.
|
||||
.N 1
|
||||
The names of the types used are:
|
||||
.IS 4
|
||||
.PS - 10
|
||||
.PT int
|
||||
an integer of wordsize
|
||||
.PT int2
|
||||
an integer whose size is the maximum of the wordsize and 2
|
||||
bytes
|
||||
.PT int4
|
||||
an integer whose size is the maximum of the wordsize and 4
|
||||
bytes
|
||||
.PT intp
|
||||
an integer with the size of a pointer
|
||||
.PT uns2
|
||||
an unsigned integer whose size is the maximum of the wordsize and 2
|
||||
.PT unsp
|
||||
an unsigned integer with the size of a pointer
|
||||
.PT ptr
|
||||
a pointer into data space
|
||||
.PE 1
|
||||
.IE 0
|
||||
The table below lists the i/o codes with their results and
|
||||
parameters.
|
||||
This list is similar to the system calls of the UNIX Version 7
|
||||
operating system.
|
||||
.BP
|
||||
.A
|
||||
To execute a monitor call, proceed as follows:
|
||||
.IS 2
|
||||
.N 1
|
||||
.PS a 4 "" )
|
||||
.PT
|
||||
Stack the parameters, in reverse order, last parameter first.
|
||||
.PT
|
||||
Push the monitor call number (iocode) onto the stack.
|
||||
.PT
|
||||
Execute the MON instruction.
|
||||
.PE 1
|
||||
.IE
|
||||
An error code is present on the top of the stack after
|
||||
execution of most monitor calls.
|
||||
If this error code is zero, the call performed the action
|
||||
requested and the results are available on top of the stack.
|
||||
Non-zero error codes indicate a failure, in this case no
|
||||
results are available and the error code has been pushed twice.
|
||||
This construction enables programs to test for failure with a
|
||||
single instruction (~TEQ or TNE~) and still find out the cause of
|
||||
the failure.
|
||||
The result name 'e' is reserved for the error code.
|
||||
.N 1
|
||||
List of monitor calls.
|
||||
.DS B
|
||||
number name parameters results function
|
||||
|
||||
1 Exit status:int Terminate this process
|
||||
2 Fork e,flag,pid:int Spawn new process
|
||||
3 Read fildes:int;buf:ptr;nbytes:unsp
|
||||
e:int;rbytes:unsp Read from file
|
||||
4 Write fildes:int;buf:ptr;nbytes:unsp
|
||||
e:int;wbytes:unsp Write on a file
|
||||
5 Open string:ptr;flag:int
|
||||
e,fildes:int Open file for read and/or write
|
||||
6 Close fildes:int e:int Close a file
|
||||
7 Wait e:int;status,pid:int2
|
||||
Wait for child
|
||||
8 Creat string:ptr;mode:int
|
||||
e,fildes:int Create a new file
|
||||
9 Link string1,string2:ptr
|
||||
e:int Link to a file
|
||||
10 Unlink string:ptr e:int Remove directory entry
|
||||
12 Chdir string:ptr e:int Change default directory
|
||||
14 Mknod string:ptr;mode,addr:int2
|
||||
e:int Make a special file
|
||||
15 Chmod string:ptr;mode:int2
|
||||
e:int Change mode of file
|
||||
16 Chown string:ptr;owner,group:int2
|
||||
e:int Change owner/group of a file
|
||||
18 Stat string,statbuf:ptr
|
||||
e:int Get file status
|
||||
19 Lseek fildes:int;off:int4;whence:int
|
||||
e:int;oldoff:int4 Move read/write pointer
|
||||
20 Getpid pid:int2 Get process identification
|
||||
21 Mount special,string:ptr;rwflag:int
|
||||
e:int Mount file system
|
||||
22 Umount special:ptr e:int Unmount file system
|
||||
23 Setuid userid:int2 e:int Set user ID
|
||||
24 Getuid e_uid,r_uid:int2 Get user ID
|
||||
25 Stime time:int4 e:int Set time and date
|
||||
26 Ptrace request:int;pid:int2;addr:ptr;data:int
|
||||
e,value:int Process trace
|
||||
27 Alarm seconds:uns2 previous:uns2 Schedule signal
|
||||
28 Fstat fildes:int;statbuf:ptr
|
||||
e:int Get file status
|
||||
29 Pause Stop until signal
|
||||
30 Utime string,timep:ptr
|
||||
e:int Set file times
|
||||
33 Access string,mode:int e:int Determine file accessibility
|
||||
34 Nice incr:int Set program priority
|
||||
35 Ftime bufp:ptr e:int Get date and time
|
||||
36 Sync Update filesystem
|
||||
37 Kill pid:int2;sig:int
|
||||
e:int Send signal to a process
|
||||
41 Dup fildes,newfildes:int
|
||||
e,fildes:int Duplicate a file descriptor
|
||||
42 Pipe e,w_des,r_des:int Create a pipe
|
||||
43 Times buffer:ptr Get process times
|
||||
44 Profil buff:ptr;bufsiz,offset,scale:intp Execution time profile
|
||||
46 Setgid gid:int2 e:int Set group ID
|
||||
47 Getgid e_gid,r_gid:int Get group ID
|
||||
48 Sigtrp trapno,signo:int
|
||||
e,prevtrap:int See below
|
||||
51 Acct file:ptr e:int Turn accounting on or off
|
||||
53 Lock flag:int e:int Lock a process
|
||||
54 Ioctl fildes,request:int;argp:ptr
|
||||
e:int Control device
|
||||
56 Mpxcall cmd:int;vec:ptr e:int Multiplexed file handling
|
||||
59 Exece name,argv,envp:ptr
|
||||
e:int Execute a file
|
||||
60 Umask complmode:int2 oldmask:int2 Set file creation mode mask
|
||||
61 Chroot string:ptr e:int Change root directory
|
||||
.DE 1
|
||||
Codes 0, 11, 13, 17, 31, 32, 38, 39, 40, 45, 49, 50, 52,
|
||||
55, 57, 58, 62, and 63 are
|
||||
not used.
|
||||
.P
|
||||
All monitor calls, except fork and sigtrp
|
||||
are the same as the UNIX version 7 system calls.
|
||||
.P
|
||||
The sigtrp entry maps UNIX signals onto EM interrupts.
|
||||
Normally, trapno is in the range 0 to 252.
|
||||
In that case it requests that signal signo
|
||||
will cause trap trapno to occur.
|
||||
When given trap number -2, default signal handling is reset, and when given
|
||||
trap number -3, the signal is ignored.
|
||||
.P
|
||||
The flag returned by fork is 1 in the child process and 0 in
|
||||
the parent.
|
||||
The pid returned is the process-id of the other process.
|
||||
.BP
|
||||
.S1 "TRAPS AND INTERRUPTS"
|
||||
EM provides a means for the user program to catch all traps
|
||||
generated by the program itself, the hardware, or external conditions.
|
||||
This mechanism uses five instructions: LIM, SIM, SIG, TRP and RTT.
|
||||
This section of the manual may be omitted on the first reading since it
|
||||
presupposes knowledge of the EM instruction set.
|
||||
.P
|
||||
The action taken when a trap occures is determined by the value
|
||||
of an internal EM trap register.
|
||||
This register contains a pointer to a procedure.
|
||||
Initially the pointer used is zero and all traps halt the
|
||||
program with, hopefully, a useful message to the outside world.
|
||||
The SIG instruction can be used to alter the trap register,
|
||||
it pops a procedure pointer from the
|
||||
stack into the trap register.
|
||||
When a trap occurs after storing a nonzero value in the trap
|
||||
register, the procedure pointed to by the trap register
|
||||
is called with the trap number
|
||||
as the only parameter (see below).
|
||||
SIG returns the previous value of the trap register on the
|
||||
stack.
|
||||
Two consecutive SIGs are a no-op.
|
||||
When a trap occurs, the trap register is reset to its initial
|
||||
condition, to prevent recursive traps from hanging the machine up,
|
||||
e.g. stack overflow in the stack overflow handling procedure.
|
||||
.P
|
||||
The runtime systems for some languages need to ignore some EM
|
||||
traps.
|
||||
EM offers a feature called the ignore mask.
|
||||
It contains one bit for each of the lowest 16 trap numbers.
|
||||
The bits are numbered 0 to 15, with the least significant bit
|
||||
having number 0.
|
||||
If a certain bit is 1 the corresponding trap never
|
||||
occurs and processing simply continues.
|
||||
The actions performed by the offending instruction are
|
||||
described by the Pascal program in appendix A.
|
||||
.N
|
||||
If the bit is 0, traps are not ignored.
|
||||
The instructions LIM and SIM allow copying and replacement of
|
||||
the ignore mask.~
|
||||
.P
|
||||
The TRP instruction generates a trap, the trap number being found on the
|
||||
stack.
|
||||
This is, among other things,
|
||||
useful for library procedures and runtime systems.
|
||||
It can also be used by a low level trap procedure to pass the trap to a
|
||||
higher level one (see example below).
|
||||
.P
|
||||
The RTT instruction returns from the trap procedure and continues after the
|
||||
trap.
|
||||
In the list below all traps marked with an asterisk ('*') are
|
||||
considered to be fatal and it is explicitly undefined what happens if
|
||||
you try to restart after the trap.
|
||||
.P
|
||||
The way a trap procedure is called is completely compatible
|
||||
with normal calling conventions. The only way a trap procedure
|
||||
differs from normal procedures is the return. It has to use RTT instead
|
||||
of RET. This is necessary because the complete runtime status is saved on the
|
||||
stack before calling the procedure and all this status has to be reloaded.
|
||||
Error numbers are in the range 0 to 252.
|
||||
The trap numbers are divided into three categories:
|
||||
.IS 4
|
||||
.N 1
|
||||
.PS - 10
|
||||
.PT ~~0-~63
|
||||
EM machine errors, e.g. illegal instruction.
|
||||
.PS - 8
|
||||
.PT ~0-15
|
||||
maskable
|
||||
.PT 16-63
|
||||
not maskable
|
||||
.PE
|
||||
.PT ~64-127
|
||||
Reserved for use by compilers, run time systems, etc.
|
||||
.PT 128-252
|
||||
Available for user programs.
|
||||
.PE 1
|
||||
.IE
|
||||
EM machine errors are numbered as follows:
|
||||
.DS I 5
|
||||
.TS
|
||||
tab(@);
|
||||
n l l.
|
||||
0@EARRAY@Array bound error
|
||||
1@ERANGE@Range bound error
|
||||
2@ESET@Set bound error
|
||||
3@EIOVFL@Integer overflow
|
||||
4@EFOVFL@Floating overflow
|
||||
5@EFUNFL@Floating underflow
|
||||
6@EIDIVZ@Divide by 0
|
||||
7@EFDIVZ@Divide by 0.0
|
||||
8@EIUND@Undefined integer
|
||||
9@EFUND@Undefined float
|
||||
10@ECONV@Conversion error
|
||||
16*@ESTACK@Stack overflow
|
||||
17*@EHEAP@Heap overflow
|
||||
18*@EILLINS@Illegal instruction
|
||||
19*@EODDZ@Illegal size argument
|
||||
20*@ECASE@Case error
|
||||
21*@EMEMFLT@Addressing non existent memory
|
||||
22*@EBADPTR@Bad pointer used
|
||||
23*@EBADPC@Program counter out of range
|
||||
24@EBADLAE@Bad argument of LAE
|
||||
25@EBADMON@Bad monitor call
|
||||
26@EBADLIN@Argument of LIN too high
|
||||
27@EBADGTO@GTO descriptor error
|
||||
.TE
|
||||
.DE 0
|
||||
.P
|
||||
As an example,
|
||||
suppose a subprocedure has to be written to do a numeric
|
||||
calculation.
|
||||
When an overflow occurs the computation has to be stopped and
|
||||
the higher level procedure must be resumed.
|
||||
This can be programmed as follows using the mechanism described above:
|
||||
.DS B
|
||||
mes 2,2,2 ; set sizes
|
||||
ersave
|
||||
bss 2,0,0 ; Room to save previous value of trap procedure
|
||||
msave
|
||||
bss 2,0,0 ; Room to save previous value of trap mask
|
||||
|
||||
pro calcule,0 ; entry point
|
||||
lxl 0 ; fill in non-local goto descriptor with LB
|
||||
ste jmpbuf+4
|
||||
lor 1 ; and SP
|
||||
ste jmpbuf+2
|
||||
lim ; get current ignore mask
|
||||
ste msave ; save it
|
||||
lim
|
||||
loc 16 ; bit for EFOVFL
|
||||
ior 2 ; set in mask
|
||||
sim ; ignore EFOVFL from now on
|
||||
lpi $catch ; load procedure identifier
|
||||
sig ; catch wil get all traps now
|
||||
ste ersave ; save previous trap procedure identifier
|
||||
; perform calculation now, possibly generating overflow
|
||||
1 ; label jumped to by catch procedure
|
||||
loe ersave ; get old trap procedure
|
||||
sig ; refer all following trap to old procedure
|
||||
asp 2 ; remove result of sig
|
||||
loe msave ; restore previous mask
|
||||
sim ; done now
|
||||
; load result of calculation
|
||||
ret 2 ; return result
|
||||
jmpbuf
|
||||
con *1,0,0
|
||||
end
|
||||
.DE 0
|
||||
.VS 1 1
|
||||
.DS
|
||||
Example of catch procedure
|
||||
pro catch,0 ; Local procedure that must catch the overflow trap
|
||||
lol 2 ; Load trap number
|
||||
loc 4 ; check for overflow
|
||||
bne *1 ; if other trap, call higher trap procedure
|
||||
gto jmpbuf ; return to procedure calcule
|
||||
1 ; other trap has occurred
|
||||
loe ersave ; previous trap procedure
|
||||
sig ; other procedure will get the traps now
|
||||
asp 2 ; remove the result of sig
|
||||
lol 2 ; stack trap number
|
||||
trp ; call other trap procedure
|
||||
rtt ; if other procedure returns, do the same
|
||||
end
|
||||
.DE
|
2922
doc/em/itables
2922
doc/em/itables
File diff suppressed because it is too large
Load diff
|
@ -1 +0,0 @@
|
|||
0
|
|
@ -1,28 +0,0 @@
|
|||
#define WS EM_WSIZE
|
||||
#define PS EM_PSIZE
|
||||
#include "test.h"
|
||||
mes 2,WS,PS
|
||||
mes 1
|
||||
mes 4,300
|
||||
.000
|
||||
con "tst000"
|
||||
exp $m_a_i_n
|
||||
pro $m_a_i_n,0
|
||||
loc 123
|
||||
loc -98
|
||||
; TEST 000: empty
|
||||
fil .000
|
||||
loc -98
|
||||
bne *1
|
||||
loc 123
|
||||
bne *1
|
||||
lin 0
|
||||
nop
|
||||
loc 0
|
||||
ret WS
|
||||
1
|
||||
lin 1
|
||||
nop
|
||||
loc 1
|
||||
ret WS
|
||||
end
|
3
include/.distr
Normal file
3
include/.distr
Normal file
|
@ -0,0 +1,3 @@
|
|||
_tail_mon
|
||||
_tail_cc
|
||||
occam
|
3
lang/cem/.distr
Normal file
3
lang/cem/.distr
Normal file
|
@ -0,0 +1,3 @@
|
|||
cemcom
|
||||
ctest
|
||||
libcc
|
|
@ -1,88 +0,0 @@
|
|||
Files
|
||||
cem.1
|
||||
cem.c
|
||||
cemcom.1
|
||||
Parameters
|
||||
Makefile
|
||||
LLlex.c
|
||||
LLlex.h
|
||||
LLmessage.c
|
||||
align.h
|
||||
alloc.c
|
||||
alloc.h
|
||||
arith.c
|
||||
arith.h
|
||||
asm.c
|
||||
assert.h
|
||||
atw.h
|
||||
blocks.c
|
||||
char.tab
|
||||
ch7.c
|
||||
ch7bin.c
|
||||
ch7mon.c
|
||||
class.h
|
||||
code.c
|
||||
code.str
|
||||
conversion.c
|
||||
cstoper.c
|
||||
dataflow.c
|
||||
declar.g
|
||||
declarator.c
|
||||
declar.str
|
||||
decspecs.c
|
||||
decspecs.str
|
||||
def.str
|
||||
domacro.c
|
||||
dumpidf.c
|
||||
error.c
|
||||
eval.c
|
||||
expr.c
|
||||
expr.str
|
||||
expression.g
|
||||
faulty.h
|
||||
field.c
|
||||
field.str
|
||||
file_info.h
|
||||
idf.c
|
||||
idf.str
|
||||
init.c
|
||||
input.c
|
||||
input.h
|
||||
interface.h
|
||||
ival.c
|
||||
label.c
|
||||
label.h
|
||||
level.h
|
||||
macro.str
|
||||
main.c
|
||||
make.allocd
|
||||
make.hfiles
|
||||
make.next
|
||||
make.tokcase
|
||||
make.tokfile
|
||||
mcomm.c
|
||||
mes.h
|
||||
options
|
||||
options.c
|
||||
program.g
|
||||
replace.c
|
||||
scan.c
|
||||
sizes.h
|
||||
skip.c
|
||||
specials.h
|
||||
stack.c
|
||||
stack.str
|
||||
statement.g
|
||||
stb.c
|
||||
storage.c
|
||||
storage.h
|
||||
stmt.str
|
||||
struct.c
|
||||
struct.str
|
||||
switch.c
|
||||
switch.str
|
||||
tab.c
|
||||
tokenname.c
|
||||
tokenname.h
|
||||
type.c
|
||||
type.str
|
|
@ -1,799 +0,0 @@
|
|||
# $Header$
|
||||
# M A K E F I L E F O R A C K C - C O M P I L E R
|
||||
|
||||
# Machine and environ dependent definitions
|
||||
EMHOME = /usr/em# # ACK tree on this machine
|
||||
DESTINATION = /user1/$$USER/bin# # where to put the stuff
|
||||
MKDEP = $(EMHOME)/bin/mkdep# # dependency generator
|
||||
MAP =
|
||||
#MAP = -DInsertFile=ins_file -DInsertText=ins_text# bug in m68k2 back end
|
||||
SIM = /user1/dick/bin/sim# # Dicks sim program
|
||||
LINT = /usr/new/lint
|
||||
|
||||
# Libraries and EM interface definitions
|
||||
SYSLIB = $(EMHOME)/modules/lib/libsystem.a
|
||||
EMKLIB = $(EMHOME)/modules/lib/libemk.a
|
||||
EMELIB = $(EMHOME)/modules/lib/libeme.a
|
||||
STRLIB = $(EMHOME)/modules/lib/libstring.a
|
||||
PRTLIB = $(EMHOME)/modules/lib/libprint.a
|
||||
EMMESLIB = $(EMHOME)/modules/lib/libem_mes.a
|
||||
INPLIB = $(EMHOME)/modules/lib/libinput.a
|
||||
ALLOCLIB = $(EMHOME)/modules/lib/liballoc.a
|
||||
MALLOC = $(EMHOME)/modules/lib/malloc.o
|
||||
#CH3LIB = $(EMHOME)/modules/lib/libch3.a
|
||||
CH3LIB =
|
||||
LIBS = $(INPLIB) $(CH3LIB) $(EMMESLIB) $(EMKLIB) \
|
||||
$(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB)
|
||||
ELIBS = $(INPLIB) $(CH3LIB) $(EMMESLIB) $(EMELIB) \
|
||||
$(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB)
|
||||
LIB_INCLUDES = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg
|
||||
EM_INCLUDES = -I$(EMHOME)/h
|
||||
SYSLLIB = $(EMHOME)/modules/lib/llib-lsys.ln
|
||||
EMKLLIB = $(EMHOME)/modules/lib/llib-lemk.ln
|
||||
EMELLIB = $(EMHOME)/modules/lib/llib-leme.ln
|
||||
STRLLIB = $(EMHOME)/modules/lib/llib-lstr.ln
|
||||
PRTLLIB = $(EMHOME)/modules/lib/llib-lprint.ln
|
||||
EMMESLLIB = $(EMHOME)/modules/lib/llib-lmes.ln
|
||||
INPLLIB = $(EMHOME)/modules/lib/llib-linput.ln
|
||||
CH3LLIB = $(EMHOME)/modules/lib/llib-lch3.ln
|
||||
ALLOCLLIB = $(EMHOME)/modules/lib/llib-alloc.ln
|
||||
LINTLIBS =
|
||||
#LINTLIBS = $(CH3LLIB) $(INPLLIB) $(EMMESLLIB) $(EMKLLIB) \
|
||||
# $(PRTLLIB) $(STRLLIB) $(SYSLLIB) $(ALLOCLLIB)
|
||||
|
||||
# Where to install the compiler and its driver
|
||||
CEMCOM = $(DESTINATION)/cemcom
|
||||
DRIVER = $(DESTINATION)/cem
|
||||
|
||||
# What C compiler to use and how
|
||||
# CC = $(ACK) -.c
|
||||
# CC = CC
|
||||
# CC = /bin/cc
|
||||
COPTIONS =
|
||||
|
||||
# What parser generator to use and how
|
||||
GEN = $(EMHOME)/bin/LLgen
|
||||
GENOPTIONS = -vv
|
||||
|
||||
# Special #defines during compilation
|
||||
CDEFS = $(MAP) $(EM_INCLUDES) $(LIB_INCLUDES)
|
||||
CFLAGS = $(CDEFS) $(COPTIONS) -O# we cannot pass the COPTIONS to lint!
|
||||
|
||||
# Grammar files and their objects
|
||||
LSRC = tokenfile.g declar.g statement.g expression.g program.g ival.g
|
||||
GLCSRC = tokenfile.c declar.c statement.c expression.c program.c ival.c
|
||||
LOBJ = tokenfile.o declar.o statement.o expression.o program.o Lpars.o ival.o
|
||||
|
||||
# Objects of hand-written C files
|
||||
COBJ = main.o idf.o declarator.o decspecs.o struct.o \
|
||||
expr.o ch7.o ch7bin.o cstoper.o arith.o \
|
||||
asm.o code.o dumpidf.o error.o field.o\
|
||||
tokenname.o LLlex.o LLmessage.o \
|
||||
input.o domacro.o replace.o init.o options.o \
|
||||
scan.o skip.o stack.o type.o ch7mon.o label.o eval.o \
|
||||
switch.o conversion.o \
|
||||
blocks.o dataflow.o Version.o
|
||||
|
||||
# Objects of other generated C files
|
||||
GOBJ = char.o symbol2str.o next.o
|
||||
|
||||
# generated source files
|
||||
GSRC = char.c symbol2str.c next.c \
|
||||
code.h declar.h decspecs.h def.h expr.h field.h estack.h \
|
||||
idf.h macro.h stack.h stmt.h struct.h switch.h type.h
|
||||
|
||||
# .h files generated by `make hfiles'; PLEASE KEEP THIS UP-TO-DATE!
|
||||
GHSRC = botch_free.h dataflow.h debug.h density.h errout.h \
|
||||
idfsize.h ifdepth.h inputtype.h inumlength.h lapbuf.h \
|
||||
maxincl.h nobitfield.h nofloat.h nopp.h noRoption.h nocross.h \
|
||||
nparams.h numsize.h parbufsize.h pathlength.h \
|
||||
strsize.h target_sizes.h textsize.h use_tmp.h spec_arith.h static.h
|
||||
|
||||
# Other generated files, for 'make clean' only
|
||||
GENERATED = tab tokenfile.g Lpars.h LLfiles LL.output lint.out \
|
||||
print Xref lxref hfiles cfiles $(GLCSRC)
|
||||
|
||||
# include files containing ALLOCDEF specifications
|
||||
NEXTFILES = code.str declar.str decspecs.str def.str expr.str field.str \
|
||||
estack.str \
|
||||
idf.str macro.str stack.str stmt.str struct.str switch.str type.str
|
||||
|
||||
.SUFFIXES: .str .h
|
||||
.str.h:
|
||||
./make.allocd <$*.str >$*.h
|
||||
|
||||
all: cc
|
||||
|
||||
cc:
|
||||
make "CC=$(CC)" hfiles
|
||||
make "CC=$(CC)" LLfiles
|
||||
make "CC=$(CC)" main
|
||||
|
||||
cem: cem.c
|
||||
$(CC) -O cem.c $(SYSLIB) -o cem
|
||||
|
||||
lint.cem: cem.c
|
||||
$(LINT) -bx cem.c
|
||||
|
||||
hfiles: ./make.hfiles Parameters
|
||||
./make.hfiles Parameters
|
||||
@touch hfiles
|
||||
|
||||
LLfiles: $(LSRC)
|
||||
$(GEN) $(GENOPTIONS) $(LSRC)
|
||||
@touch LLfiles
|
||||
|
||||
tokenfile.g: tokenname.c make.tokfile
|
||||
<tokenname.c ./make.tokfile >tokenfile.g
|
||||
|
||||
symbol2str.c: tokenname.c make.tokcase
|
||||
<tokenname.c ./make.tokcase >symbol2str.c
|
||||
|
||||
char.c: tab char.tab
|
||||
tab -fchar.tab >char.c
|
||||
|
||||
next.c: make.next $(NEXTFILES)
|
||||
./make.next $(NEXTFILES) >next.c
|
||||
|
||||
code.h: make.allocd
|
||||
declar.h: make.allocd
|
||||
decspecs.h: make.allocd
|
||||
def.h: make.allocd
|
||||
estack.h: make.allocd
|
||||
expr.h: make.allocd
|
||||
field.h: make.allocd
|
||||
idf.h: make.allocd
|
||||
macro.h: make.allocd
|
||||
stack.h: make.allocd
|
||||
stmt.h: make.allocd
|
||||
struct.h: make.allocd
|
||||
switch.h: make.allocd
|
||||
type.h: make.allocd
|
||||
|
||||
# Objects needed for 'main'
|
||||
OBJ = $(COBJ) $(LOBJ) $(GOBJ)
|
||||
|
||||
main: $(OBJ) Makefile
|
||||
$(CC) $(COPTIONS) $(LFLAGS) $(OBJ) $(LIBS) -o main
|
||||
size main
|
||||
|
||||
emain: $(OBJ) Makefile
|
||||
$(CC) $(COPTIONS) $(LFLAGS) $(OBJ) $(ELIBS) -o emain
|
||||
size emain
|
||||
|
||||
cfiles: hfiles LLfiles $(GSRC)
|
||||
@touch cfiles
|
||||
|
||||
install: main cem
|
||||
cp main $(CEMCOM)
|
||||
cp cem $(DRIVER)
|
||||
|
||||
print: files
|
||||
pr `cat files` > print
|
||||
|
||||
tags: cfiles
|
||||
ctags `sources $(OBJ)`
|
||||
|
||||
shar: files
|
||||
shar `cat files`
|
||||
|
||||
listcfiles:
|
||||
@echo `sources $(OBJ)`
|
||||
|
||||
listobjects:
|
||||
@echo $(OBJ)
|
||||
|
||||
depend: cfiles
|
||||
sed '/^#AUTOAUTO/,$$d' Makefile >Makefile.new
|
||||
echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >>Makefile.new
|
||||
$(MKDEP) `sources $(OBJ)` | sed 's/\.c:/.o:/' >>Makefile.new
|
||||
mv Makefile Makefile.old
|
||||
mv Makefile.new Makefile
|
||||
|
||||
xref:
|
||||
ctags -x `grep "\.[ch]" files`|sed "s/).*/)/">Xref
|
||||
|
||||
lxref:
|
||||
lxref $(OBJ) -lc >lxref
|
||||
|
||||
lint: lint.main lint.cem lint.tab
|
||||
|
||||
lint.main: cfiles
|
||||
$(LINT) -bx $(CDEFS) `sources $(OBJ)` $(LINTLIBS) >lint.out
|
||||
|
||||
cchk:
|
||||
cchk `sources $(COBJ)`
|
||||
|
||||
clean:
|
||||
rm -f `sources $(LOBJ)` $(OBJ) $(GENERATED) $(GSRC) $(GHSRC)
|
||||
|
||||
tab:
|
||||
$(CC) tab.c -o tab
|
||||
|
||||
lint.tab:
|
||||
$(LINT) -abx tab.c
|
||||
|
||||
sim: cfiles
|
||||
$(SIM) $(SIMFLAGS) `sources $(COBJ)` $(GSRC) $(LSRC)
|
||||
|
||||
#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
|
||||
main.o: LLlex.h
|
||||
main.o: Lpars.h
|
||||
main.o: align.h
|
||||
main.o: arith.h
|
||||
main.o: debug.h
|
||||
main.o: declar.h
|
||||
main.o: file_info.h
|
||||
main.o: idf.h
|
||||
main.o: input.h
|
||||
main.o: inputtype.h
|
||||
main.o: level.h
|
||||
main.o: maxincl.h
|
||||
main.o: noRoption.h
|
||||
main.o: nobitfield.h
|
||||
main.o: nocross.h
|
||||
main.o: nofloat.h
|
||||
main.o: nopp.h
|
||||
main.o: sizes.h
|
||||
main.o: spec_arith.h
|
||||
main.o: specials.h
|
||||
main.o: target_sizes.h
|
||||
main.o: tokenname.h
|
||||
main.o: type.h
|
||||
main.o: use_tmp.h
|
||||
idf.o: LLlex.h
|
||||
idf.o: Lpars.h
|
||||
idf.o: align.h
|
||||
idf.o: arith.h
|
||||
idf.o: assert.h
|
||||
idf.o: botch_free.h
|
||||
idf.o: debug.h
|
||||
idf.o: declar.h
|
||||
idf.o: decspecs.h
|
||||
idf.o: def.h
|
||||
idf.o: file_info.h
|
||||
idf.o: idf.h
|
||||
idf.o: idfsize.h
|
||||
idf.o: label.h
|
||||
idf.o: level.h
|
||||
idf.o: noRoption.h
|
||||
idf.o: nobitfield.h
|
||||
idf.o: nocross.h
|
||||
idf.o: nofloat.h
|
||||
idf.o: nopp.h
|
||||
idf.o: sizes.h
|
||||
idf.o: spec_arith.h
|
||||
idf.o: specials.h
|
||||
idf.o: stack.h
|
||||
idf.o: struct.h
|
||||
idf.o: target_sizes.h
|
||||
idf.o: type.h
|
||||
declarator.o: Lpars.h
|
||||
declarator.o: arith.h
|
||||
declarator.o: botch_free.h
|
||||
declarator.o: declar.h
|
||||
declarator.o: expr.h
|
||||
declarator.o: idf.h
|
||||
declarator.o: label.h
|
||||
declarator.o: nobitfield.h
|
||||
declarator.o: nocross.h
|
||||
declarator.o: nofloat.h
|
||||
declarator.o: nopp.h
|
||||
declarator.o: sizes.h
|
||||
declarator.o: spec_arith.h
|
||||
declarator.o: target_sizes.h
|
||||
declarator.o: type.h
|
||||
decspecs.o: Lpars.h
|
||||
decspecs.o: arith.h
|
||||
decspecs.o: decspecs.h
|
||||
decspecs.o: def.h
|
||||
decspecs.o: level.h
|
||||
decspecs.o: noRoption.h
|
||||
decspecs.o: nobitfield.h
|
||||
decspecs.o: nofloat.h
|
||||
decspecs.o: spec_arith.h
|
||||
decspecs.o: type.h
|
||||
struct.o: LLlex.h
|
||||
struct.o: Lpars.h
|
||||
struct.o: align.h
|
||||
struct.o: arith.h
|
||||
struct.o: assert.h
|
||||
struct.o: botch_free.h
|
||||
struct.o: debug.h
|
||||
struct.o: def.h
|
||||
struct.o: field.h
|
||||
struct.o: file_info.h
|
||||
struct.o: idf.h
|
||||
struct.o: level.h
|
||||
struct.o: noRoption.h
|
||||
struct.o: nobitfield.h
|
||||
struct.o: nocross.h
|
||||
struct.o: nofloat.h
|
||||
struct.o: nopp.h
|
||||
struct.o: sizes.h
|
||||
struct.o: spec_arith.h
|
||||
struct.o: stack.h
|
||||
struct.o: struct.h
|
||||
struct.o: target_sizes.h
|
||||
struct.o: type.h
|
||||
expr.o: LLlex.h
|
||||
expr.o: Lpars.h
|
||||
expr.o: arith.h
|
||||
expr.o: botch_free.h
|
||||
expr.o: declar.h
|
||||
expr.o: decspecs.h
|
||||
expr.o: def.h
|
||||
expr.o: expr.h
|
||||
expr.o: file_info.h
|
||||
expr.o: idf.h
|
||||
expr.o: label.h
|
||||
expr.o: level.h
|
||||
expr.o: noRoption.h
|
||||
expr.o: nobitfield.h
|
||||
expr.o: nocross.h
|
||||
expr.o: nofloat.h
|
||||
expr.o: nopp.h
|
||||
expr.o: sizes.h
|
||||
expr.o: spec_arith.h
|
||||
expr.o: target_sizes.h
|
||||
expr.o: type.h
|
||||
ch7.o: Lpars.h
|
||||
ch7.o: arith.h
|
||||
ch7.o: assert.h
|
||||
ch7.o: debug.h
|
||||
ch7.o: def.h
|
||||
ch7.o: expr.h
|
||||
ch7.o: idf.h
|
||||
ch7.o: label.h
|
||||
ch7.o: nobitfield.h
|
||||
ch7.o: nofloat.h
|
||||
ch7.o: nopp.h
|
||||
ch7.o: spec_arith.h
|
||||
ch7.o: struct.h
|
||||
ch7.o: type.h
|
||||
ch7bin.o: Lpars.h
|
||||
ch7bin.o: arith.h
|
||||
ch7bin.o: botch_free.h
|
||||
ch7bin.o: expr.h
|
||||
ch7bin.o: idf.h
|
||||
ch7bin.o: label.h
|
||||
ch7bin.o: noRoption.h
|
||||
ch7bin.o: nobitfield.h
|
||||
ch7bin.o: nofloat.h
|
||||
ch7bin.o: nopp.h
|
||||
ch7bin.o: spec_arith.h
|
||||
ch7bin.o: struct.h
|
||||
ch7bin.o: type.h
|
||||
cstoper.o: Lpars.h
|
||||
cstoper.o: arith.h
|
||||
cstoper.o: assert.h
|
||||
cstoper.o: debug.h
|
||||
cstoper.o: expr.h
|
||||
cstoper.o: idf.h
|
||||
cstoper.o: label.h
|
||||
cstoper.o: nobitfield.h
|
||||
cstoper.o: nocross.h
|
||||
cstoper.o: nofloat.h
|
||||
cstoper.o: nopp.h
|
||||
cstoper.o: sizes.h
|
||||
cstoper.o: spec_arith.h
|
||||
cstoper.o: target_sizes.h
|
||||
cstoper.o: type.h
|
||||
arith.o: Lpars.h
|
||||
arith.o: arith.h
|
||||
arith.o: botch_free.h
|
||||
arith.o: expr.h
|
||||
arith.o: field.h
|
||||
arith.o: idf.h
|
||||
arith.o: label.h
|
||||
arith.o: mes.h
|
||||
arith.o: noRoption.h
|
||||
arith.o: nobitfield.h
|
||||
arith.o: nofloat.h
|
||||
arith.o: nopp.h
|
||||
arith.o: spec_arith.h
|
||||
arith.o: type.h
|
||||
code.o: LLlex.h
|
||||
code.o: Lpars.h
|
||||
code.o: align.h
|
||||
code.o: arith.h
|
||||
code.o: assert.h
|
||||
code.o: atw.h
|
||||
code.o: botch_free.h
|
||||
code.o: code.h
|
||||
code.o: dataflow.h
|
||||
code.o: debug.h
|
||||
code.o: declar.h
|
||||
code.o: decspecs.h
|
||||
code.o: def.h
|
||||
code.o: expr.h
|
||||
code.o: file_info.h
|
||||
code.o: idf.h
|
||||
code.o: label.h
|
||||
code.o: level.h
|
||||
code.o: mes.h
|
||||
code.o: noRoption.h
|
||||
code.o: nobitfield.h
|
||||
code.o: nocross.h
|
||||
code.o: nofloat.h
|
||||
code.o: nopp.h
|
||||
code.o: sizes.h
|
||||
code.o: spec_arith.h
|
||||
code.o: specials.h
|
||||
code.o: stack.h
|
||||
code.o: stmt.h
|
||||
code.o: target_sizes.h
|
||||
code.o: type.h
|
||||
code.o: use_tmp.h
|
||||
dumpidf.o: Lpars.h
|
||||
dumpidf.o: arith.h
|
||||
dumpidf.o: debug.h
|
||||
dumpidf.o: def.h
|
||||
dumpidf.o: expr.h
|
||||
dumpidf.o: field.h
|
||||
dumpidf.o: idf.h
|
||||
dumpidf.o: label.h
|
||||
dumpidf.o: nobitfield.h
|
||||
dumpidf.o: nofloat.h
|
||||
dumpidf.o: nopp.h
|
||||
dumpidf.o: spec_arith.h
|
||||
dumpidf.o: stack.h
|
||||
dumpidf.o: static.h
|
||||
dumpidf.o: struct.h
|
||||
dumpidf.o: type.h
|
||||
error.o: LLlex.h
|
||||
error.o: arith.h
|
||||
error.o: debug.h
|
||||
error.o: errout.h
|
||||
error.o: expr.h
|
||||
error.o: file_info.h
|
||||
error.o: label.h
|
||||
error.o: nofloat.h
|
||||
error.o: nopp.h
|
||||
error.o: spec_arith.h
|
||||
error.o: tokenname.h
|
||||
error.o: use_tmp.h
|
||||
field.o: Lpars.h
|
||||
field.o: arith.h
|
||||
field.o: assert.h
|
||||
field.o: code.h
|
||||
field.o: debug.h
|
||||
field.o: expr.h
|
||||
field.o: field.h
|
||||
field.o: idf.h
|
||||
field.o: label.h
|
||||
field.o: nobitfield.h
|
||||
field.o: nocross.h
|
||||
field.o: nofloat.h
|
||||
field.o: nopp.h
|
||||
field.o: sizes.h
|
||||
field.o: spec_arith.h
|
||||
field.o: target_sizes.h
|
||||
field.o: type.h
|
||||
tokenname.o: LLlex.h
|
||||
tokenname.o: Lpars.h
|
||||
tokenname.o: arith.h
|
||||
tokenname.o: file_info.h
|
||||
tokenname.o: idf.h
|
||||
tokenname.o: nofloat.h
|
||||
tokenname.o: nopp.h
|
||||
tokenname.o: spec_arith.h
|
||||
tokenname.o: tokenname.h
|
||||
LLlex.o: LLlex.h
|
||||
LLlex.o: Lpars.h
|
||||
LLlex.o: arith.h
|
||||
LLlex.o: assert.h
|
||||
LLlex.o: class.h
|
||||
LLlex.o: debug.h
|
||||
LLlex.o: def.h
|
||||
LLlex.o: file_info.h
|
||||
LLlex.o: idf.h
|
||||
LLlex.o: idfsize.h
|
||||
LLlex.o: input.h
|
||||
LLlex.o: nocross.h
|
||||
LLlex.o: nofloat.h
|
||||
LLlex.o: nopp.h
|
||||
LLlex.o: numsize.h
|
||||
LLlex.o: sizes.h
|
||||
LLlex.o: spec_arith.h
|
||||
LLlex.o: strsize.h
|
||||
LLlex.o: target_sizes.h
|
||||
LLmessage.o: LLlex.h
|
||||
LLmessage.o: Lpars.h
|
||||
LLmessage.o: arith.h
|
||||
LLmessage.o: file_info.h
|
||||
LLmessage.o: idf.h
|
||||
LLmessage.o: nofloat.h
|
||||
LLmessage.o: nopp.h
|
||||
LLmessage.o: spec_arith.h
|
||||
input.o: file_info.h
|
||||
input.o: input.h
|
||||
input.o: inputtype.h
|
||||
input.o: nopp.h
|
||||
domacro.o: LLlex.h
|
||||
domacro.o: Lpars.h
|
||||
domacro.o: arith.h
|
||||
domacro.o: assert.h
|
||||
domacro.o: botch_free.h
|
||||
domacro.o: class.h
|
||||
domacro.o: debug.h
|
||||
domacro.o: file_info.h
|
||||
domacro.o: idf.h
|
||||
domacro.o: idfsize.h
|
||||
domacro.o: ifdepth.h
|
||||
domacro.o: input.h
|
||||
domacro.o: interface.h
|
||||
domacro.o: macro.h
|
||||
domacro.o: nofloat.h
|
||||
domacro.o: nopp.h
|
||||
domacro.o: nparams.h
|
||||
domacro.o: parbufsize.h
|
||||
domacro.o: spec_arith.h
|
||||
domacro.o: textsize.h
|
||||
replace.o: LLlex.h
|
||||
replace.o: arith.h
|
||||
replace.o: assert.h
|
||||
replace.o: class.h
|
||||
replace.o: debug.h
|
||||
replace.o: file_info.h
|
||||
replace.o: idf.h
|
||||
replace.o: input.h
|
||||
replace.o: interface.h
|
||||
replace.o: macro.h
|
||||
replace.o: nofloat.h
|
||||
replace.o: nopp.h
|
||||
replace.o: pathlength.h
|
||||
replace.o: spec_arith.h
|
||||
replace.o: static.h
|
||||
replace.o: strsize.h
|
||||
init.o: class.h
|
||||
init.o: idf.h
|
||||
init.o: interface.h
|
||||
init.o: macro.h
|
||||
init.o: nopp.h
|
||||
options.o: align.h
|
||||
options.o: arith.h
|
||||
options.o: botch_free.h
|
||||
options.o: class.h
|
||||
options.o: dataflow.h
|
||||
options.o: idf.h
|
||||
options.o: idfsize.h
|
||||
options.o: macro.h
|
||||
options.o: maxincl.h
|
||||
options.o: noRoption.h
|
||||
options.o: nobitfield.h
|
||||
options.o: nocross.h
|
||||
options.o: nofloat.h
|
||||
options.o: nopp.h
|
||||
options.o: sizes.h
|
||||
options.o: spec_arith.h
|
||||
options.o: target_sizes.h
|
||||
options.o: use_tmp.h
|
||||
scan.o: class.h
|
||||
scan.o: idf.h
|
||||
scan.o: input.h
|
||||
scan.o: interface.h
|
||||
scan.o: lapbuf.h
|
||||
scan.o: macro.h
|
||||
scan.o: nopp.h
|
||||
scan.o: nparams.h
|
||||
skip.o: LLlex.h
|
||||
skip.o: arith.h
|
||||
skip.o: class.h
|
||||
skip.o: file_info.h
|
||||
skip.o: input.h
|
||||
skip.o: interface.h
|
||||
skip.o: nofloat.h
|
||||
skip.o: nopp.h
|
||||
skip.o: spec_arith.h
|
||||
stack.o: Lpars.h
|
||||
stack.o: arith.h
|
||||
stack.o: botch_free.h
|
||||
stack.o: debug.h
|
||||
stack.o: def.h
|
||||
stack.o: idf.h
|
||||
stack.o: level.h
|
||||
stack.o: mes.h
|
||||
stack.o: noRoption.h
|
||||
stack.o: nobitfield.h
|
||||
stack.o: nofloat.h
|
||||
stack.o: nopp.h
|
||||
stack.o: spec_arith.h
|
||||
stack.o: stack.h
|
||||
stack.o: struct.h
|
||||
stack.o: type.h
|
||||
type.o: Lpars.h
|
||||
type.o: align.h
|
||||
type.o: arith.h
|
||||
type.o: botch_free.h
|
||||
type.o: def.h
|
||||
type.o: idf.h
|
||||
type.o: nobitfield.h
|
||||
type.o: nocross.h
|
||||
type.o: nofloat.h
|
||||
type.o: nopp.h
|
||||
type.o: sizes.h
|
||||
type.o: spec_arith.h
|
||||
type.o: target_sizes.h
|
||||
type.o: type.h
|
||||
ch7mon.o: Lpars.h
|
||||
ch7mon.o: arith.h
|
||||
ch7mon.o: botch_free.h
|
||||
ch7mon.o: def.h
|
||||
ch7mon.o: expr.h
|
||||
ch7mon.o: idf.h
|
||||
ch7mon.o: label.h
|
||||
ch7mon.o: nobitfield.h
|
||||
ch7mon.o: nofloat.h
|
||||
ch7mon.o: nopp.h
|
||||
ch7mon.o: spec_arith.h
|
||||
ch7mon.o: type.h
|
||||
label.o: Lpars.h
|
||||
label.o: arith.h
|
||||
label.o: def.h
|
||||
label.o: idf.h
|
||||
label.o: label.h
|
||||
label.o: level.h
|
||||
label.o: noRoption.h
|
||||
label.o: nobitfield.h
|
||||
label.o: nofloat.h
|
||||
label.o: nopp.h
|
||||
label.o: spec_arith.h
|
||||
label.o: type.h
|
||||
eval.o: Lpars.h
|
||||
eval.o: align.h
|
||||
eval.o: arith.h
|
||||
eval.o: assert.h
|
||||
eval.o: atw.h
|
||||
eval.o: code.h
|
||||
eval.o: dataflow.h
|
||||
eval.o: debug.h
|
||||
eval.o: def.h
|
||||
eval.o: expr.h
|
||||
eval.o: idf.h
|
||||
eval.o: label.h
|
||||
eval.o: level.h
|
||||
eval.o: mes.h
|
||||
eval.o: nobitfield.h
|
||||
eval.o: nocross.h
|
||||
eval.o: nofloat.h
|
||||
eval.o: nopp.h
|
||||
eval.o: sizes.h
|
||||
eval.o: spec_arith.h
|
||||
eval.o: stack.h
|
||||
eval.o: target_sizes.h
|
||||
eval.o: type.h
|
||||
switch.o: Lpars.h
|
||||
switch.o: arith.h
|
||||
switch.o: assert.h
|
||||
switch.o: botch_free.h
|
||||
switch.o: code.h
|
||||
switch.o: debug.h
|
||||
switch.o: density.h
|
||||
switch.o: expr.h
|
||||
switch.o: idf.h
|
||||
switch.o: label.h
|
||||
switch.o: noRoption.h
|
||||
switch.o: nobitfield.h
|
||||
switch.o: nofloat.h
|
||||
switch.o: nopp.h
|
||||
switch.o: spec_arith.h
|
||||
switch.o: switch.h
|
||||
switch.o: type.h
|
||||
conversion.o: Lpars.h
|
||||
conversion.o: arith.h
|
||||
conversion.o: nobitfield.h
|
||||
conversion.o: nocross.h
|
||||
conversion.o: nofloat.h
|
||||
conversion.o: sizes.h
|
||||
conversion.o: spec_arith.h
|
||||
conversion.o: target_sizes.h
|
||||
conversion.o: type.h
|
||||
blocks.o: align.h
|
||||
blocks.o: arith.h
|
||||
blocks.o: atw.h
|
||||
blocks.o: label.h
|
||||
blocks.o: nocross.h
|
||||
blocks.o: nofloat.h
|
||||
blocks.o: sizes.h
|
||||
blocks.o: spec_arith.h
|
||||
blocks.o: stack.h
|
||||
blocks.o: target_sizes.h
|
||||
dataflow.o: dataflow.h
|
||||
tokenfile.o: Lpars.h
|
||||
declar.o: LLlex.h
|
||||
declar.o: Lpars.h
|
||||
declar.o: arith.h
|
||||
declar.o: debug.h
|
||||
declar.o: declar.h
|
||||
declar.o: decspecs.h
|
||||
declar.o: def.h
|
||||
declar.o: expr.h
|
||||
declar.o: field.h
|
||||
declar.o: file_info.h
|
||||
declar.o: idf.h
|
||||
declar.o: label.h
|
||||
declar.o: level.h
|
||||
declar.o: nobitfield.h
|
||||
declar.o: nocross.h
|
||||
declar.o: nofloat.h
|
||||
declar.o: nopp.h
|
||||
declar.o: sizes.h
|
||||
declar.o: spec_arith.h
|
||||
declar.o: struct.h
|
||||
declar.o: target_sizes.h
|
||||
declar.o: type.h
|
||||
statement.o: LLlex.h
|
||||
statement.o: Lpars.h
|
||||
statement.o: arith.h
|
||||
statement.o: botch_free.h
|
||||
statement.o: code.h
|
||||
statement.o: debug.h
|
||||
statement.o: def.h
|
||||
statement.o: expr.h
|
||||
statement.o: file_info.h
|
||||
statement.o: idf.h
|
||||
statement.o: label.h
|
||||
statement.o: nobitfield.h
|
||||
statement.o: nofloat.h
|
||||
statement.o: nopp.h
|
||||
statement.o: spec_arith.h
|
||||
statement.o: stack.h
|
||||
statement.o: type.h
|
||||
expression.o: LLlex.h
|
||||
expression.o: Lpars.h
|
||||
expression.o: arith.h
|
||||
expression.o: expr.h
|
||||
expression.o: file_info.h
|
||||
expression.o: idf.h
|
||||
expression.o: label.h
|
||||
expression.o: noRoption.h
|
||||
expression.o: nobitfield.h
|
||||
expression.o: nofloat.h
|
||||
expression.o: nopp.h
|
||||
expression.o: spec_arith.h
|
||||
expression.o: type.h
|
||||
program.o: LLlex.h
|
||||
program.o: Lpars.h
|
||||
program.o: arith.h
|
||||
program.o: code.h
|
||||
program.o: declar.h
|
||||
program.o: decspecs.h
|
||||
program.o: def.h
|
||||
program.o: expr.h
|
||||
program.o: file_info.h
|
||||
program.o: idf.h
|
||||
program.o: label.h
|
||||
program.o: nobitfield.h
|
||||
program.o: nofloat.h
|
||||
program.o: nopp.h
|
||||
program.o: spec_arith.h
|
||||
program.o: type.h
|
||||
Lpars.o: Lpars.h
|
||||
ival.o: LLlex.h
|
||||
ival.o: Lpars.h
|
||||
ival.o: align.h
|
||||
ival.o: arith.h
|
||||
ival.o: assert.h
|
||||
ival.o: class.h
|
||||
ival.o: debug.h
|
||||
ival.o: def.h
|
||||
ival.o: estack.h
|
||||
ival.o: expr.h
|
||||
ival.o: field.h
|
||||
ival.o: file_info.h
|
||||
ival.o: idf.h
|
||||
ival.o: label.h
|
||||
ival.o: level.h
|
||||
ival.o: noRoption.h
|
||||
ival.o: nobitfield.h
|
||||
ival.o: nocross.h
|
||||
ival.o: nofloat.h
|
||||
ival.o: nopp.h
|
||||
ival.o: sizes.h
|
||||
ival.o: spec_arith.h
|
||||
ival.o: struct.h
|
||||
ival.o: target_sizes.h
|
||||
ival.o: type.h
|
||||
char.o: class.h
|
||||
symbol2str.o: Lpars.h
|
|
@ -1,135 +0,0 @@
|
|||
!File: pathlength.h
|
||||
#define PATHLENGTH 1024 /* max. length of path to file */
|
||||
|
||||
|
||||
!File: errout.h
|
||||
#define ERROUT STDERR /* file pointer for writing messages */
|
||||
#define MAXERR_LINE 5 /* maximum number of error messages given
|
||||
on the same input line. */
|
||||
|
||||
|
||||
!File: idfsize.h
|
||||
#define IDFSIZE 64 /* maximum significant length of an identifier */
|
||||
|
||||
|
||||
!File: numsize.h
|
||||
#define NUMSIZE 256 /* maximum length of a numeric constant */
|
||||
|
||||
|
||||
!File: nparams.h
|
||||
#define NPARAMS 32 /* maximum number of parameters of macros */
|
||||
|
||||
|
||||
!File: ifdepth.h
|
||||
#define IFDEPTH 256 /* maximum number of nested if-constructions */
|
||||
|
||||
|
||||
!File: maxincl.h
|
||||
#define MAXINCL 12 /* maximum number of #include directories */
|
||||
|
||||
|
||||
!File: density.h
|
||||
#define DENSITY 2 /* see switch.[ch] for an explanation */
|
||||
|
||||
|
||||
!File: lapbuf.h
|
||||
#define LAPBUF 4096 /* size of macro actual parameter buffer */
|
||||
|
||||
|
||||
!File: strsize.h
|
||||
#define ISTRSIZE 32 /* minimum number of bytes allocated for
|
||||
storing a string */
|
||||
#define RSTRSIZE 8 /* step size in enlarging the memory for
|
||||
the storage of a string */
|
||||
|
||||
|
||||
!File: target_sizes.h
|
||||
#define MAXSIZE 8 /* the maximum of the SZ_* constants */
|
||||
|
||||
/* target machine sizes */
|
||||
#define SZ_CHAR (arith)1
|
||||
#define SZ_SHORT (arith)2
|
||||
#define SZ_WORD (arith)4
|
||||
#define SZ_INT (arith)4
|
||||
#define SZ_LONG (arith)4
|
||||
#ifndef NOFLOAT
|
||||
#define SZ_FLOAT (arith)4
|
||||
#define SZ_DOUBLE (arith)8
|
||||
#endif NOFLOAT
|
||||
#define SZ_POINTER (arith)4
|
||||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT SZ_SHORT
|
||||
#define AL_WORD SZ_WORD
|
||||
#define AL_INT SZ_WORD
|
||||
#define AL_LONG SZ_WORD
|
||||
#ifndef NOFLOAT
|
||||
#define AL_FLOAT SZ_WORD
|
||||
#define AL_DOUBLE SZ_WORD
|
||||
#endif NOFLOAT
|
||||
#define AL_POINTER SZ_WORD
|
||||
#define AL_STRUCT 1
|
||||
#define AL_UNION 1
|
||||
|
||||
|
||||
!File: botch_free.h
|
||||
#undef BOTCH_FREE 1 /* when defined, botch freed memory, as a check */
|
||||
|
||||
|
||||
!File: dataflow.h
|
||||
#define DATAFLOW 1 /* produce some compile-time xref */
|
||||
|
||||
|
||||
!File: debug.h
|
||||
#undef DEBUG 1 /* perform various self-tests */
|
||||
|
||||
|
||||
!File: use_tmp.h
|
||||
#define USE_TMP 1 /* collect exa, exp, ina and inp commands
|
||||
and let them precede the rest of
|
||||
the generated compact code */
|
||||
|
||||
|
||||
!File: parbufsize.h
|
||||
#define PARBUFSIZE 1024
|
||||
|
||||
|
||||
!File: textsize.h
|
||||
#define ITEXTSIZE 8 /* 1st piece of memory for repl. text */
|
||||
#define RTEXTSIZE 8 /* stepsize for enlarging repl.text */
|
||||
|
||||
|
||||
!File: inputtype.h
|
||||
#undef INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: nopp.h
|
||||
#undef NOPP 1 /* if NOT defined, use built-int preprocessor */
|
||||
|
||||
|
||||
!File: nobitfield.h
|
||||
#undef NOBITFIELD 1 /* if NOT defined, implement bitfields */
|
||||
|
||||
|
||||
!File: spec_arith.h
|
||||
/* describes internal compiler arithmetics */
|
||||
#undef SPECIAL_ARITHMETICS /* something different from native long */
|
||||
|
||||
|
||||
!File: static.h
|
||||
#define GSTATIC /* for large global "static" arrays */
|
||||
|
||||
|
||||
!File: nofloat.h
|
||||
#undef NOFLOAT 1 /* if NOT defined, floats are implemented */
|
||||
|
||||
|
||||
!File: noRoption.h
|
||||
#undef NOROPTION 1 /* if NOT defined, R option is implemented */
|
||||
|
||||
|
||||
!File: nocross.h
|
||||
#undef NOCROSS 1 /* if NOT defined, cross compiler */
|
||||
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* M E M O R Y A L L O C A T I O N R O U T I N E S */
|
||||
|
||||
/* The allocation of memory in this program, which plays an important
|
||||
role in reading files, replacing macros and building expression
|
||||
trees, is not performed by malloc etc. The reason for having own
|
||||
memory allocation routines (malloc(), realloc() and free()) is
|
||||
plain: the garbage collection performed by the library functions
|
||||
malloc(), realloc() and free() costs a lot of time, while in most
|
||||
cases (on a VAX) the freeing and reallocation of memory is not
|
||||
necessary. The only reallocation done in this program is at
|
||||
building strings in memory. This means that the last
|
||||
(re-)allocated piece of memory can be extended.
|
||||
|
||||
The (basic) memory allocating routines offered by this memory
|
||||
handling package are:
|
||||
|
||||
char *malloc(n) : allocate n bytes
|
||||
char *realloc(ptr, n) : reallocate buffer to n bytes
|
||||
(works only if ptr was last allocated)
|
||||
free(ptr) : if ptr points to last allocated
|
||||
memory, this memory is re-allocatable
|
||||
Salloc(str, sz) : save string in malloc storage
|
||||
*/
|
||||
|
||||
#include <system.h>
|
||||
#include "myalloc.h" /* UF */
|
||||
#include "debug.h" /* UF */
|
||||
|
||||
#include "alloc.h"
|
||||
#include "assert.h"
|
||||
|
||||
#ifdef OWNALLOC
|
||||
char *sys_break();
|
||||
/* the following variables are used for book-keeping */
|
||||
static int nfreebytes = 0; /* # free bytes in sys_break space */
|
||||
static char *freeb; /* pointer to first free byte */
|
||||
static char *lastalloc; /* pointer to last malloced sp */
|
||||
static int lastnbytes; /* nr of bytes in last allocated */
|
||||
/* space */
|
||||
static char *firstfreeb = 0;
|
||||
|
||||
#endif OWNALLOC
|
||||
|
||||
char *
|
||||
Salloc(str, sz)
|
||||
register char str[];
|
||||
register int sz;
|
||||
{
|
||||
/* Salloc() is not a primitive function: it just allocates a
|
||||
piece of storage and copies a given string into it.
|
||||
*/
|
||||
char *res = Malloc(sz);
|
||||
register char *m = res;
|
||||
|
||||
while (sz--)
|
||||
*m++ = *str++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef OWNALLOC
|
||||
|
||||
#define ALIGN(m) (ALIGNSIZE * (((m) - 1) / ALIGNSIZE + 1))
|
||||
|
||||
char *
|
||||
malloc(n)
|
||||
unsigned n;
|
||||
{
|
||||
/* malloc() is a very simple malloc().
|
||||
*/
|
||||
n = ALIGN(n);
|
||||
if (nfreebytes < n) {
|
||||
register nbts = (n <= ALLOCSIZ) ? ALLOCSIZ : n;
|
||||
|
||||
if (!nfreebytes) {
|
||||
if ((freeb = sys_break(nbts)) == ILL_BREAK)
|
||||
fatal("out of memory");
|
||||
}
|
||||
else {
|
||||
if (sys_break(nbts) == ILL_BREAK)
|
||||
fatal("out of memory");
|
||||
}
|
||||
nfreebytes += nbts;
|
||||
}
|
||||
lastalloc = freeb;
|
||||
freeb = lastalloc + n;
|
||||
lastnbytes = n;
|
||||
nfreebytes -= n;
|
||||
return lastalloc;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
char *
|
||||
realloc(ptr, n)
|
||||
char *ptr;
|
||||
unsigned n;
|
||||
{
|
||||
/* realloc() is designed to append more bytes to the latest
|
||||
allocated piece of memory. However reallocation should be
|
||||
performed, even if the mentioned memory is not the latest
|
||||
allocated one, this situation will not occur. To do so,
|
||||
realloc should know how many bytes are allocated the last
|
||||
time for that piece of memory. ????
|
||||
*/
|
||||
register int nbytes = n;
|
||||
|
||||
ASSERT(ptr == lastalloc); /* security */
|
||||
nbytes -= lastnbytes; /* # bytes required */
|
||||
if (nbytes == 0) /* no extra bytes */
|
||||
return lastalloc;
|
||||
|
||||
/* if nbytes < 0: free last allocated bytes;
|
||||
if nbytes > 0: allocate more bytes
|
||||
*/
|
||||
if (nbytes > 0)
|
||||
nbytes = ALIGN(nbytes);
|
||||
if (nfreebytes < nbytes) {
|
||||
register int nbts = (nbytes < ALLOCSIZ) ? ALLOCSIZ : nbytes;
|
||||
if (sys_break(nbts) == ILL_BREAK)
|
||||
fatal("out of memory");
|
||||
nfreebytes += nbts;
|
||||
}
|
||||
freeb += nbytes; /* less bytes */
|
||||
lastnbytes += nbytes; /* change nr of last all. bytes */
|
||||
nfreebytes -= nbytes; /* less or more free bytes */
|
||||
return lastalloc;
|
||||
}
|
||||
|
||||
/* to ensure that the alloc library package will not be loaded: */
|
||||
/*ARGSUSED*/
|
||||
free(p)
|
||||
char *p;
|
||||
{}
|
||||
|
||||
init_mem()
|
||||
{
|
||||
firstfreeb = sys_break(0);
|
||||
/* align the first memory unit to ALIGNSIZE ??? */
|
||||
if ((long) firstfreeb % ALIGNSIZE != 0) {
|
||||
register char *fb = firstfreeb;
|
||||
|
||||
fb = (char *)ALIGN((long)fb);
|
||||
firstfreeb = sys_break(fb - firstfreeb);
|
||||
firstfreeb = fb;
|
||||
ASSERT((long)firstfreeb % ALIGNSIZE == 0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
mem_stat()
|
||||
{
|
||||
extern char options[];
|
||||
|
||||
if (options['m'])
|
||||
print("Total nr of bytes allocated: %d\n",
|
||||
sys_break(0) - firstfreeb);
|
||||
}
|
||||
#endif DEBUG
|
||||
#endif OWNALLOC
|
|
@ -1,16 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* PROGRAM'S INTERFACE TO MEMORY ALLOCATION ROUTINES */
|
||||
|
||||
/* This file serves as the interface between the program and the
|
||||
memory allocating routines.
|
||||
There are 3 memory allocation routines:
|
||||
char *Malloc(n) to allocate n bytes
|
||||
char *Salloc(str, n) to allocate n bytes
|
||||
and fill them with string str
|
||||
char *Realloc(str, n) reallocate the string at str to n bytes
|
||||
*/
|
||||
|
||||
extern char *Salloc(), *malloc(), *realloc();
|
||||
|
||||
#define Malloc(n) malloc((unsigned)(n))
|
||||
#define Srealloc(ptr,n) realloc(ptr, (unsigned)(n))
|
|
@ -1,23 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* C O D E - G E N E R A T O R D E F I N I T I O N S */
|
||||
|
||||
struct stat_block {
|
||||
struct stat_block *next;
|
||||
label st_break;
|
||||
label st_continue;
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct stat_block */
|
||||
/* ALLOCDEF "stat_block" */
|
||||
extern char *st_alloc();
|
||||
extern struct stat_block *h_stat_block;
|
||||
#define new_stat_block() ((struct stat_block *) \
|
||||
st_alloc((char **)&h_stat_block, sizeof(struct stat_block)))
|
||||
#define free_stat_block(p) st_free(p, h_stat_block, sizeof(struct stat_block))
|
||||
|
||||
|
||||
#define LVAL 0
|
||||
#define RVAL 1
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
|
@ -1,45 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* DEFINITION OF DECLARATOR DESCRIPTORS */
|
||||
|
||||
/* A 'declarator' consists of an idf and a linked list of
|
||||
language-defined unary operations: *, [] and (), called
|
||||
decl_unary's.
|
||||
*/
|
||||
|
||||
struct declarator {
|
||||
struct declarator *next;
|
||||
struct idf *dc_idf;
|
||||
struct decl_unary *dc_decl_unary;
|
||||
struct idstack_item *dc_fparams; /* params for function */
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct declarator */
|
||||
/* ALLOCDEF "declarator" */
|
||||
extern char *st_alloc();
|
||||
extern struct declarator *h_declarator;
|
||||
#define new_declarator() ((struct declarator *) \
|
||||
st_alloc((char **)&h_declarator, sizeof(struct declarator)))
|
||||
#define free_declarator(p) st_free(p, h_declarator, sizeof(struct declarator))
|
||||
|
||||
|
||||
#define NO_PARAMS ((struct idstack_item *) 0)
|
||||
|
||||
struct decl_unary {
|
||||
struct decl_unary *next;
|
||||
int du_fund; /* POINTER, ARRAY or FUNCTION */
|
||||
arith du_count; /* for ARRAYs only */
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct decl_unary */
|
||||
/* ALLOCDEF "decl_unary" */
|
||||
extern char *st_alloc();
|
||||
extern struct decl_unary *h_decl_unary;
|
||||
#define new_decl_unary() ((struct decl_unary *) \
|
||||
st_alloc((char **)&h_decl_unary, sizeof(struct decl_unary)))
|
||||
#define free_decl_unary(p) st_free(p, h_decl_unary, sizeof(struct decl_unary))
|
||||
|
||||
|
||||
extern struct type *declare_type();
|
||||
extern struct declarator null_declarator;
|
|
@ -1,23 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* DECLARATION SPECIFIER DEFINITION */
|
||||
|
||||
struct decspecs {
|
||||
struct decspecs *next;
|
||||
struct type *ds_type; /* single type */
|
||||
int ds_sc_given; /* 1 if the st. class is explicitly given */
|
||||
int ds_sc; /* storage class, given or implied */
|
||||
int ds_size; /* LONG, SHORT or 0 */
|
||||
int ds_unsigned; /* 0 or 1 */
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct decspecs */
|
||||
/* ALLOCDEF "decspecs" */
|
||||
extern char *st_alloc();
|
||||
extern struct decspecs *h_decspecs;
|
||||
#define new_decspecs() ((struct decspecs *) \
|
||||
st_alloc((char **)&h_decspecs, sizeof(struct decspecs)))
|
||||
#define free_decspecs(p) st_free(p, h_decspecs, sizeof(struct decspecs))
|
||||
|
||||
|
||||
extern struct decspecs null_decspecs;
|
|
@ -1,37 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* IDENTIFIER DEFINITION DESCRIPTOR */
|
||||
|
||||
struct def { /* for ordinary tags */
|
||||
struct def *next;
|
||||
int df_level;
|
||||
struct type *df_type;
|
||||
int df_sc; /* may be:
|
||||
GLOBAL, STATIC, EXTERN, IMPLICIT,
|
||||
TYPEDEF,
|
||||
FORMAL, AUTO,
|
||||
ENUM, LABEL
|
||||
*/
|
||||
int df_register; /* REG_NONE, REG_DEFAULT or REG_BONUS */
|
||||
char df_initialized; /* an initialization has been generated */
|
||||
char df_alloc; /* 0, ALLOC_SEEN or ALLOC_DONE */
|
||||
char df_used; /* set if idf is used */
|
||||
char df_formal_array; /* to warn if sizeof is taken */
|
||||
arith df_address;
|
||||
};
|
||||
|
||||
#define ALLOC_SEEN 1 /* an allocating declaration has been seen */
|
||||
#define ALLOC_DONE 2 /* the allocating declaration has been done */
|
||||
|
||||
#define REG_NONE 0 /* no register candidate */
|
||||
#define REG_DEFAULT 1 /* register candidate, not declared as such */
|
||||
#define REG_BONUS 10 /* register candidate, declared as such */
|
||||
|
||||
|
||||
/* allocation definitions of struct def */
|
||||
/* ALLOCDEF "def" */
|
||||
extern char *st_alloc();
|
||||
extern struct def *h_def;
|
||||
#define new_def() ((struct def *) \
|
||||
st_alloc((char **)&h_def, sizeof(struct def)))
|
||||
#define free_def(p) st_free(p, h_def, sizeof(struct def))
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* STRING MANIPULATION AND PRINT ROUTINES */
|
||||
|
||||
#include <system.h>
|
||||
#include "ssize.h"
|
||||
|
||||
char *long2str();
|
||||
|
||||
static
|
||||
integral(c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'b':
|
||||
return -2;
|
||||
case 'd':
|
||||
return 10;
|
||||
case 'o':
|
||||
return -8;
|
||||
case 'u':
|
||||
return -10;
|
||||
case 'x':
|
||||
return -16;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
format(buf, fmt, argp)
|
||||
char *buf, *fmt;
|
||||
char *argp;
|
||||
{
|
||||
register char *pf = fmt, *pa = argp;
|
||||
register char *pb = buf;
|
||||
|
||||
while (*pf) {
|
||||
if (*pf == '%') {
|
||||
register width, base, pad, npad;
|
||||
char *arg;
|
||||
char cbuf[2];
|
||||
char *badformat = "<bad format>";
|
||||
|
||||
/* get padder */
|
||||
if (*++pf == '0') {
|
||||
pad = '0';
|
||||
++pf;
|
||||
}
|
||||
else
|
||||
pad = ' ';
|
||||
|
||||
/* get width */
|
||||
width = 0;
|
||||
while (*pf >= '0' && *pf <= '9')
|
||||
width = 10 * width + *pf++ - '0';
|
||||
|
||||
/* get text and move pa */
|
||||
if (*pf == 's') {
|
||||
arg = *(char **)pa;
|
||||
pa += sizeof(char *);
|
||||
}
|
||||
else
|
||||
if (*pf == 'c') {
|
||||
cbuf[0] = * (char *) pa;
|
||||
cbuf[1] = '\0';
|
||||
pa += sizeof(int);
|
||||
arg = &cbuf[0];
|
||||
}
|
||||
else
|
||||
if (*pf == 'l') {
|
||||
/* alignment ??? */
|
||||
if (base = integral(*++pf)) {
|
||||
arg = long2str(*(long *)pa, base);
|
||||
pa += sizeof(long);
|
||||
}
|
||||
else {
|
||||
pf--;
|
||||
arg = badformat;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (base = integral(*pf)) {
|
||||
arg = long2str((long)*(int *)pa, base);
|
||||
pa += sizeof(int);
|
||||
}
|
||||
else
|
||||
if (*pf == '%')
|
||||
arg = "%";
|
||||
else
|
||||
arg = badformat;
|
||||
|
||||
npad = width - strlen(arg);
|
||||
|
||||
while (npad-- > 0)
|
||||
*pb++ = pad;
|
||||
|
||||
while (*pb++ = *arg++);
|
||||
pb--;
|
||||
pf++;
|
||||
}
|
||||
else
|
||||
*pb++ = *pf++;
|
||||
}
|
||||
return pb - buf;
|
||||
}
|
||||
|
||||
doprnt(fp, fmt, argp)
|
||||
File *fp;
|
||||
char *fmt;
|
||||
int argp[];
|
||||
{
|
||||
char buf[SSIZE];
|
||||
|
||||
sys_write(fp, buf, format(buf, fmt, (char *)argp));
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
printf(fmt, args)
|
||||
char *fmt;
|
||||
char args;
|
||||
{
|
||||
char buf[SSIZE];
|
||||
|
||||
sys_write(STDOUT, buf, format(buf, fmt, &args));
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
fprintf(fp, fmt, args)
|
||||
File *fp;
|
||||
char *fmt;
|
||||
char args;
|
||||
{
|
||||
char buf[SSIZE];
|
||||
|
||||
sys_write(fp, buf, format(buf, fmt, &args));
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
char *
|
||||
sprintf(buf, fmt, args)
|
||||
char *buf, *fmt;
|
||||
char args;
|
||||
{
|
||||
buf[format(buf, fmt, &args)] = '\0';
|
||||
return buf;
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* EM CODE OUTPUT ROUTINES */
|
||||
|
||||
#define CMODE 0644
|
||||
#define MAX_ARG_CNT 32
|
||||
|
||||
#include "em.h"
|
||||
#include <system.h>
|
||||
#include "arith.h"
|
||||
#include "label.h"
|
||||
|
||||
/*
|
||||
putbyte(), C_open() and C_close() are the basic routines for
|
||||
respectively write on, open and close the output file.
|
||||
The put_*() functions serve as formatting functions of the
|
||||
various EM language constructs.
|
||||
See "Description of a Machine Architecture for use with
|
||||
Block Structured Languages" par. 11.2 for the meaning of these
|
||||
names.
|
||||
*/
|
||||
|
||||
/* supply a kind of buffered output */
|
||||
#define flush(x) sys_write(ofp, &obuf[0], x)
|
||||
|
||||
static char obuf[BUFSIZ];
|
||||
static char *opp = &obuf[0];
|
||||
File *ofp = 0;
|
||||
|
||||
putbyte(b) /* shouldn't putbyte() be a macro ??? (EB) */
|
||||
int b;
|
||||
{
|
||||
if (opp >= &obuf[BUFSIZ]) { /* flush if buffer overflows */
|
||||
if (flush(BUFSIZ) == 0)
|
||||
sys_stop(S_ABORT);
|
||||
opp = &obuf[0];
|
||||
}
|
||||
*opp++ = (char) b;
|
||||
}
|
||||
|
||||
C_init(wsize, psize)
|
||||
arith wsize, psize;
|
||||
{}
|
||||
|
||||
C_open(nm) /* open file for compact code output */
|
||||
char *nm;
|
||||
{
|
||||
if (nm == 0)
|
||||
ofp = STDOUT; /* standard output */
|
||||
else
|
||||
if (sys_open(nm, OP_WRITE, &ofp) == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
C_close()
|
||||
{
|
||||
if (flush(opp - &obuf[0]) == 0)
|
||||
sys_stop(S_ABORT);
|
||||
opp = obuf; /* reset opp */
|
||||
if (ofp != STDOUT)
|
||||
sys_close(ofp);
|
||||
ofp = 0;
|
||||
}
|
||||
|
||||
C_busy()
|
||||
{
|
||||
return ofp != 0; /* true if code is being generated */
|
||||
}
|
||||
|
||||
/*** the compact code generating routines ***/
|
||||
#define fit16i(x) ((x) >= (long)0xFFFF8000 && (x) <= (long)0x00007FFF)
|
||||
#define fit8u(x) ((x) <= 0xFF) /* x is already unsigned */
|
||||
|
||||
put_ilb(l)
|
||||
label l;
|
||||
{
|
||||
if (fit8u(l)) {
|
||||
put8(sp_ilb1);
|
||||
put8((int)l);
|
||||
}
|
||||
else {
|
||||
put8(sp_ilb2);
|
||||
put16(l);
|
||||
}
|
||||
}
|
||||
|
||||
put_dlb(l)
|
||||
label l;
|
||||
{
|
||||
if (fit8u(l)) {
|
||||
put8(sp_dlb1);
|
||||
put8((int)l);
|
||||
}
|
||||
else {
|
||||
put8(sp_dlb2);
|
||||
put16(l);
|
||||
}
|
||||
}
|
||||
|
||||
put_cst(l)
|
||||
arith l;
|
||||
{
|
||||
if (l >= (arith) -sp_zcst0 && l < (arith) (sp_ncst0 - sp_zcst0)) {
|
||||
/* we can convert 'l' to an int because its value
|
||||
can be stored in a byte.
|
||||
*/
|
||||
put8((int) l + (sp_zcst0 + sp_fcst0));
|
||||
}
|
||||
else
|
||||
if (fit16i(l)) { /* the cast from long to int causes no trouble here */
|
||||
put8(sp_cst2);
|
||||
put16((int) l);
|
||||
}
|
||||
else {
|
||||
put8(sp_cst4);
|
||||
put32(l);
|
||||
}
|
||||
}
|
||||
|
||||
put_doff(l, v)
|
||||
label l;
|
||||
arith v;
|
||||
{
|
||||
if (v == 0)
|
||||
put_dlb(l);
|
||||
else {
|
||||
put8(sp_doff);
|
||||
put_dlb(l);
|
||||
put_cst(v);
|
||||
}
|
||||
}
|
||||
|
||||
put_noff(s, v)
|
||||
char *s;
|
||||
arith v;
|
||||
{
|
||||
if (v == 0)
|
||||
put_dnam(s);
|
||||
else {
|
||||
put8(sp_doff);
|
||||
put_dnam(s);
|
||||
put_cst(v);
|
||||
}
|
||||
}
|
||||
|
||||
put_dnam(s)
|
||||
char *s;
|
||||
{
|
||||
put8(sp_dnam);
|
||||
put_str(s);
|
||||
}
|
||||
|
||||
put_pnam(s)
|
||||
char *s;
|
||||
{
|
||||
put8(sp_pnam);
|
||||
put_str(s);
|
||||
}
|
||||
|
||||
#ifdef ____
|
||||
put_fcon(s, sz)
|
||||
char *s;
|
||||
arith sz;
|
||||
{
|
||||
put8(sp_fcon);
|
||||
put_cst(sz);
|
||||
put_str(s);
|
||||
}
|
||||
#endif ____
|
||||
|
||||
put_wcon(sp, v, sz) /* sp_icon, sp_ucon or sp_fcon with int repr */
|
||||
int sp;
|
||||
char *v;
|
||||
arith sz;
|
||||
{
|
||||
/* how 'bout signextension int --> long ??? */
|
||||
put8(sp);
|
||||
put_cst(sz);
|
||||
put_str(v);
|
||||
}
|
||||
|
||||
put_str(s)
|
||||
char *s;
|
||||
{
|
||||
register int len;
|
||||
|
||||
put_cst((arith) (len = strlen(s)));
|
||||
while (--len >= 0)
|
||||
put8(*s++);
|
||||
}
|
||||
|
||||
put_cstr(s)
|
||||
char *s;
|
||||
{
|
||||
register int len = prepare_string(s);
|
||||
|
||||
put8(sp_scon);
|
||||
put_cst((arith) len);
|
||||
while (--len >= 0)
|
||||
put8(*s++);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* DESCRIPTION OF INTERFACE TO EM CODE GENERATING ROUTINES */
|
||||
|
||||
#include "proc_intf.h" /* use macros or functions */
|
||||
|
||||
/* include the EM description files */
|
||||
#include <em_spec.h>
|
||||
#include <em_pseu.h>
|
||||
#include <em_mes.h>
|
||||
#include <em_mnem.h>
|
||||
#include <em_reg.h>
|
||||
|
||||
/* macros used in the definitions of the interface functions C_* */
|
||||
#define OP(x) put_op(x)
|
||||
#define CST(x) put_cst(x)
|
||||
#define DCST(x) put_cst(x)
|
||||
#define CSTR(x) put_cstr(x)
|
||||
#define PS(x) put_ps(x)
|
||||
#define DLB(x) put_dlb(x)
|
||||
#define ILB(x) put_ilb(x)
|
||||
#define NOFF(x,y) put_noff((x), (y))
|
||||
#define DOFF(x,y) put_doff((x), (y))
|
||||
#define PNAM(x) put_pnam(x)
|
||||
#define DNAM(x) put_dnam(x)
|
||||
#define CEND() put_cend()
|
||||
#define WCON(x,y,z) put_wcon((x), (y), (z))
|
||||
#define FCON(x,y) put_fcon((x), (y))
|
||||
|
||||
/* variants of primitive "putbyte" */
|
||||
#define put8(x) putbyte(x) /* defined in "em.c" */
|
||||
#define put16(x) (put8((int) x), put8((int) (x >> 8)))
|
||||
#define put32(x) (put16((int) x), put16((int) (x >> 16)))
|
||||
#define put_cend() put8(sp_cend)
|
||||
#define put_op(x) put8(x)
|
||||
#define put_ps(x) put8(x)
|
||||
|
||||
/* user interface */
|
||||
#define C_magic() put16(sp_magic) /* EM magic word */
|
||||
|
||||
#ifndef PROC_INTF
|
||||
#include "writeem.h"
|
||||
#endif PROC_INTF
|
|
@ -1,136 +0,0 @@
|
|||
% emcode definitions for the CEM compiler -- intermediate code
|
||||
C_adf(p) | arith p; | OP(op_adf), CST(p)
|
||||
C_adi(p) | arith p; | OP(op_adi), CST(p)
|
||||
C_adp(p) | arith p; | OP(op_adp), CST(p)
|
||||
C_ads(p) | arith p; | OP(op_ads), CST(p)
|
||||
C_adu(p) | arith p; | OP(op_adu), CST(p)
|
||||
C_and(p) | arith p; | OP(op_and), CST(p)
|
||||
C_asp(p) | arith p; | OP(op_asp), CST(p)
|
||||
C_bra(l) | label l; | OP(op_bra), CST((arith)l)
|
||||
C_cai() | | OP(op_cai)
|
||||
C_cal(p) | char *p; | OP(op_cal), PNAM(p)
|
||||
C_cff() | | OP(op_cff)
|
||||
C_cfi() | | OP(op_cfi)
|
||||
C_cfu() | | OP(op_cfu)
|
||||
C_cif() | | OP(op_cif)
|
||||
C_cii() | | OP(op_cii)
|
||||
C_ciu() | | OP(op_ciu)
|
||||
C_cmf(p) | arith p; | OP(op_cmf), CST(p)
|
||||
C_cmi(p) | arith p; | OP(op_cmi), CST(p)
|
||||
C_cmp() | | OP(op_cmp)
|
||||
C_cmu(p) | arith p; | OP(op_cmu), CST(p)
|
||||
C_com(p) | arith p; | OP(op_com), CST(p)
|
||||
C_csa(p) | arith p; | OP(op_csa), CST(p)
|
||||
C_csb(p) | arith p; | OP(op_csb), CST(p)
|
||||
C_cuf() | | OP(op_cuf)
|
||||
C_cui() | | OP(op_cui)
|
||||
C_cuu() | | OP(op_cuu)
|
||||
C_dup(p) | arith p; | OP(op_dup), CST(p)
|
||||
C_dvf(p) | arith p; | OP(op_dvf), CST(p)
|
||||
C_dvi(p) | arith p; | OP(op_dvi), CST(p)
|
||||
C_dvu(p) | arith p; | OP(op_dvu), CST(p)
|
||||
C_fil_dlb(l, o) | label l; arith o; | OP(op_fil), DOFF(l, o)
|
||||
C_ior(p) | arith p; | OP(op_ior), CST(p)
|
||||
C_lae_dnam(p, o) | char *p; arith o; | OP(op_lae), NOFF(p, o)
|
||||
C_lae_dlb(l, o) | label l; arith o; | OP(op_lae), DOFF(l, o)
|
||||
C_lal(p) | arith p; | OP(op_lal), CST(p)
|
||||
C_ldc(p) | arith p; | OP(op_ldc), DCST(p)
|
||||
C_lde_dnam(p, o) | char *p; arith o; | OP(op_lde), NOFF(p, o)
|
||||
C_lde_dlb(l, o) | label l; arith o; | OP(op_lde), DOFF(l, o)
|
||||
C_ldl(p) | arith p; | OP(op_ldl), CST(p)
|
||||
C_lfr(p) | arith p; | OP(op_lfr), CST(p)
|
||||
C_lin(p) | arith p; | OP(op_lin), CST(p)
|
||||
C_loc(p) | arith p; | OP(op_loc), CST(p)
|
||||
C_loe_dnam(p, o) | char *p; arith o; | OP(op_loe), NOFF(p, o)
|
||||
C_loe_dlb(l, o) | label l; arith o; | OP(op_loe), DOFF(l, o)
|
||||
C_loi(p) | arith p; | OP(op_loi), CST(p)
|
||||
C_lol(p) | arith p; | OP(op_lol), CST(p)
|
||||
C_lor(p) | arith p; | OP(op_lor), CST(p)
|
||||
C_lpi(p) | char *p; | OP(op_lpi), PNAM(p)
|
||||
C_mlf(p) | arith p; | OP(op_mlf), CST(p)
|
||||
C_mli(p) | arith p; | OP(op_mli), CST(p)
|
||||
C_mlu(p) | arith p; | OP(op_mlu), CST(p)
|
||||
C_ngf(p) | arith p; | OP(op_ngf), CST(p)
|
||||
C_ngi(p) | arith p; | OP(op_ngi), CST(p)
|
||||
C_ret(p) | arith p; | OP(op_ret), CST(p)
|
||||
C_rmi(p) | arith p; | OP(op_rmi), CST(p)
|
||||
C_rmu(p) | arith p; | OP(op_rmu), CST(p)
|
||||
C_sbf(p) | arith p; | OP(op_sbf), CST(p)
|
||||
C_sbi(p) | arith p; | OP(op_sbi), CST(p)
|
||||
C_sbs(p) | arith p; | OP(op_sbs), CST(p)
|
||||
C_sbu(p) | arith p; | OP(op_sbu), CST(p)
|
||||
C_sde_dnam(p, o) | char *p; arith o; | OP(op_sde), NOFF(p, o)
|
||||
C_sde_dlb(l, o) | label l; arith o; | OP(op_sde), DOFF(l, o)
|
||||
C_sdl(p) | arith p; | OP(op_sdl), CST(p)
|
||||
C_sli(p) | arith p; | OP(op_sli), CST(p)
|
||||
C_slu(p) | arith p; | OP(op_slu), CST(p)
|
||||
C_sri(p) | arith p; | OP(op_sri), CST(p)
|
||||
C_sru(p) | arith p; | OP(op_sru), CST(p)
|
||||
C_ste_dnam(p, o) | char *p; arith o; | OP(op_ste), NOFF(p, o)
|
||||
C_ste_dlb(l, o) | label l; arith o; | OP(op_ste), DOFF(l, o)
|
||||
C_sti(p) | arith p; | OP(op_sti), CST(p)
|
||||
C_stl(p) | arith p; | OP(op_stl), CST(p)
|
||||
C_xor(p) | arith p; | OP(op_xor), CST(p)
|
||||
C_zeq(l) | label l; | OP(op_zeq), CST((arith)l)
|
||||
C_zge(l) | label l; | OP(op_zge), CST((arith)l)
|
||||
C_zgt(l) | label l; | OP(op_zgt), CST((arith)l)
|
||||
C_zle(l) | label l; | OP(op_zle), CST((arith)l)
|
||||
C_zlt(l) | label l; | OP(op_zlt), CST((arith)l)
|
||||
C_zne(l) | label l; | OP(op_zne), CST((arith)l)
|
||||
%
|
||||
C_df_dlb(l) | label l; | DLB(l)
|
||||
C_df_dnam(s) | char *s; | DNAM(s)
|
||||
C_df_ilb(l) | label l; | ILB(l)
|
||||
%
|
||||
C_bss_cst(n, w, i) | arith n, w; int i; |
|
||||
PS(ps_bss), DCST(n), CST(w), CST((arith)i)
|
||||
%
|
||||
C_con_icon(val, siz) | char *val; arith siz; |
|
||||
PS(ps_con), WCON(sp_icon, val, siz), CEND()
|
||||
C_con_ucon(val, siz) | char *val; arith siz; |
|
||||
PS(ps_con), WCON(sp_ucon, val, siz), CEND()
|
||||
C_con_fcon(val, siz) | char *val; arith siz; |
|
||||
PS(ps_con), WCON(sp_fcon, val, siz), CEND()
|
||||
C_con_scon(str, siz) | char *str; arith siz; | PS(ps_con), CSTR(str), CEND()
|
||||
C_con_dnam(str, val) | char *str; arith val; |
|
||||
PS(ps_con), NOFF(str, val), CEND()
|
||||
C_con_dlb(l, val) | label l; arith val; |
|
||||
PS(ps_con), DOFF(l, val), CEND()
|
||||
C_con_pnam(str) | char *str; | PS(ps_con), PNAM(str), CEND()
|
||||
%
|
||||
C_rom_cst(l) | arith l; | PS(ps_rom), CST(l), CEND()
|
||||
C_rom_icon(val, siz) | char *val; arith siz; |
|
||||
PS(ps_rom), WCON(sp_icon, val, siz), CEND()
|
||||
C_rom_fcon(val, siz) | char *val; arith siz; |
|
||||
PS(ps_rom), WCON(sp_fcon, val, siz), CEND()
|
||||
C_rom_ilb(l) | label l; | PS(ps_rom), ILB(l), CEND()
|
||||
%
|
||||
C_cst(l) | arith l; | CST(l)
|
||||
C_icon(val, siz) | char *val; arith siz; | WCON(sp_icon, val, siz)
|
||||
C_ucon(val, siz) | char *val; arith siz; | WCON(sp_ucon, val, siz)
|
||||
C_fcon(val, siz) | char *val; arith siz; | WCON(sp_fcon, val, siz)
|
||||
C_scon(str, siz) | char *str; arith siz; | CSTR(str)
|
||||
C_dnam(str, val) | char *str; arith val; | NOFF(str, val)
|
||||
C_dlb(l, val) | label l; arith val; | DOFF(l, val)
|
||||
C_pnam(str) | char *str; | PNAM(str)
|
||||
C_ilb(l) | label l; | ILB(l)
|
||||
%
|
||||
C_pro_narg(p1) | char *p1; | PS(ps_pro), PNAM(p1), CEND()
|
||||
C_end(l) | arith l; | PS(ps_end), CST(l)
|
||||
%
|
||||
C_exa(s) | char *s; | PS(ps_exa), DNAM(s)
|
||||
C_exp(s) | char *s; | PS(ps_exp), PNAM(s)
|
||||
C_ina_pt(l) | label l; | PS(ps_ina), DLB(l)
|
||||
C_ina(s) | char *s; | PS(ps_ina), DNAM(s)
|
||||
C_inp(s) | char *s; | PS(ps_inp), PNAM(s)
|
||||
%
|
||||
C_ms_err() | | PS(ps_mes), CST((arith)ms_err), CEND()
|
||||
C_ms_emx(p1, p2) | arith p1, p2; |
|
||||
PS(ps_mes), CST((arith)ms_emx), CST(p1), CST(p2), CEND()
|
||||
C_ms_reg(a, b, c, d) | arith a, b; int c, d; |
|
||||
PS(ps_mes), CST((arith)ms_reg), CST(a), CST(b), CST((arith)c), CST((arith)d), CEND()
|
||||
C_ms_src(l, s) | arith l; char *s; |
|
||||
PS(ps_mes), CST((arith)ms_src), CST(l), CSTR(s), CEND()
|
||||
C_ms_flt() | | PS(ps_mes), CST((arith)ms_flt), CEND()
|
||||
C_ms_par(l) | arith l; | PS(ps_mes), CST((arith)ms_par), CST(l), CEND()
|
||||
C_ms_gto() | | PS(ps_mes), CST((arith)ms_gto), CEND()
|
|
@ -1,102 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* EXPRESSION DESCRIPTOR */
|
||||
|
||||
/* What we want to define is the struct expr, but since it contains
|
||||
a union of various goodies, we define them first; so be patient.
|
||||
*/
|
||||
|
||||
struct value {
|
||||
struct idf *vl_idf; /* idf of an external name or 0 */
|
||||
arith vl_value; /* constant, or offset if idf != 0 */
|
||||
};
|
||||
|
||||
struct string {
|
||||
char *sg_value; /* string of characters repr. the constant */
|
||||
label sg_datlab; /* global data-label */
|
||||
};
|
||||
|
||||
struct floating {
|
||||
char *fl_value; /* pointer to string repr. the fp const. */
|
||||
label fl_datlab; /* global data_label */
|
||||
};
|
||||
|
||||
struct oper {
|
||||
struct type *op_type; /* resulting type of the operation */
|
||||
struct expr *op_left;
|
||||
int op_oper; /* the symbol of the operator */
|
||||
struct expr *op_right;
|
||||
};
|
||||
|
||||
/* The following constants indicate the class of the expression: */
|
||||
#define Value 0 /* it is a value known at load time */
|
||||
#define String 1 /* it is a string constant */
|
||||
#define Float 2 /* it is a floating point constant */
|
||||
#define Oper 3 /* it is a run-time expression */
|
||||
#define Type 4 /* only its type is relevant */
|
||||
|
||||
struct expr {
|
||||
struct expr *next;
|
||||
char *ex_file; /* the file it (probably) comes from */
|
||||
unsigned int ex_line; /* the line it (probably) comes from */
|
||||
struct type *ex_type;
|
||||
char ex_lvalue;
|
||||
char ex_flags;
|
||||
int ex_class;
|
||||
int ex_depth;
|
||||
union {
|
||||
struct value ex_value;
|
||||
struct string ex_string;
|
||||
struct floating ex_float;
|
||||
struct oper ex_oper;
|
||||
} ex_object;
|
||||
};
|
||||
|
||||
/* some abbreviated selections */
|
||||
#define VL_VALUE ex_object.ex_value.vl_value
|
||||
#define VL_IDF ex_object.ex_value.vl_idf
|
||||
#define SG_VALUE ex_object.ex_string.sg_value
|
||||
#define SG_DATLAB ex_object.ex_string.sg_datlab
|
||||
#define FL_VALUE ex_object.ex_float.fl_value
|
||||
#define FL_DATLAB ex_object.ex_float.fl_datlab
|
||||
#define OP_TYPE ex_object.ex_oper.op_type
|
||||
#define OP_LEFT ex_object.ex_oper.op_left
|
||||
#define OP_OPER ex_object.ex_oper.op_oper
|
||||
#define OP_RIGHT ex_object.ex_oper.op_right
|
||||
|
||||
#define EXPRTYPE(e) ((e)->ex_type->tp_fund)
|
||||
|
||||
/* An expression is a `load-time constant' if it is of the form
|
||||
<idf> +/- <integral> or <integral>;
|
||||
it is a `compile-time constant' if it is an <integral>.
|
||||
*/
|
||||
#define is_ld_cst(e) ((e)->ex_lvalue == 0 && (e)->ex_class == Value)
|
||||
#define is_cp_cst(e) (is_ld_cst(e) && (e)->VL_IDF == 0)
|
||||
|
||||
/* a floating constant expression ?
|
||||
*/
|
||||
#define is_fp_cst(e) ((e)->ex_class == Float)
|
||||
|
||||
/* some bits for the ex_flag field, to keep track of various
|
||||
interesting properties of an expression.
|
||||
*/
|
||||
#define EX_SIZEOF 001 /* contains sizeof operator */
|
||||
#define EX_CAST 002 /* contains cast */
|
||||
#define EX_LOGICAL 004 /* contains logical operator */
|
||||
#define EX_COMMA 010 /* contains expression comma */
|
||||
#define EX_PARENS 020 /* the top level is parenthesized */
|
||||
|
||||
#define NILEXPR ((struct expr *)0)
|
||||
|
||||
extern struct expr *intexpr(), *new_oper();
|
||||
|
||||
|
||||
/* allocation definitions of struct expr */
|
||||
/* ALLOCDEF "expr" */
|
||||
extern char *st_alloc();
|
||||
extern struct expr *h_expr;
|
||||
#define new_expr() ((struct expr *) \
|
||||
st_alloc((char **)&h_expr, sizeof(struct expr)))
|
||||
#define free_expr(p) st_free(p, h_expr, sizeof(struct expr))
|
||||
|
||||
|
||||
#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)
|
|
@ -1,20 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* FIELD DESCRIPTOR */
|
||||
|
||||
struct field { /* for field specifiers */
|
||||
struct field *next;
|
||||
arith fd_mask;
|
||||
int fd_shift;
|
||||
int fd_width;
|
||||
struct sdef *fd_sdef; /* upward pointer */
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct field */
|
||||
/* ALLOCDEF "field" */
|
||||
extern char *st_alloc();
|
||||
extern struct field *h_field;
|
||||
#define new_field() ((struct field *) \
|
||||
st_alloc((char **)&h_field, sizeof(struct field)))
|
||||
#define free_field(p) st_free(p, h_field, sizeof(struct field))
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* IDENTIFIER DESCRIPTOR */
|
||||
|
||||
#include "nopp.h"
|
||||
|
||||
/* Since the % operation in the calculation of the hash function
|
||||
turns out to be expensive, it is replaced by the cheaper XOR (^).
|
||||
Each character of the identifier is xored with an 8-bit mask which
|
||||
depends on the position of the character; the sum of these results
|
||||
is the hash value. The random masks are obtained from a
|
||||
congruence generator in idf.c.
|
||||
*/
|
||||
|
||||
#define HASHSIZE 256 /* must be a power of 2 */
|
||||
#define HASH_X 0253 /* Knuth's X */
|
||||
#define HASH_A 77 /* Knuth's a */
|
||||
#define HASH_C 153 /* Knuth's c */
|
||||
|
||||
extern char hmask[]; /* the random masks */
|
||||
#define HASHMASK (HASHSIZE-1) /* since it is a power of 2 */
|
||||
#define STARTHASH() (0)
|
||||
#define ENHASH(hs,ch,ps) (hs + (ch ^ hmask[ps]))
|
||||
#define STOPHASH(hs) (hs & HASHMASK)
|
||||
|
||||
struct idstack_item { /* stack of identifiers */
|
||||
struct idstack_item *next;
|
||||
struct idf *is_idf;
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct idstack_item */
|
||||
/* ALLOCDEF "idstack_item" */
|
||||
extern char *st_alloc();
|
||||
extern struct idstack_item *h_idstack_item;
|
||||
#define new_idstack_item() ((struct idstack_item *) \
|
||||
st_alloc((char **)&h_idstack_item, sizeof(struct idstack_item)))
|
||||
#define free_idstack_item(p) st_free(p, h_idstack_item, sizeof(struct idstack_item))
|
||||
|
||||
|
||||
struct idf {
|
||||
struct idf *next;
|
||||
char *id_text;
|
||||
#ifndef NOPP
|
||||
struct macro *id_macro;
|
||||
int id_resmac; /* if nonzero: keyword of macroproc. */
|
||||
#endif NOPP
|
||||
int id_reserved; /* non-zero for reserved words */
|
||||
struct def *id_def; /* variables, typedefs, enum-constants */
|
||||
struct sdef *id_sdef; /* selector tags */
|
||||
struct tag *id_struct; /* struct and union tags */
|
||||
struct tag *id_enum; /* enum tags */
|
||||
int id_special; /* special action needed at occurrence */
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct idf */
|
||||
/* ALLOCDEF "idf" */
|
||||
extern char *st_alloc();
|
||||
extern struct idf *h_idf;
|
||||
#define new_idf() ((struct idf *) \
|
||||
st_alloc((char **)&h_idf, sizeof(struct idf)))
|
||||
#define free_idf(p) st_free(p, h_idf, sizeof(struct idf))
|
||||
|
||||
|
||||
extern struct idf *str2idf(), *idf_hashed();
|
||||
|
||||
extern int level;
|
||||
extern struct idf *gen_idf();
|
|
@ -1,624 +0,0 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* CODE FOR THE INITIALISATION OF GLOBAL VARIABLES */
|
||||
|
||||
#include "nofloat.h"
|
||||
#include <em.h>
|
||||
#include "debug.h"
|
||||
#include <alloc.h>
|
||||
#include "nobitfield.h"
|
||||
#include "arith.h"
|
||||
#include "align.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "type.h"
|
||||
#include "struct.h"
|
||||
#include "field.h"
|
||||
#include "assert.h"
|
||||
#include "Lpars.h"
|
||||
#include "class.h"
|
||||
#include "sizes.h"
|
||||
#include "idf.h"
|
||||
#include "level.h"
|
||||
#include "def.h"
|
||||
|
||||
#define con_nullbyte() C_con_ucon("0", (arith)1)
|
||||
|
||||
char *symbol2str();
|
||||
char *long2str();
|
||||
char *strncpy();
|
||||
struct expr *do_array(), *do_struct(), *IVAL();
|
||||
extern char options[];
|
||||
|
||||
/* do_ival() performs the initialisation of a global variable
|
||||
of type tp with the initialisation expression expr by calling IVAL().
|
||||
Guided by type tp, the expression is evaluated.
|
||||
*/
|
||||
do_ival(tpp, ex)
|
||||
struct type **tpp;
|
||||
struct expr *ex;
|
||||
{
|
||||
if (IVAL(tpp, ex) != 0)
|
||||
too_many_initialisers(ex);
|
||||
}
|
||||
|
||||
/* IVAL() recursively guides the initialisation expression through the
|
||||
different routines for the different types of initialisation:
|
||||
- array initialisation
|
||||
- struct initialisation
|
||||
- fundamental type initialisation
|
||||
Upto now, the initialisation of a union is not allowed!
|
||||
An initialisation expression tree consists of normal expressions
|
||||
which can be joined together by ',' nodes, which operator acts
|
||||
like the lisp function "cons" to build lists.
|
||||
IVAL() returns a pointer to the remaining expression tree.
|
||||
*/
|
||||
struct expr *
|
||||
IVAL(tpp, ex)
|
||||
struct type **tpp; /* type of global variable */
|
||||
register struct expr *ex; /* initialiser expression */
|
||||
{
|
||||
register struct type *tp = *tpp;
|
||||
|
||||
switch (tp->tp_fund) {
|
||||
case ARRAY: /* array initialisation */
|
||||
if (valid_type(tp->tp_up, "array element") == 0)
|
||||
return 0;
|
||||
if (ISCOMMA(ex)) /* list of initialisation expressions */
|
||||
return do_array(ex, tpp);
|
||||
if (tp->tp_up->tp_fund == CHAR && ex->ex_class == String)
|
||||
/* initialisation like char s[] = "I am a string" */
|
||||
ch_array(tpp, ex);
|
||||
else /* " int i[24] = 12;" */
|
||||
check_and_pad(ex, tpp);
|
||||
break;
|
||||
case STRUCT: /* struct initialisation */
|
||||
if (valid_type(tp, "struct") == 0)
|
||||
return 0;
|
||||
if (ISCOMMA(ex)) /* list of initialisation expressions */
|
||||
return do_struct(ex, tp);
|
||||
check_and_pad(ex, tpp); /* "struct foo f = 12;" */
|
||||
break;
|
||||
case UNION:
|
||||
error("union initialisation not allowed");
|
||||
break;
|
||||
case ERRONEOUS:
|
||||
break;
|
||||
default: /* fundamental type */
|
||||
if (ISCOMMA(ex)) { /* " int i = {12};" */
|
||||
if (IVAL(tpp, ex->OP_LEFT) != 0)
|
||||
too_many_initialisers(ex);
|
||||
/* return remainings of the list for the
|
||||
other members of the aggregate, if this
|
||||
item belongs to an aggregate.
|
||||
*/
|
||||
return ex->OP_RIGHT;
|
||||
}
|
||||
check_ival(ex, tp); /* "int i = 12;" */
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do_array() initialises the members of an array described
|
||||
by type tp with the expressions in expr.
|
||||
Two important cases:
|
||||
- the number of members is known
|
||||
- the number of members is not known
|
||||
In the latter case, do_array() digests the whole expression
|
||||
tree it is given.
|
||||
In the former case, do_array() eats as many members from
|
||||
the expression tree as are needed for the array.
|
||||
If there are not sufficient members for the array, the remaining
|
||||
members are padded with zeroes
|
||||
*/
|
||||
struct expr *
|
||||
do_array(ex, tpp)
|
||||
register struct expr *ex;
|
||||
struct type **tpp;
|
||||
{
|
||||
register struct type *tp = *tpp;
|
||||
register arith elem_count;
|
||||
|
||||
ASSERT(tp->tp_fund == ARRAY && ISCOMMA(ex));
|
||||
/* the following test catches initialisations like
|
||||
char c[] = {"just a string"};
|
||||
or
|
||||
char d[] = {{"just another string"}};
|
||||
The use of the brackets causes this problem.
|
||||
Note: although the implementation of such initialisations
|
||||
is completely foolish, we did it!! (no applause, thank you)
|
||||
*/
|
||||
if (tp->tp_up->tp_fund == CHAR) {
|
||||
register struct expr *f = ex->OP_LEFT, *g = NILEXPR;
|
||||
|
||||
while (ISCOMMA(f)) { /* eat the brackets!!! */
|
||||
g = f;
|
||||
f = f->OP_LEFT;
|
||||
}
|
||||
if (f->ex_class == String) { /* hallelujah, it's a string! */
|
||||
ch_array(tpp, f);
|
||||
return g ? g->OP_RIGHT : ex->OP_RIGHT;
|
||||
}
|
||||
/* else: just go on with the next part of this function */
|
||||
if (g != 0)
|
||||
ex = g;
|
||||
}
|
||||
if (tp->tp_size == (arith)-1) {
|
||||
/* declared with unknown size: [] */
|
||||
for (elem_count = 0; ex; elem_count++) {
|
||||
/* eat whole initialisation expression */
|
||||
if (ISCOMMA(ex->OP_LEFT)) { /* embraced member */
|
||||
if (IVAL(&(tp->tp_up), ex->OP_LEFT) != 0)
|
||||
too_many_initialisers(ex);
|
||||
ex = ex->OP_RIGHT;
|
||||
}
|
||||
else {
|
||||
if (aggregate_type(tp->tp_up))
|
||||
ex = IVAL(&(tp->tp_up), ex);
|
||||
else {
|
||||
check_ival(ex->OP_LEFT, tp->tp_up);
|
||||
ex = ex->OP_RIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* set the proper size */
|
||||
*tpp = construct_type(ARRAY, tp->tp_up, elem_count);
|
||||
}
|
||||
else { /* the number of members is already known */
|
||||
arith dim = tp->tp_size / tp->tp_up->tp_size;
|
||||
|
||||
for (elem_count = 0; elem_count < dim && ex; elem_count++) {
|
||||
if (ISCOMMA(ex->OP_LEFT)) { /* embraced member */
|
||||
if (IVAL(&(tp->tp_up), ex->OP_LEFT) != 0)
|
||||
too_many_initialisers(ex);
|
||||
ex = ex->OP_RIGHT;
|
||||
}
|
||||
else {
|
||||
if (aggregate_type(tp->tp_up))
|
||||
ex = IVAL(&(tp->tp_up), ex);
|
||||
else {
|
||||
check_ival(ex->OP_LEFT, tp->tp_up);
|
||||
ex = ex->OP_RIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ex && elem_count == dim)
|
||||
/* all the members are initialised but there
|
||||
remains a part of the expression tree which
|
||||
is returned
|
||||
*/
|
||||
return ex;
|
||||
if ((ex == 0) && elem_count < dim)
|
||||
/* the expression tree is completely absorbed
|
||||
but there are still members which must be
|
||||
initialised with zeroes
|
||||
*/
|
||||
do
|
||||
pad(tp->tp_up);
|
||||
while (++elem_count < dim);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* do_struct() initialises a struct of type tp with the expression expr.
|
||||
The main loop is just controlled by the definition of the selectors
|
||||
during which alignment is taken care of.
|
||||
*/
|
||||
struct expr *
|
||||
do_struct(ex, tp)
|
||||
register struct expr *ex;
|
||||
register struct type *tp;
|
||||
{
|
||||
register struct sdef *sd = tp->tp_sdef;
|
||||
arith bytes_upto_here = (arith)0;
|
||||
arith last_offset = (arith)-1;
|
||||
|
||||
ASSERT(tp->tp_fund == STRUCT && ISCOMMA(ex));
|
||||
/* as long as there are selectors and there is an initialiser.. */
|
||||
while (sd && ex) {
|
||||
if (ISCOMMA(ex->OP_LEFT)) { /* embraced expression */
|
||||
if (IVAL(&(sd->sd_type), ex->OP_LEFT) != 0)
|
||||
too_many_initialisers(ex);
|
||||
ex = ex->OP_RIGHT;
|
||||
}
|
||||
else {
|
||||
if (aggregate_type(sd->sd_type))
|
||||
/* selector is an aggregate itself */
|
||||
ex = IVAL(&(sd->sd_type), ex);
|
||||
else {
|
||||
#ifdef NOBITFIELD
|
||||
/* fundamental type, not embraced */
|
||||
check_ival(ex->OP_LEFT, sd->sd_type);
|
||||
ex = ex->OP_RIGHT;
|
||||
#else
|
||||
if (is_anon_idf(sd->sd_idf))
|
||||
/* a hole in the struct due to
|
||||
the use of ";:n;" in a struct
|
||||
definition.
|
||||
*/
|
||||
put_bf(sd->sd_type, (arith)0);
|
||||
else { /* fundamental type, not embraced */
|
||||
check_ival(ex->OP_LEFT, sd->sd_type);
|
||||
ex = ex->OP_RIGHT;
|
||||
}
|
||||
#endif NOBITFIELD
|
||||
}
|
||||
}
|
||||
if (sd->sd_sdef) /* align upto the next selector boundary */
|
||||
bytes_upto_here += zero_bytes(sd);
|
||||
if (last_offset != sd->sd_offset) {
|
||||
/* don't take the field-width more than once */
|
||||
bytes_upto_here +=
|
||||
size_of_type(sd->sd_type, "selector");
|
||||
last_offset = sd->sd_offset;
|
||||
}
|
||||
sd = sd->sd_sdef;
|
||||
}
|
||||
/* perfect fit if (ex && (sd == 0)) holds */
|
||||
if ((ex == 0) && (sd != 0)) {
|
||||
/* there are selectors left which must be padded with zeroes */
|
||||
do {
|
||||
pad(sd->sd_type);
|
||||
/* take care of the alignment restrictions */
|
||||
if (sd->sd_sdef)
|
||||
bytes_upto_here += zero_bytes(sd);
|
||||
/* no field thrown-outs here */
|
||||
bytes_upto_here +=
|
||||
size_of_type(sd->sd_type, "selector");
|
||||
} while (sd = sd->sd_sdef);
|
||||
}
|
||||
/* keep on aligning... */
|
||||
while (bytes_upto_here++ < tp->tp_size)
|
||||
con_nullbyte();
|
||||
return ex;
|
||||
}
|
||||
|
||||
/* check_and_pad() is given a simple initialisation expression
|
||||
where the type can be either a simple or an aggregate type.
|
||||
In the latter case, only the first member is initialised and
|
||||
the rest is zeroed.
|
||||
*/
|
||||
check_and_pad(ex, tpp)
|
||||
register struct expr *ex;
|
||||
struct type **tpp;
|
||||
{
|
||||
/* ex is of a fundamental type */
|
||||
register struct type *tp = *tpp;
|
||||
|
||||
if (tp->tp_fund == ARRAY) {
|
||||
if (valid_type(tp->tp_up, "array element") == 0)
|
||||
return;
|
||||
check_and_pad(ex, &(tp->tp_up)); /* first member */
|
||||
if (tp->tp_size == (arith)-1)
|
||||
/* no size specified upto here: just
|
||||
set it to the size of one member.
|
||||
*/
|
||||
tp = *tpp = construct_type(ARRAY, tp->tp_up, (arith)1);
|
||||
else {
|
||||
register int dim = tp->tp_size / tp->tp_up->tp_size;
|
||||
/* pad remaining members with zeroes */
|
||||
while (--dim > 0)
|
||||
pad(tp->tp_up);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (tp->tp_fund == STRUCT) {
|
||||
register struct sdef *sd = tp->tp_sdef;
|
||||
|
||||
if (valid_type(tp, "struct") == 0)
|
||||
return;
|
||||
check_and_pad(ex, &(sd->sd_type));
|
||||
/* next selector is aligned by adding extra zeroes */
|
||||
if (sd->sd_sdef)
|
||||
zero_bytes(sd);
|
||||
while (sd = sd->sd_sdef) { /* pad remaining selectors */
|
||||
pad(sd->sd_type);
|
||||
if (sd->sd_sdef)
|
||||
zero_bytes(sd);
|
||||
}
|
||||
}
|
||||
else /* simple type */
|
||||
check_ival(ex, tp);
|
||||
}
|
||||
|
||||
/* pad() fills an element of type tp with zeroes.
|
||||
If the element is an aggregate, pad() is called recursively.
|
||||
*/
|
||||
pad(tp)
|
||||
register struct type *tp;
|
||||
{
|
||||
register arith sz = tp->tp_size;
|
||||
|
||||
switch (tp->tp_fund) {
|
||||
case ARRAY:
|
||||
if (valid_type(tp->tp_up, "array element") == 0)
|
||||
return;
|
||||
break;
|
||||
case STRUCT:
|
||||
if (valid_type(tp, "struct") == 0)
|
||||
return;
|
||||
break;
|
||||
case UNION:
|
||||
if (valid_type(tp, "union") == 0)
|
||||
return;
|
||||
if (options['R']) {
|
||||
warning("initialisation of unions not allowed");
|
||||
}
|
||||
break;
|
||||
#ifndef NOBITFIELD
|
||||
case FIELD:
|
||||
put_bf(tp, (arith)0);
|
||||
return;
|
||||
#endif NOBITFIELD
|
||||
case ERRONEOUS:
|
||||
return;
|
||||
}
|
||||
|
||||
while (sz >= word_size) {
|
||||
C_con_cst((arith) 0);
|
||||
sz -= word_size;
|
||||
}
|
||||
while (sz) {
|
||||
C_con_icon("0", (arith) 1);
|
||||
sz--;
|
||||
}
|
||||
}
|
||||
|
||||
/* check_ival() checks whether the initialisation of an element
|
||||
of a fundamental type is legal and, if so, performs the initialisation
|
||||
by directly generating the necessary code.
|
||||
No further comment is needed to explain the internal structure
|
||||
of this straightforward function.
|
||||
*/
|
||||
check_ival(expr, tp)
|
||||
register struct expr *expr;
|
||||
register struct type *tp;
|
||||
{
|
||||
/* The philosophy here is that ch7cast puts an explicit
|
||||
conversion node in front of the expression if the types
|
||||
are not compatible. In this case, the initialisation
|
||||
expression is no longer a constant.
|
||||
*/
|
||||
struct expr *ex = expr;
|
||||
|
||||
switch (tp->tp_fund) {
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case INT:
|
||||
case LONG:
|
||||
case ENUM:
|
||||
case POINTER:
|
||||
ch7cast(&ex, '=', tp);
|
||||
expr = ex;
|
||||
#ifdef DEBUG
|
||||
print_expr("init-expr after cast", expr);
|
||||
#endif DEBUG
|
||||
if (!is_ld_cst(expr))
|
||||
illegal_init_cst(expr);
|
||||
else
|
||||
if (expr->VL_CLASS == Const)
|
||||
con_int(expr);
|
||||
else
|
||||
if (expr->VL_CLASS == Name) {
|
||||
register struct idf *idf = expr->VL_IDF;
|
||||
|
||||
if (idf->id_def->df_level >= L_LOCAL)
|
||||
illegal_init_cst(expr);
|
||||
else /* e.g., int f(); int p = f; */
|
||||
if (idf->id_def->df_type->tp_fund == FUNCTION)
|
||||
C_con_pnam(idf->id_text);
|
||||
else /* e.g., int a; int *p = &a; */
|
||||
C_con_dnam(idf->id_text, expr->VL_VALUE);
|
||||
}
|
||||
else {
|
||||
ASSERT(expr->VL_CLASS == Label);
|
||||
C_con_dlb(expr->VL_LBL, expr->VL_VALUE);
|
||||
}
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
ch7cast(&ex, '=', tp);
|
||||
expr = ex;
|
||||
#ifdef DEBUG
|
||||
print_expr("init-expr after cast", expr);
|
||||
#endif DEBUG
|
||||
if (expr->ex_class == Float)
|
||||
C_con_fcon(expr->FL_VALUE, expr->ex_type->tp_size);
|
||||
else
|
||||
if (expr->ex_class == Oper && expr->OP_OPER == INT2FLOAT) {
|
||||
/* float f = 1; */
|
||||
expr = expr->OP_RIGHT;
|
||||
if (is_cp_cst(expr))
|
||||
C_con_fcon(long2str((long)expr->VL_VALUE, 10),
|
||||
tp->tp_size);
|
||||
else
|
||||
illegal_init_cst(expr);
|
||||
}
|
||||
else
|
||||
illegal_init_cst(expr);
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
|
||||
#ifndef NOBITFIELD
|
||||
case FIELD:
|
||||
ch7cast(&ex, '=', tp->tp_up);
|
||||
expr = ex;
|
||||
#ifdef DEBUG
|
||||
print_expr("init-expr after cast", expr);
|
||||
#endif DEBUG
|
||||
if (is_cp_cst(expr))
|
||||
put_bf(tp, expr->VL_VALUE);
|
||||
else
|
||||
illegal_init_cst(expr);
|
||||
break;
|
||||
#endif NOBITFIELD
|
||||
|
||||
case ERRONEOUS:
|
||||
break;
|
||||
default:
|
||||
crash("check_ival");
|
||||
}
|
||||
}
|
||||
|
||||
/* ch_array() initialises an array of characters when given
|
||||
a string constant.
|
||||
Alignment is taken care of.
|
||||
*/
|
||||
ch_array(tpp, ex)
|
||||
struct type **tpp; /* type tp = array of characters */
|
||||
struct expr *ex;
|
||||
{
|
||||
register struct type *tp = *tpp;
|
||||
register arith length = ex->SG_LEN;
|
||||
char *s;
|
||||
arith ntopad;
|
||||
|
||||
ASSERT(ex->ex_class == String);
|
||||
if (tp->tp_size == (arith)-1) {
|
||||
/* set the dimension */
|
||||
tp = *tpp = construct_type(ARRAY, tp->tp_up, length);
|
||||
ntopad = align(tp->tp_size, word_size) - tp->tp_size;
|
||||
}
|
||||
else {
|
||||
arith dim = tp->tp_size / tp->tp_up->tp_size;
|
||||
extern char options[];
|
||||
|
||||
if (length > dim) {
|
||||
if (options['R'])
|
||||
too_many_initialisers(ex);
|
||||
else { /* don't take the null byte into account */
|
||||
if (length > dim + 1)
|
||||
expr_warning(ex,
|
||||
"too many initialisers");
|
||||
length = dim;
|
||||
}
|
||||
}
|
||||
ntopad = align(dim, word_size) - length;
|
||||
}
|
||||
/* throw out the characters of the already prepared string */
|
||||
s = Malloc((unsigned) (length + ntopad));
|
||||
clear(s, (int) (length + ntopad));
|
||||
strncpy(s, ex->SG_VALUE, (int) length);
|
||||
free(ex->SG_VALUE);
|
||||
str_cst(s, (int) (length + ntopad));
|
||||
free(s);
|
||||
}
|
||||
|
||||
/* As long as some parts of the pipeline cannot handle very long string
|
||||
constants, string constants are written out in chunks
|
||||
*/
|
||||
str_cst(str, len)
|
||||
register char *str;
|
||||
register int len;
|
||||
{
|
||||
arith chunksize = ((127 + word_size) / word_size) * word_size;
|
||||
|
||||
while (len > chunksize) {
|
||||
C_con_scon(str, chunksize);
|
||||
len -= chunksize;
|
||||
str += chunksize;
|
||||
}
|
||||
C_con_scon(str, (arith) len);
|
||||
}
|
||||
|
||||
#ifndef NOBITFIELD
|
||||
/* put_bf() takes care of the initialisation of (bit-)field
|
||||
selectors of a struct: each time such an initialisation takes place,
|
||||
put_bf() is called instead of the normal code generating routines.
|
||||
Put_bf() stores the given integral value into "field" and
|
||||
"throws" the result of "field" out if the current selector
|
||||
is the last of this number of fields stored at the same address.
|
||||
*/
|
||||
put_bf(tp, val)
|
||||
struct type *tp;
|
||||
arith val;
|
||||
{
|
||||
static long field = (arith)0;
|
||||
static arith offset = (arith)-1;
|
||||
register struct field *fd = tp->tp_field;
|
||||
register struct sdef *sd = fd->fd_sdef;
|
||||
static struct expr exp;
|
||||
|
||||
ASSERT(sd);
|
||||
if (offset == (arith)-1) {
|
||||
/* first bitfield in this field */
|
||||
offset = sd->sd_offset;
|
||||
exp.ex_type = tp->tp_up;
|
||||
exp.ex_class = Value;
|
||||
exp.VL_CLASS = Const;
|
||||
}
|
||||
if (val != 0) /* insert the value into "field" */
|
||||
field |= (val & fd->fd_mask) << fd->fd_shift;
|
||||
if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) {
|
||||
/* the selector was the last stored at this address */
|
||||
exp.VL_VALUE = field;
|
||||
con_int(&exp);
|
||||
field = (arith)0;
|
||||
offset = (arith)-1;
|
||||
}
|
||||
}
|
||||
#endif NOBITFIELD
|
||||
|
||||
int
|
||||
zero_bytes(sd)
|
||||
register struct sdef *sd;
|
||||
{
|
||||
/* fills the space between a selector of a struct
|
||||
and the next selector of that struct with zero-bytes.
|
||||
*/
|
||||
register int n = sd->sd_sdef->sd_offset - sd->sd_offset -
|
||||
size_of_type(sd->sd_type, "struct member");
|
||||
register int count = n;
|
||||
|
||||
while (n-- > 0)
|
||||
con_nullbyte();
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
valid_type(tp, str)
|
||||
struct type *tp;
|
||||
char *str;
|
||||
{
|
||||
if (tp->tp_size < 0) {
|
||||
error("size of %s unknown", str);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
con_int(ex)
|
||||
register struct expr *ex;
|
||||
{
|
||||
register struct type *tp = ex->ex_type;
|
||||
|
||||
ASSERT(is_cp_cst(ex));
|
||||
if (tp->tp_unsigned)
|
||||
C_con_ucon(long2str((long)ex->VL_VALUE, -10), tp->tp_size);
|
||||
else
|
||||
C_con_icon(long2str((long)ex->VL_VALUE, 10), tp->tp_size);
|
||||
}
|
||||
|
||||
illegal_init_cst(ex)
|
||||
struct expr *ex;
|
||||
{
|
||||
expr_error(ex, "illegal initialisation constant");
|
||||
}
|
||||
|
||||
too_many_initialisers(ex)
|
||||
struct expr *ex;
|
||||
{
|
||||
expr_error(ex, "too many initialisers");
|
||||
}
|
||||
|
||||
aggregate_type(tp)
|
||||
register struct type *tp;
|
||||
{
|
||||
return tp->tp_fund == ARRAY || tp->tp_fund == STRUCT;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* PREPROCESSOR: DEFINITION OF MACRO DESCRIPTOR */
|
||||
|
||||
#include "nopp.h"
|
||||
|
||||
#ifndef NOPP
|
||||
/* The flags of the mc_flag field of the macro structure. Note that
|
||||
these flags can be set simultaneously.
|
||||
*/
|
||||
#define NOFLAG 0 /* no special flags */
|
||||
#define FUNC 01 /* function attached */
|
||||
#define PREDEF 02 /* predefined macro */
|
||||
|
||||
#define FORMALP 0200 /* mask for creating macro formal parameter */
|
||||
|
||||
/* The macro descriptor is very simple, except the fact that the
|
||||
mc_text, which points to the replacement text, contains the
|
||||
non-ascii characters \201, \202, etc, indicating the position of a
|
||||
formal parameter in this text.
|
||||
*/
|
||||
struct macro {
|
||||
struct macro *next;
|
||||
char * mc_text; /* the replacement text */
|
||||
int mc_nps; /* number of formal parameters */
|
||||
int mc_length; /* length of replacement text */
|
||||
char mc_flag; /* marking this macro */
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct macro */
|
||||
/* ALLOCDEF "macro" */
|
||||
extern char *st_alloc();
|
||||
extern struct macro *h_macro;
|
||||
#define new_macro() ((struct macro *) \
|
||||
st_alloc((char **)&h_macro, sizeof(struct macro)))
|
||||
#define free_macro(p) st_free(p, h_macro, sizeof(struct macro))
|
||||
|
||||
|
||||
/* `token' numbers of keywords of command-line processor
|
||||
*/
|
||||
#define K_UNKNOWN 0
|
||||
#define K_DEFINE 1
|
||||
#define K_ELIF 2
|
||||
#define K_ELSE 3
|
||||
#define K_ENDIF 4
|
||||
#define K_IF 5
|
||||
#define K_IFDEF 6
|
||||
#define K_IFNDEF 7
|
||||
#define K_INCLUDE 8
|
||||
#define K_LINE 9
|
||||
#define K_UNDEF 10
|
||||
#endif NOPP
|
|
@ -1,19 +0,0 @@
|
|||
ed - $1 <<'--EOI--'
|
||||
g/^%/d
|
||||
g/^ /.-1,.j
|
||||
1,$s/^\([^|]*\)|\([^|]*\)|\(.*\)$/\
|
||||
\1 \2 {\
|
||||
\3;\
|
||||
}/
|
||||
1i
|
||||
/* EM COMPACT CODE -- PROCEDURAL INTERFACE (generated from emcode.def) */
|
||||
#include "em.h"
|
||||
#ifdef PROC_INTF
|
||||
#include "label.h"
|
||||
#include "arith.h"
|
||||
.
|
||||
$a
|
||||
#endif PROC_INTF
|
||||
.
|
||||
1,$p
|
||||
--EOI--
|
|
@ -1,10 +0,0 @@
|
|||
ed - $1 <<'--EOI--'
|
||||
g/^%/d
|
||||
g/^ /.-1,.j
|
||||
1,$s/^\([^|]*\)|[^|]*|\(.*\)$/\
|
||||
#define \1 (\2)/
|
||||
1i
|
||||
/* EM COMPACT CODE -- MACRO DEFINITIONS (generated from emcode.def) */
|
||||
.
|
||||
1,$p
|
||||
--EOI--
|
|
@ -1,46 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* IDENTIFIER STACK DEFINITIONS */
|
||||
|
||||
/* The identifier stack is implemented as a stack of sets.
|
||||
The stack is implemented by a doubly linked list,
|
||||
the sets by singly linked lists.
|
||||
*/
|
||||
|
||||
struct stack_level {
|
||||
struct stack_level *next;
|
||||
struct stack_level *sl_next; /* upward link */
|
||||
struct stack_level *sl_previous; /* downward link */
|
||||
struct stack_entry *sl_entry; /* sideward link */
|
||||
arith sl_local_offset; /* @ for first coming object */
|
||||
arith sl_max_block; /* maximum size of sub-block */
|
||||
int sl_level;
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct stack_level */
|
||||
/* ALLOCDEF "stack_level" */
|
||||
extern char *st_alloc();
|
||||
extern struct stack_level *h_stack_level;
|
||||
#define new_stack_level() ((struct stack_level *) \
|
||||
st_alloc((char **)&h_stack_level, sizeof(struct stack_level)))
|
||||
#define free_stack_level(p) st_free(p, h_stack_level, sizeof(struct stack_level))
|
||||
|
||||
|
||||
struct stack_entry {
|
||||
struct stack_entry *next;
|
||||
struct idf *se_idf;
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct stack_entry */
|
||||
/* ALLOCDEF "stack_entry" */
|
||||
extern char *st_alloc();
|
||||
extern struct stack_entry *h_stack_entry;
|
||||
#define new_stack_entry() ((struct stack_entry *) \
|
||||
st_alloc((char **)&h_stack_entry, sizeof(struct stack_entry)))
|
||||
#define free_stack_entry(p) st_free(p, h_stack_entry, sizeof(struct stack_entry))
|
||||
|
||||
|
||||
extern struct stack_level *local_level;
|
||||
extern struct stack_level *stack_level_of();
|
||||
extern int level;
|
|
@ -1,67 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* S T R U C T U R E - S T O R A G E M A N A G E M E N T */
|
||||
|
||||
/* Assume that each structure contains a field "next", of pointer
|
||||
type, as first tagfield.
|
||||
struct xxx serves as a general structure: it just declares the
|
||||
tagfield "next" as first field of a structure.
|
||||
Please don't worry about any warnings when compiling this file
|
||||
because some dirty tricks are performed to obtain the necessary
|
||||
actions.
|
||||
*/
|
||||
|
||||
#include "debug.h" /* UF */
|
||||
#include "botch_free.h" /* UF */
|
||||
#include "assert.h"
|
||||
#include "alloc.h"
|
||||
#include "storage.h"
|
||||
|
||||
struct xxx {
|
||||
char *next;
|
||||
};
|
||||
|
||||
char *
|
||||
head_alloc(phead, size)
|
||||
char **phead;
|
||||
int size;
|
||||
{
|
||||
struct xxx *tmp;
|
||||
|
||||
if (*phead == 0) {
|
||||
return Malloc(size);
|
||||
}
|
||||
tmp = (struct xxx *) (*phead);
|
||||
*phead = (char *) tmp->next;
|
||||
return (char *) tmp;
|
||||
}
|
||||
|
||||
/* instead of Calloc: */
|
||||
clear(ptr, n)
|
||||
char *ptr;
|
||||
int n;
|
||||
{
|
||||
ASSERT((long)ptr % sizeof (long) == 0);
|
||||
while (n >= sizeof (long)) { /* high-speed clear loop */
|
||||
*(long *)ptr = 0L;
|
||||
ptr += sizeof (long), n -= sizeof (long);
|
||||
}
|
||||
while (n--)
|
||||
*ptr++ = '\0';
|
||||
}
|
||||
|
||||
#ifdef BOTCH_FREE
|
||||
botch(ptr, n)
|
||||
char *ptr;
|
||||
int n;
|
||||
{ /* Writes garbage over n chars starting from ptr.
|
||||
Used to check if freed memory is used inappropriately.
|
||||
*/
|
||||
ASSERT((long)ptr % sizeof (long) == 0);
|
||||
while (n >= sizeof (long)) { /* high-speed botch loop */
|
||||
*(long *)ptr = 025252525252L;
|
||||
ptr += sizeof (long), n -= sizeof (long);
|
||||
}
|
||||
while (n--)
|
||||
*ptr++ = '\252';
|
||||
}
|
||||
#endif BOTCH_FREE
|
|
@ -1,23 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* S T R U C T U R E - S T O R A G E D E F I N I T I O N S */
|
||||
|
||||
/* Storage allocation is one of the most expensive operations in
|
||||
the compiler and consequently much thought and experimentation
|
||||
has gone into it. To simplify the hooking in of new super-fancy
|
||||
algorithms, all allocating and freeing of storage for structs
|
||||
goes through the macros
|
||||
st_alloc(&head, size)
|
||||
st_free(ptr, head, size)
|
||||
which, hopefully, convey enough information.
|
||||
*/
|
||||
|
||||
extern char *head_alloc();
|
||||
|
||||
#define st_alloc(headp, size) head_alloc((char **)headp, size)
|
||||
|
||||
#ifndef BOTCH_FREE
|
||||
#define st_free(ptr, head, size) (ptr->next = head, head = ptr)
|
||||
#else def BOTCH_FREE
|
||||
#define st_free(ptr, head, size) (botch((char *)(ptr), size), \
|
||||
ptr->next = head, head = ptr)
|
||||
#endif BOTCH_FREE
|
|
@ -1,277 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* STRING MANIPULATION AND PRINT ROUTINES */
|
||||
|
||||
#include <system.h>
|
||||
#include "string.h"
|
||||
#include "nopp.h"
|
||||
#include "str_params.h"
|
||||
#include "arith.h"
|
||||
|
||||
doprnt(fp, fmt, argp)
|
||||
File *fp;
|
||||
char *fmt;
|
||||
int argp[];
|
||||
{
|
||||
char buf[SSIZE];
|
||||
|
||||
sys_write(fp, buf, format(buf, fmt, (char *)argp));
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
printf(fmt, args)
|
||||
char *fmt;
|
||||
char args;
|
||||
{
|
||||
char buf[SSIZE];
|
||||
|
||||
sys_write(STDOUT, buf, format(buf, fmt, &args));
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
fprintf(fp, fmt, args)
|
||||
File *fp;
|
||||
char *fmt;
|
||||
char args;
|
||||
{
|
||||
char buf[SSIZE];
|
||||
|
||||
sys_write(fp, buf, format(buf, fmt, &args));
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
char *
|
||||
sprintf(buf, fmt, args)
|
||||
char *buf, *fmt;
|
||||
char args;
|
||||
{
|
||||
buf[format(buf, fmt, &args)] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
format(buf, fmt, argp)
|
||||
char *buf, *fmt;
|
||||
char *argp;
|
||||
{
|
||||
register char *pf = fmt, *pa = argp;
|
||||
register char *pb = buf;
|
||||
|
||||
while (*pf) {
|
||||
if (*pf == '%') {
|
||||
register width, base, pad, npad;
|
||||
char *arg;
|
||||
char cbuf[2];
|
||||
char *badformat = "<bad format>";
|
||||
|
||||
/* get padder */
|
||||
if (*++pf == '0') {
|
||||
pad = '0';
|
||||
++pf;
|
||||
}
|
||||
else
|
||||
pad = ' ';
|
||||
|
||||
/* get width */
|
||||
width = 0;
|
||||
while (*pf >= '0' && *pf <= '9')
|
||||
width = 10 * width + *pf++ - '0';
|
||||
|
||||
/* get text and move pa */
|
||||
if (*pf == 's') {
|
||||
arg = *(char **)pa;
|
||||
pa += sizeof(char *);
|
||||
}
|
||||
else
|
||||
if (*pf == 'c') {
|
||||
cbuf[0] = * (char *) pa;
|
||||
cbuf[1] = '\0';
|
||||
pa += sizeof(int);
|
||||
arg = &cbuf[0];
|
||||
}
|
||||
else
|
||||
if (*pf == 'l') {
|
||||
/* alignment ??? */
|
||||
if (base = integral(*++pf)) {
|
||||
arg = int_str(*(long *)pa, base);
|
||||
pa += sizeof(long);
|
||||
}
|
||||
else {
|
||||
pf--;
|
||||
arg = badformat;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (base = integral(*pf)) {
|
||||
arg = int_str((long)*(int *)pa, base);
|
||||
pa += sizeof(int);
|
||||
}
|
||||
else
|
||||
if (*pf == '%')
|
||||
arg = "%";
|
||||
else
|
||||
arg = badformat;
|
||||
|
||||
npad = width - strlen(arg);
|
||||
|
||||
while (npad-- > 0)
|
||||
*pb++ = pad;
|
||||
|
||||
while (*pb++ = *arg++);
|
||||
pb--;
|
||||
pf++;
|
||||
}
|
||||
else
|
||||
*pb++ = *pf++;
|
||||
}
|
||||
return pb - buf;
|
||||
}
|
||||
|
||||
integral(c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'b':
|
||||
return -2;
|
||||
case 'd':
|
||||
return 10;
|
||||
case 'o':
|
||||
return -8;
|
||||
case 'u':
|
||||
return -10;
|
||||
case 'x':
|
||||
return -16;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Integer to String translator
|
||||
*/
|
||||
char *
|
||||
int_str(val, base)
|
||||
register long val;
|
||||
register base;
|
||||
{
|
||||
/* int_str() is a very simple integer to string converter.
|
||||
base < 0 : unsigned.
|
||||
base must be an element of [-16,-2] V [2,16].
|
||||
*/
|
||||
static char numbuf[MAXWIDTH];
|
||||
static char vec[] = "0123456789ABCDEF";
|
||||
register char *p = &numbuf[MAXWIDTH];
|
||||
int sign = (base > 0);
|
||||
|
||||
*--p = '\0'; /* null-terminate string */
|
||||
if (val) {
|
||||
if (base > 0) {
|
||||
if (val < (arith)0) {
|
||||
if ((val = -val) < (arith)0)
|
||||
goto overflow;
|
||||
}
|
||||
else
|
||||
sign = 0;
|
||||
}
|
||||
else
|
||||
if (base < 0) { /* unsigned */
|
||||
base = -base;
|
||||
if (val < (arith)0) {
|
||||
register mod, i;
|
||||
|
||||
overflow:
|
||||
/* this takes a rainy Sunday afternoon to explain */
|
||||
/* ??? */
|
||||
mod = 0;
|
||||
for (i = 0; i < 8 * sizeof val; i++) {
|
||||
mod <<= 1;
|
||||
if (val < 0)
|
||||
mod++;
|
||||
val <<= 1;
|
||||
if (mod >= base) {
|
||||
mod -= base;
|
||||
val++;
|
||||
}
|
||||
}
|
||||
*--p = vec[mod];
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
*--p = vec[(int) (val % base)];
|
||||
val /= base;
|
||||
} while (val != (arith)0);
|
||||
|
||||
if (sign)
|
||||
*--p = '-'; /* don't forget it !! */
|
||||
}
|
||||
else
|
||||
*--p = '0'; /* just a simple 0 */
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/* return negative, zero or positive value if
|
||||
resp. s < t, s == t or s > t
|
||||
*/
|
||||
int
|
||||
strcmp(s, t)
|
||||
register char *s, *t;
|
||||
{
|
||||
while (*s == *t++)
|
||||
if (*s++ == '\0')
|
||||
return 0;
|
||||
return *s - *--t;
|
||||
}
|
||||
|
||||
/* return length of s
|
||||
*/
|
||||
int
|
||||
strlen(s)
|
||||
char *s;
|
||||
{
|
||||
register char *b = s;
|
||||
|
||||
while (*b++)
|
||||
;
|
||||
return b - s - 1;
|
||||
}
|
||||
|
||||
#ifndef NOPP
|
||||
/* append t to s
|
||||
*/
|
||||
char *
|
||||
strcat(s, t)
|
||||
register char *s, *t;
|
||||
{
|
||||
register char *b = s;
|
||||
|
||||
while (*s++)
|
||||
;
|
||||
s--;
|
||||
while (*s++ = *t++)
|
||||
;
|
||||
return b;
|
||||
}
|
||||
|
||||
/* Copy t into s
|
||||
*/
|
||||
char *
|
||||
strcpy(s, t)
|
||||
register char *s, *t;
|
||||
{
|
||||
register char *b = s;
|
||||
|
||||
while (*s++ = *t++)
|
||||
;
|
||||
return b;
|
||||
}
|
||||
|
||||
char *
|
||||
rindex(str, chr)
|
||||
register char *str, chr;
|
||||
{
|
||||
register char *retptr = 0;
|
||||
|
||||
while (*str)
|
||||
if (*str++ == chr)
|
||||
retptr = &str[-1];
|
||||
return retptr;
|
||||
}
|
||||
#endif NOPP
|
|
@ -1,13 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* STRING-ROUTINE DEFINITIONS */
|
||||
|
||||
#define stdin 0
|
||||
#define stdout 1
|
||||
#define stderr 2
|
||||
|
||||
#define itos(n) int_str((long)(n), 10)
|
||||
|
||||
char *sprintf(); /* string.h */
|
||||
char *int_str(); /* string.h */
|
||||
|
||||
char *strcpy(), *strcat(), *rindex();
|
|
@ -1,44 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* SELECTOR DESCRIPTOR */
|
||||
|
||||
struct sdef { /* for selectors */
|
||||
struct sdef *next;
|
||||
int sd_level;
|
||||
struct idf *sd_idf; /* its name */
|
||||
struct sdef *sd_sdef; /* the next selector */
|
||||
struct type *sd_stype; /* the struct it belongs to */
|
||||
struct type *sd_type; /* its type */
|
||||
arith sd_offset;
|
||||
};
|
||||
|
||||
extern char *st_alloc();
|
||||
|
||||
|
||||
/* allocation definitions of struct sdef */
|
||||
/* ALLOCDEF "sdef" */
|
||||
extern char *st_alloc();
|
||||
extern struct sdef *h_sdef;
|
||||
#define new_sdef() ((struct sdef *) \
|
||||
st_alloc((char **)&h_sdef, sizeof(struct sdef)))
|
||||
#define free_sdef(p) st_free(p, h_sdef, sizeof(struct sdef))
|
||||
|
||||
|
||||
struct tag { /* for struct-, union- and enum tags */
|
||||
struct tag *next;
|
||||
int tg_level;
|
||||
int tg_busy; /* non-zero during declaration of struct/union pack */
|
||||
struct type *tg_type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* allocation definitions of struct tag */
|
||||
/* ALLOCDEF "tag" */
|
||||
extern char *st_alloc();
|
||||
extern struct tag *h_tag;
|
||||
#define new_tag() ((struct tag *) \
|
||||
st_alloc((char **)&h_tag, sizeof(struct tag)))
|
||||
#define free_tag(p) st_free(p, h_tag, sizeof(struct tag))
|
||||
|
||||
|
||||
struct sdef *idf2sdef();
|
|
@ -1,40 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* S W I T C H - T A B L E - S T R U C T U R E */
|
||||
|
||||
struct switch_hdr {
|
||||
struct switch_hdr *next;
|
||||
label sh_break;
|
||||
label sh_default;
|
||||
label sh_table;
|
||||
int sh_nrofentries;
|
||||
struct type *sh_type;
|
||||
arith sh_lowerbd;
|
||||
arith sh_upperbd;
|
||||
struct case_entry *sh_entries;
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct switch_hdr */
|
||||
/* ALLOCDEF "switch_hdr" */
|
||||
extern char *st_alloc();
|
||||
extern struct switch_hdr *h_switch_hdr;
|
||||
#define new_switch_hdr() ((struct switch_hdr *) \
|
||||
st_alloc((char **)&h_switch_hdr, sizeof(struct switch_hdr)))
|
||||
#define free_switch_hdr(p) st_free(p, h_switch_hdr, sizeof(struct switch_hdr))
|
||||
|
||||
|
||||
struct case_entry {
|
||||
struct case_entry *next;
|
||||
label ce_label;
|
||||
arith ce_value;
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct case_entry */
|
||||
/* ALLOCDEF "case_entry" */
|
||||
extern char *st_alloc();
|
||||
extern struct case_entry *h_case_entry;
|
||||
#define new_case_entry() ((struct case_entry *) \
|
||||
st_alloc((char **)&h_case_entry, sizeof(struct case_entry)))
|
||||
#define free_case_entry(p) st_free(p, h_case_entry, sizeof(struct case_entry))
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* SYSTEM DEPENDENT ROUTINES */
|
||||
|
||||
#include "system.h"
|
||||
#include "inputtype.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
extern long lseek();
|
||||
|
||||
int
|
||||
xopen(name, flag, mode)
|
||||
char *name;
|
||||
{
|
||||
if (name[0] == '-' && name[1] == '\0')
|
||||
return (flag == OP_RDONLY) ? 0 : 1;
|
||||
|
||||
switch (flag) {
|
||||
|
||||
case OP_RDONLY:
|
||||
return open(name, 0);
|
||||
case OP_WRONLY:
|
||||
return open(name, 1);
|
||||
case OP_CREAT:
|
||||
return creat(name, mode);
|
||||
case OP_APPEND:
|
||||
{
|
||||
register fd;
|
||||
|
||||
if ((fd = open(name, 1)) < 0)
|
||||
return -1;
|
||||
lseek(fd, 0L, 2);
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
int
|
||||
xclose(fildes)
|
||||
{
|
||||
if (fildes != 0 && fildes != 1)
|
||||
return close(fildes);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef READ_IN_ONE
|
||||
long
|
||||
xfsize(fildes)
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
if (fstat(fildes, &stbuf) != 0)
|
||||
return -1;
|
||||
return stbuf.st_size;
|
||||
}
|
||||
#endif READ_IN_ONE
|
||||
|
||||
exit(n)
|
||||
{
|
||||
_exit(n);
|
||||
}
|
||||
|
||||
xstop(how, stat)
|
||||
{
|
||||
switch (how) {
|
||||
case S_ABORT:
|
||||
abort();
|
||||
case S_EXIT:
|
||||
exit(stat);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* SYSTEM DEPENDANT DEFINITIONS */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define OP_RDONLY 0 /* open for read */
|
||||
#define OP_WRONLY 1 /* open for write */
|
||||
#define OP_CREAT 2 /* create and open for write */
|
||||
#define OP_APPEND 3 /* open for write at end */
|
||||
|
||||
#define sys_open(name, flag) xopen(name, flag, 0)
|
||||
#define sys_close(fildes) xclose(fildes)
|
||||
#define sys_read(fildes, buffer, nbytes) read(fildes, buffer, nbytes)
|
||||
#define sys_write(fildes, buffer, nbytes) write(fildes, buffer, nbytes)
|
||||
#define sys_creat(name, mode) xopen(name, OP_CREAT, mode)
|
||||
#define sys_remove(name) unlink(name)
|
||||
#define sys_fsize(fd) xfsize(fd)
|
||||
#define sys_sbrk(incr) sbrk(incr)
|
||||
#define sys_stop(how, stat) xstop(how, stat)
|
||||
|
||||
#define S_ABORT 1
|
||||
#define S_EXIT 2
|
||||
|
||||
char *sbrk();
|
||||
long xfsize();
|
||||
|
||||
extern int errno;
|
||||
|
||||
#define sys_errno errno
|
||||
|
||||
#define time_type time_t
|
||||
#define sys_time(tloc) time(tloc)
|
||||
time_type time();
|
|
@ -1,52 +0,0 @@
|
|||
/* $Header$ */
|
||||
/* TYPE DESCRIPTOR */
|
||||
|
||||
#include "nobitfield.h"
|
||||
|
||||
struct type {
|
||||
struct type *next; /* used only with ARRAY */
|
||||
short tp_fund; /* fundamental type */
|
||||
char tp_unsigned;
|
||||
int tp_align;
|
||||
arith tp_size; /* -1 if declared but not defined */
|
||||
struct idf *tp_idf; /* name of STRUCT, UNION or ENUM */
|
||||
struct sdef *tp_sdef; /* to first selector */
|
||||
struct type *tp_up; /* from FIELD, POINTER, ARRAY
|
||||
or FUNCTION to fund. */
|
||||
struct field *tp_field; /* field descriptor if fund == FIELD */
|
||||
struct type *tp_pointer;/* to POINTER */
|
||||
struct type *tp_array; /* to ARRAY */
|
||||
struct type *tp_function;/* to FUNCTION */
|
||||
};
|
||||
|
||||
extern struct type
|
||||
*create_type(), *standard_type(), *construct_type(), *pointer_to(),
|
||||
*array_of(), *function_of();
|
||||
|
||||
#ifndef NOBITFIELD
|
||||
extern struct type *field_of();
|
||||
#endif NOBITFIELD
|
||||
|
||||
extern struct type
|
||||
*char_type, *uchar_type,
|
||||
*short_type, *ushort_type,
|
||||
*word_type, *uword_type,
|
||||
*int_type, *uint_type,
|
||||
*long_type, *ulong_type,
|
||||
*float_type, *double_type,
|
||||
*void_type, *label_type,
|
||||
*string_type, *funint_type, *error_type;
|
||||
|
||||
extern struct type *pa_type; /* type.c */
|
||||
|
||||
extern arith size_of_type(), align();
|
||||
|
||||
|
||||
/* allocation definitions of struct type */
|
||||
/* ALLOCDEF "type" */
|
||||
extern char *st_alloc();
|
||||
extern struct type *h_type;
|
||||
#define new_type() ((struct type *) \
|
||||
st_alloc((char **)&h_type, sizeof(struct type)))
|
||||
#define free_type(p) st_free(p, h_type, sizeof(struct type))
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
(-40) + 300
|
||||
(-40) - 300
|
||||
(-40) / 300
|
||||
(-40) * 300
|
||||
(-40) || 300
|
||||
(-40) && 300
|
||||
-(-40)
|
||||
!(-40)
|
||||
(-40) == 300
|
||||
(-40) != 300
|
||||
(-40) <= 300
|
||||
(-40) >= 300
|
||||
(-40) < 300
|
||||
(-40) > 300
|
||||
(-40) ? (-40) : 300
|
||||
x = (-40) -4.000000e+01
|
||||
x += (-40) -3.685850e+01
|
||||
x -= (-40) 4.314150e+01
|
||||
x /= (-40) -7.853750e-02
|
||||
x *= (-40) -1.256600e+02
|
||||
x ++ 4.141500e+00
|
||||
x -- 2.141500e+00
|
||||
-- x 2.141500e+00
|
||||
++ x 4.141500e+00
|
||||
y = ( (-40) + 300 ) 17538
|
||||
y = ( (-40) - 300 ) 50346
|
||||
y = ( (-40) / 300 ) 0
|
||||
y = ( (-40) * 300 ) -2147432645
|
||||
y = ( (-40) || 300 ) 16512
|
||||
y = ( (-40) && 300 ) 16512
|
||||
y = ( -(-40) ) 17184
|
||||
y = ( !(-40) ) 0
|
||||
y = ( (-40) == 300 ) 0
|
||||
y = ( (-40) != 300 ) 16512
|
||||
y = ( (-40) <= 300 ) 16512
|
||||
y = ( (-40) >= 300 ) 0
|
||||
y = ( (-40) < 300 ) 16512
|
||||
y = ( (-40) > 300 ) 0
|
||||
y = ( (-40) ? (-40) : 300 ) 49952
|
||||
y = ( x = (-40) ) -4.000000e+01 49952
|
||||
y = ( x += (-40) ) -3.685850e+01 1864024851
|
||||
y = ( x -= (-40) ) 4.314150e+01 -1864023252
|
||||
y = ( x /= (-40) ) -7.853750e-02 -666583392
|
||||
y = ( x *= (-40) ) -1.256600e+02 1374405627
|
||||
y = ( x ++ ) 4.141500e+00 240533833
|
||||
y = ( x -- ) 2.141500e+00 240533833
|
||||
y = ( -- x ) 2.141500e+00 240533769
|
||||
y = ( ++ x ) 4.141500e+00 -2027208316
|
||||
yes if ( (-40) + 300 ) yes() ; else no()
|
||||
yes if ( (-40) - 300 ) yes() ; else no()
|
||||
no if ( (-40) / 300 ) yes() ; else no()
|
||||
yes if ( (-40) * 300 ) yes() ; else no()
|
||||
yes if ( (-40) || 300 ) yes() ; else no()
|
||||
yes if ( (-40) && 300 ) yes() ; else no()
|
||||
yes if ( -(-40) ) yes() ; else no()
|
||||
no if ( !(-40) ) yes() ; else no()
|
||||
no if ( (-40) == 300 ) yes() ; else no()
|
||||
yes if ( (-40) != 300 ) yes() ; else no()
|
||||
yes if ( (-40) <= 300 ) yes() ; else no()
|
||||
no if ( (-40) >= 300 ) yes() ; else no()
|
||||
yes if ( (-40) < 300 ) yes() ; else no()
|
||||
no if ( (-40) > 300 ) yes() ; else no()
|
||||
yes if ( (-40) ? (-40) : 300 ) yes() ; else no()
|
||||
yes if ( x = (-40) ) yes() ; else no() -4.000000e+01
|
||||
yes if ( x += (-40) ) yes() ; else no() -3.685850e+01
|
||||
yes if ( x -= (-40) ) yes() ; else no() 4.314150e+01
|
||||
yes if ( x /= (-40) ) yes() ; else no() -7.853750e-02
|
||||
yes if ( x *= (-40) ) yes() ; else no() -1.256600e+02
|
||||
yes if ( x ++ ) yes() ; else no() 4.141500e+00
|
||||
yes if ( x -- ) yes() ; else no() 2.141500e+00
|
||||
yes if ( -- x ) yes() ; else no() 2.141500e+00
|
||||
yes if ( ++ x ) yes() ; else no() 4.141500e+00
|
|
@ -1,3 +0,0 @@
|
|||
The program whose output you are comparing this file with should
|
||||
not have compiled.
|
||||
It declares a function, with an argument and without a body.
|
|
@ -1,152 +0,0 @@
|
|||
w1
|
||||
st2.w1_i 506
|
||||
(*st3).w1_i 506
|
||||
st1.w1_i 711
|
||||
st2.w1_i 711
|
||||
es2[2].w1_i 711
|
||||
st2.w1_i 577
|
||||
st2.w1_i -577
|
||||
st1.w1_i 577
|
||||
w2
|
||||
s2t2: .w2_i 18000 .w2_d 3.141500
|
||||
s2t3->w2_d 3.141500
|
||||
w3
|
||||
s3t2.w3_a[ 0] a
|
||||
s3t2.w3_a[ 1] b
|
||||
s3t2.w3_a[ 2] c
|
||||
s3t2.w3_a[ 3] d
|
||||
s3t2.w3_a[ 4] e
|
||||
s3t2.w3_a[ 5] f
|
||||
s3t2.w3_a[ 6] g
|
||||
s3t2.w3_a[ 7] h
|
||||
s3t2.w3_a[ 8] i
|
||||
s3t2.w3_a[ 9] j
|
||||
s3t2.w3_a[10] k
|
||||
s3t2.w3_a[11] l
|
||||
s3t2.w3_a[12] m
|
||||
s3t2.w3_a[13] n
|
||||
s3t2.w3_a[14] o
|
||||
s3t2.w3_a[15] p
|
||||
s3t2.w3_a[16] q
|
||||
s3t2.w3_a[17] r
|
||||
s3t2.w3_a[18] s
|
||||
s3t2.w3_a[19] t
|
||||
s3t2.w3_a[20] u
|
||||
s3t2.w3_a[21] v
|
||||
s3t2.w3_a[22] w
|
||||
s3t2.w3_a[23] x
|
||||
s3t2.w3_a[24] y
|
||||
s3t2.w3_a[25] z
|
||||
s3t2.w3_x 1.000000
|
||||
s3t1.w3_a[ 0] A
|
||||
s3t1.w3_a[ 1] B
|
||||
s3t1.w3_a[ 2] C
|
||||
s3t1.w3_a[ 3] D
|
||||
s3t1.w3_a[ 4] E
|
||||
s3t1.w3_a[ 5] F
|
||||
s3t1.w3_a[ 6] G
|
||||
s3t1.w3_a[ 7] H
|
||||
s3t1.w3_a[ 8] I
|
||||
s3t1.w3_a[ 9] J
|
||||
s3t1.w3_a[10] K
|
||||
s3t1.w3_a[11] L
|
||||
s3t1.w3_a[12] M
|
||||
s3t1.w3_a[13] N
|
||||
s3t1.w3_a[14] O
|
||||
s3t1.w3_a[15] P
|
||||
s3t1.w3_a[16] Q
|
||||
s3t1.w3_a[17] R
|
||||
s3t1.w3_a[18] S
|
||||
s3t1.w3_a[19] T
|
||||
s3t1.w3_a[20] U
|
||||
s3t1.w3_a[21] V
|
||||
s3t1.w3_a[22] W
|
||||
s3t1.w3_a[23] X
|
||||
s3t1.w3_a[24] Y
|
||||
s3t1.w3_a[25] Z
|
||||
s3t1.w3_x 0.318319
|
||||
structure parameters
|
||||
before -1
|
||||
str.w3_a[ 0] 1
|
||||
str.w3_a[ 1] 2
|
||||
str.w3_a[ 2] 3
|
||||
str.w3_a[ 3] 4
|
||||
str.w3_a[ 4] 5
|
||||
str.w3_a[ 5] 6
|
||||
str.w3_a[ 6] 7
|
||||
str.w3_a[ 7] 8
|
||||
str.w3_a[ 8] 9
|
||||
str.w3_a[ 9] 10
|
||||
str.w3_a[10] 11
|
||||
str.w3_a[11] 12
|
||||
str.w3_a[12] 13
|
||||
str.w3_a[13] 14
|
||||
str.w3_a[14] 15
|
||||
str.w3_a[15] 16
|
||||
str.w3_a[16] 17
|
||||
str.w3_a[17] 18
|
||||
str.w3_a[18] 19
|
||||
str.w3_a[19] 20
|
||||
str.w3_a[20] 21
|
||||
str.w3_a[21] 22
|
||||
str.w3_a[22] 23
|
||||
str.w3_a[23] 24
|
||||
str.w3_a[24] 25
|
||||
str.w3_a[25] 26
|
||||
str.w3_x 2.810000
|
||||
after 1000
|
||||
|
||||
Stucture valued functions
|
||||
myp.w3_a:
|
||||
0 97
|
||||
1 96
|
||||
2 95
|
||||
3 94
|
||||
4 93
|
||||
5 92
|
||||
6 91
|
||||
7 90
|
||||
8 89
|
||||
9 88
|
||||
10 87
|
||||
11 86
|
||||
12 85
|
||||
13 84
|
||||
14 83
|
||||
15 82
|
||||
16 81
|
||||
17 80
|
||||
18 79
|
||||
19 78
|
||||
20 77
|
||||
21 76
|
||||
22 75
|
||||
23 74
|
||||
24 73
|
||||
25 72
|
||||
0 99
|
||||
1 100
|
||||
2 101
|
||||
3 102
|
||||
4 103
|
||||
5 104
|
||||
6 105
|
||||
7 106
|
||||
8 107
|
||||
9 108
|
||||
10 109
|
||||
11 110
|
||||
12 111
|
||||
13 112
|
||||
14 113
|
||||
15 114
|
||||
16 115
|
||||
17 116
|
||||
18 117
|
||||
19 118
|
||||
20 119
|
||||
21 120
|
||||
22 121
|
||||
23 122
|
||||
24 123
|
||||
25 124
|
|
@ -1,174 +0,0 @@
|
|||
Tue May 22 15:12:22 MDT 1984
|
||||
***** ctconv
|
||||
acc conv.c
|
||||
conv.c
|
||||
"conv.c", line 41: warning: Overflow in constant expression
|
||||
running conv.cem
|
||||
comparing conv
|
||||
***** ctdecl
|
||||
acc decl.c
|
||||
decl.c
|
||||
running decl.cem
|
||||
comparing decl
|
||||
***** ctdivers
|
||||
acc ops.c
|
||||
ops.c
|
||||
running ops.cem
|
||||
comparing ops
|
||||
***** cterr
|
||||
acc bugs.c
|
||||
bugs.c
|
||||
"bugs.c", line 92: warning: Overflow in constant expression
|
||||
running bugs.cem
|
||||
comparing bugs
|
||||
9,$c9,$
|
||||
< compl_ind
|
||||
< END
|
||||
---
|
||||
> END
|
||||
***** ctest1
|
||||
acc test.c
|
||||
test.c
|
||||
running test.cem
|
||||
comparing test
|
||||
***** ctest2
|
||||
acc t7.c
|
||||
t7.c
|
||||
"t7.c", line 161: warning: statement not reached
|
||||
"t7.c", line 178: warning: statement not reached
|
||||
"t7.c", line 182: warning: statement not reached
|
||||
"t7.c", line 186: warning: statement not reached
|
||||
"t7.c", line 190: warning: statement not reached
|
||||
"t7.c", line 194: warning: statement not reached
|
||||
"t7.c", line 198: warning: statement not reached
|
||||
"t7.c", line 205: warning: statement not reached
|
||||
"t7.c", line 207: warning: statement not reached
|
||||
"t7.c", line 211: warning: statement not reached
|
||||
"t7.c", line 213: warning: statement not reached
|
||||
"t7.c", line 287: warning: statement not reached
|
||||
"t7.c", line 294: warning: statement not reached
|
||||
"t7.c", line 300: warning: statement not reached
|
||||
"t7.c", line 307: warning: statement not reached
|
||||
"t7.c", line 343: warning: statement not reached
|
||||
"t7.c", line 344: warning: statement not reached
|
||||
"t7.c", line 345: warning: statement not reached
|
||||
"t7.c", line 346: warning: statement not reached
|
||||
"t7.c", line 348: warning: statement not reached
|
||||
"t7.c", line 452: warning: statement not reached
|
||||
"t7.c", line 561: warning: statement not reached
|
||||
"t7.c", line 589: warning: statement not reached
|
||||
running t7.cem
|
||||
comparing t7
|
||||
***** ctest3
|
||||
acc test2.c
|
||||
test2.c
|
||||
running test2.cem
|
||||
comparing test2
|
||||
***** ctest5
|
||||
acc test1.c
|
||||
test1.c
|
||||
"test1.c", line 101: warning: Illegal shift count in constant expression
|
||||
"test1.c", line 370: warning: illegal pointer combination
|
||||
"test1.c", line 371: warning: illegal pointer combination
|
||||
"test1.c", line 372: warning: illegal pointer combination
|
||||
"test1.c", line 384: warning: illegal pointer combination
|
||||
"test1.c", line 407: warning: illegal pointer combination
|
||||
"test1.c", line 408: warning: illegal pointer combination
|
||||
"test1.c", line 409: warning: illegal pointer combination
|
||||
"test1.c", line 421: warning: illegal pointer combination
|
||||
running test1.cem
|
||||
comparing test1
|
||||
***** ctgen
|
||||
`bf.c' is up to date.
|
||||
acc bf.c
|
||||
bf.c
|
||||
running bf.cem
|
||||
comparing bf
|
||||
`cel.c' is up to date.
|
||||
acc cel.c
|
||||
cel.c
|
||||
running cel.cem
|
||||
comparing cel
|
||||
`clu.c' is up to date.
|
||||
acc clu.c
|
||||
clu.c
|
||||
"clu.c", line 60: warning: Overflow in constant expression
|
||||
"clu.c", line 66: warning: Overflow in constant expression
|
||||
running clu.cem
|
||||
comparing clu
|
||||
28c28
|
||||
< x *= 40000 0
|
||||
---
|
||||
> x *= 40000 6784
|
||||
65c65
|
||||
< y = ( x *= 40000 ) 0 0
|
||||
---
|
||||
> y = ( x *= 40000 ) 6784 6784
|
||||
102c102
|
||||
< no if ( x *= 40000 ) yes() ; else no() 0
|
||||
---
|
||||
> yes if ( x *= 40000 ) yes() ; else no() 6784
|
||||
`ec.c' is up to date.
|
||||
acc ec.c
|
||||
ec.c
|
||||
"ec.c", line 58: warning: Overflow in constant expression
|
||||
"ec.c", line 64: warning: Overflow in constant expression
|
||||
running ec.cem
|
||||
comparing ec
|
||||
`ef.c' is up to date.
|
||||
acc ef.c
|
||||
ef.c
|
||||
running ef.cem
|
||||
comparing ef
|
||||
`ei.c' is up to date.
|
||||
acc ei.c
|
||||
ei.c
|
||||
"ei.c", line 22: warning: Overflow in constant expression
|
||||
"ei.c", line 65: warning: Overflow in constant expression
|
||||
"ei.c", line 108: warning: Overflow in constant expression
|
||||
running ei.cem
|
||||
comparing ei
|
||||
`el.c' is up to date.
|
||||
acc el.c
|
||||
el.c
|
||||
running el.cem
|
||||
comparing el
|
||||
`eu.c' is up to date.
|
||||
acc eu.c
|
||||
eu.c
|
||||
"eu.c", line 58: warning: Overflow in constant expression
|
||||
"eu.c", line 64: warning: Overflow in constant expression
|
||||
running eu.cem
|
||||
comparing eu
|
||||
28c28
|
||||
< x *= 40000 0
|
||||
---
|
||||
> x *= 40000 6784
|
||||
65c65
|
||||
< y = ( x *= 40000 ) 0 0
|
||||
---
|
||||
> y = ( x *= 40000 ) 6784 6784
|
||||
102c102
|
||||
< no if ( x *= 40000 ) yes() ; else no() 0
|
||||
---
|
||||
> yes if ( x *= 40000 ) yes() ; else no() 6784
|
||||
`id.c' is up to date.
|
||||
acc id.c
|
||||
id.c
|
||||
running id.cem
|
||||
comparing id
|
||||
`lc.c' is up to date.
|
||||
acc lc.c
|
||||
lc.c
|
||||
"lc.c", line 60: warning: Overflow in constant expression
|
||||
"lc.c", line 66: warning: Overflow in constant expression
|
||||
running lc.cem
|
||||
comparing lc
|
||||
`ld.c' is up to date.
|
||||
acc ld.c
|
||||
ld.c
|
||||
running ld.cem
|
||||
comparing ld
|
||||
`lf.c' is up to date.
|
||||
acc lf.c
|
||||
lf.c
|
3
lang/cem/libcc/.distr
Normal file
3
lang/cem/libcc/.distr
Normal file
|
@ -0,0 +1,3 @@
|
|||
gen
|
||||
mon
|
||||
stdio
|
|
@ -1,518 +0,0 @@
|
|||
/* L E X I C A L A N A L Y S E R F O R M O D U L A - 2 */
|
||||
|
||||
#include "debug.h"
|
||||
#include "idfsize.h"
|
||||
#include "numsize.h"
|
||||
#include "strsize.h"
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "f_info.h"
|
||||
#include "Lpars.h"
|
||||
#include "class.h"
|
||||
#include "idf.h"
|
||||
#include "type.h"
|
||||
#include "LLlex.h"
|
||||
#include "const.h"
|
||||
#include "warning.h"
|
||||
|
||||
long str2long();
|
||||
|
||||
struct token dot,
|
||||
aside;
|
||||
struct type *toktype;
|
||||
int idfsize = IDFSIZE;
|
||||
#ifdef DEBUG
|
||||
extern int cntlines;
|
||||
#endif
|
||||
|
||||
static int eofseen;
|
||||
|
||||
STATIC
|
||||
SkipComment()
|
||||
{
|
||||
/* Skip Modula-2 comments (* ... *).
|
||||
Note that comments may be nested (par. 3.5).
|
||||
*/
|
||||
register int ch;
|
||||
register int CommentLevel = 0;
|
||||
|
||||
LoadChar(ch);
|
||||
for (;;) {
|
||||
if (class(ch) == STNL) {
|
||||
LineNumber++;
|
||||
#ifdef DEBUG
|
||||
cntlines++;
|
||||
#endif
|
||||
}
|
||||
else if (ch == '(') {
|
||||
LoadChar(ch);
|
||||
if (ch == '*') CommentLevel++;
|
||||
else continue;
|
||||
}
|
||||
else if (ch == '*') {
|
||||
LoadChar(ch);
|
||||
if (ch == ')') {
|
||||
CommentLevel--;
|
||||
if (CommentLevel < 0) break;
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
else if (ch == EOI) {
|
||||
lexerror("unterminated comment");
|
||||
break;
|
||||
}
|
||||
LoadChar(ch);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC struct string *
|
||||
GetString(upto)
|
||||
{
|
||||
/* Read a Modula-2 string, delimited by the character "upto".
|
||||
*/
|
||||
register int ch;
|
||||
register struct string *str = (struct string *)
|
||||
Malloc((unsigned) sizeof(struct string));
|
||||
register char *p;
|
||||
register int len;
|
||||
|
||||
len = ISTRSIZE;
|
||||
str->s_str = p = Malloc((unsigned int) ISTRSIZE);
|
||||
while (LoadChar(ch), ch != upto) {
|
||||
if (class(ch) == STNL) {
|
||||
lexerror("newline in string");
|
||||
LineNumber++;
|
||||
#ifdef DEBUG
|
||||
cntlines++;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (ch == EOI) {
|
||||
lexerror("end-of-file in string");
|
||||
break;
|
||||
}
|
||||
*p++ = ch;
|
||||
if (p - str->s_str == len) {
|
||||
str->s_str = Srealloc(str->s_str,
|
||||
(unsigned int) len + RSTRSIZE);
|
||||
p = str->s_str + len;
|
||||
len += RSTRSIZE;
|
||||
}
|
||||
}
|
||||
str->s_length = p - str->s_str;
|
||||
while (p - str->s_str < len) *p++ = '\0';
|
||||
if (str->s_length == 0) str->s_length = 1;
|
||||
/* ??? string length at least 1 ??? */
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *s_error = "illegal line directive";
|
||||
|
||||
STATIC int
|
||||
getch()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
for (;;) {
|
||||
LoadChar(ch);
|
||||
if ((ch & 0200) && ch != EOI) {
|
||||
error("non-ascii '\\%03o' read", ch & 0377);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ch == EOI) {
|
||||
eofseen = 1;
|
||||
return '\n';
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
STATIC
|
||||
linedirective() {
|
||||
/* Read a line directive
|
||||
*/
|
||||
register int ch;
|
||||
register int i = 0;
|
||||
char buf[IDFSIZE + 2];
|
||||
register char *c = buf;
|
||||
|
||||
do { /*
|
||||
* Skip to next digit
|
||||
* Do not skip newlines
|
||||
*/
|
||||
ch = getch();
|
||||
if (class(ch) == STNL) {
|
||||
LineNumber++;
|
||||
error(s_error);
|
||||
return;
|
||||
}
|
||||
} while (class(ch) != STNUM);
|
||||
do {
|
||||
i = i*10 + (ch - '0');
|
||||
ch = getch();
|
||||
} while (class(ch) == STNUM);
|
||||
while (ch != '"' && class(ch) != STNL) ch = getch();
|
||||
if (ch == '"') {
|
||||
c = buf;
|
||||
do {
|
||||
*c++ = ch = getch();
|
||||
if (class(ch) == STNL) {
|
||||
LineNumber++;
|
||||
error(s_error);
|
||||
return;
|
||||
}
|
||||
} while (ch != '"');
|
||||
*--c = '\0';
|
||||
do {
|
||||
ch = getch();
|
||||
} while (class(ch) != STNL);
|
||||
/*
|
||||
* Remember the file name
|
||||
*/
|
||||
if (!eofseen && strcmp(FileName,buf)) {
|
||||
FileName = Salloc(buf,(unsigned) strlen(buf) + 1);
|
||||
}
|
||||
}
|
||||
if (eofseen) {
|
||||
error(s_error);
|
||||
return;
|
||||
}
|
||||
LineNumber = i;
|
||||
}
|
||||
|
||||
int
|
||||
LLlex()
|
||||
{
|
||||
/* LLlex() is the Lexical Analyzer.
|
||||
The putting aside of tokens is taken into account.
|
||||
*/
|
||||
register struct token *tk = ˙
|
||||
char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 2];
|
||||
register int ch, nch;
|
||||
|
||||
toktype = error_type;
|
||||
|
||||
if (ASIDE) { /* a token is put aside */
|
||||
*tk = aside;
|
||||
ASIDE = 0;
|
||||
return tk->tk_symb;
|
||||
}
|
||||
|
||||
tk->tk_lineno = LineNumber;
|
||||
|
||||
again2:
|
||||
if (eofseen) {
|
||||
eofseen = 0;
|
||||
ch = EOI;
|
||||
}
|
||||
else {
|
||||
again:
|
||||
LoadChar(ch);
|
||||
again1:
|
||||
if ((ch & 0200) && ch != EOI) {
|
||||
error("non-ascii '\\%03o' read", ch & 0377);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
switch (class(ch)) {
|
||||
|
||||
case STNL:
|
||||
LineNumber++;
|
||||
#ifdef DEBUG
|
||||
cntlines++;
|
||||
#endif
|
||||
tk->tk_lineno++;
|
||||
LoadChar(ch);
|
||||
if (ch != '#') goto again1;
|
||||
linedirective();
|
||||
goto again2;
|
||||
|
||||
case STSKIP:
|
||||
goto again;
|
||||
|
||||
case STGARB:
|
||||
if ((unsigned) ch - 040 < 0137) {
|
||||
lexerror("garbage char %c", ch);
|
||||
}
|
||||
else lexerror("garbage char \\%03o", ch);
|
||||
goto again;
|
||||
|
||||
case STSIMP:
|
||||
if (ch == '(') {
|
||||
LoadChar(nch);
|
||||
if (nch == '*') {
|
||||
SkipComment();
|
||||
goto again;
|
||||
}
|
||||
else if (nch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
}
|
||||
return tk->tk_symb = ch;
|
||||
|
||||
case STCOMP:
|
||||
LoadChar(nch);
|
||||
switch (ch) {
|
||||
|
||||
case '.':
|
||||
if (nch == '.') {
|
||||
return tk->tk_symb = UPTO;
|
||||
}
|
||||
break;
|
||||
|
||||
case ':':
|
||||
if (nch == '=') {
|
||||
return tk->tk_symb = BECOMES;
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
if (nch == '=') {
|
||||
return tk->tk_symb = LESSEQUAL;
|
||||
}
|
||||
if (nch == '>') {
|
||||
lexwarning(W_STRICT, "'<>' is old-fashioned; use '#'");
|
||||
return tk->tk_symb = '#';
|
||||
}
|
||||
break;
|
||||
|
||||
case '>':
|
||||
if (nch == '=') {
|
||||
return tk->tk_symb = GREATEREQUAL;
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
crash("(LLlex, STCOMP)");
|
||||
}
|
||||
if (nch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
return tk->tk_symb = ch;
|
||||
|
||||
case STIDF:
|
||||
{
|
||||
register char *tag = &buf[0];
|
||||
register struct idf *id;
|
||||
|
||||
do {
|
||||
if (tag - buf < idfsize) *tag++ = ch;
|
||||
LoadChar(ch);
|
||||
} while(in_idf(ch));
|
||||
|
||||
if (ch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
*tag++ = '\0';
|
||||
|
||||
tk->TOK_IDF = id = str2idf(buf, 1);
|
||||
return tk->tk_symb = id->id_reserved ? id->id_reserved : IDENT;
|
||||
}
|
||||
|
||||
case STSTR: {
|
||||
register struct string *str = GetString(ch);
|
||||
|
||||
if (str->s_length == 1) {
|
||||
tk->TOK_INT = *(str->s_str) & 0377;
|
||||
toktype = char_type;
|
||||
free(str->s_str);
|
||||
free((char *) str);
|
||||
}
|
||||
else {
|
||||
tk->tk_data.tk_str = str;
|
||||
toktype = standard_type(T_STRING, 1, str->s_length);
|
||||
}
|
||||
return tk->tk_symb = STRING;
|
||||
}
|
||||
|
||||
case STNUM:
|
||||
{
|
||||
/* The problem arising with the "parsing" of a number
|
||||
is that we don't know the base in advance so we
|
||||
have to read the number with the help of a rather
|
||||
complex finite automaton.
|
||||
*/
|
||||
enum statetp {Oct,Hex,Dec,OctEndOrHex,End,OptReal,Real};
|
||||
register enum statetp state;
|
||||
register int base;
|
||||
register char *np = &buf[1];
|
||||
/* allow a '-' to be added */
|
||||
|
||||
buf[0] = '-';
|
||||
*np++ = ch;
|
||||
state = is_oct(ch) ? Oct : Dec;
|
||||
LoadChar(ch);
|
||||
for (;;) {
|
||||
switch(state) {
|
||||
case Oct:
|
||||
while (is_oct(ch)) {
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (ch == 'B' || ch == 'C') {
|
||||
base = 8;
|
||||
state = OctEndOrHex;
|
||||
break;
|
||||
}
|
||||
/* Fall Through */
|
||||
case Dec:
|
||||
base = 10;
|
||||
while (is_dig(ch)) {
|
||||
if (np < &buf[NUMSIZE]) {
|
||||
*np++ = ch;
|
||||
}
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (is_hex(ch)) state = Hex;
|
||||
else if (ch == '.') state = OptReal;
|
||||
else {
|
||||
state = End;
|
||||
if (ch == 'H') base = 16;
|
||||
else if (ch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
}
|
||||
break;
|
||||
|
||||
case Hex:
|
||||
while (is_hex(ch)) {
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
base = 16;
|
||||
state = End;
|
||||
if (ch != 'H') {
|
||||
lexerror("H expected after hex number");
|
||||
if (ch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
}
|
||||
break;
|
||||
|
||||
case OctEndOrHex:
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
if (ch == 'H') {
|
||||
base = 16;
|
||||
state = End;
|
||||
break;
|
||||
}
|
||||
if (is_hex(ch)) {
|
||||
state = Hex;
|
||||
break;
|
||||
}
|
||||
if (ch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
ch = *--np;
|
||||
*np++ = '\0';
|
||||
base = 8;
|
||||
/* Fall through */
|
||||
|
||||
case End:
|
||||
*np = '\0';
|
||||
if (np >= &buf[NUMSIZE]) {
|
||||
tk->TOK_INT = 1;
|
||||
lexerror("constant too long");
|
||||
}
|
||||
else {
|
||||
np = &buf[1];
|
||||
while (*np == '0') np++;
|
||||
tk->TOK_INT = str2long(np, base);
|
||||
if (strlen(np) > 14 /* ??? */ ||
|
||||
tk->TOK_INT < 0) {
|
||||
lexwarning(W_ORDINARY, "overflow in constant");
|
||||
}
|
||||
}
|
||||
if (ch == 'C' && base == 8) {
|
||||
toktype = char_type;
|
||||
if (tk->TOK_INT<0 || tk->TOK_INT>255) {
|
||||
lexwarning(W_ORDINARY, "character constant out of range");
|
||||
}
|
||||
}
|
||||
else if (tk->TOK_INT>=0 &&
|
||||
tk->TOK_INT<=max_int) {
|
||||
toktype = intorcard_type;
|
||||
}
|
||||
else toktype = card_type;
|
||||
return tk->tk_symb = INTEGER;
|
||||
|
||||
case OptReal:
|
||||
/* The '.' could be the first of the '..'
|
||||
token. At this point, we need a
|
||||
look-ahead of two characters.
|
||||
*/
|
||||
LoadChar(ch);
|
||||
if (ch == '.') {
|
||||
/* Indeed the '..' token
|
||||
*/
|
||||
PushBack();
|
||||
PushBack();
|
||||
state = End;
|
||||
base = 10;
|
||||
break;
|
||||
}
|
||||
state = Real;
|
||||
break;
|
||||
}
|
||||
if (state == Real) break;
|
||||
}
|
||||
|
||||
/* a real real constant */
|
||||
if (np < &buf[NUMSIZE]) *np++ = '.';
|
||||
|
||||
while (is_dig(ch)) {
|
||||
/* Fractional part
|
||||
*/
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
|
||||
if (ch == 'E') {
|
||||
/* Scale factor
|
||||
*/
|
||||
if (np < &buf[NUMSIZE]) *np++ = 'E';
|
||||
LoadChar(ch);
|
||||
if (ch == '+' || ch == '-') {
|
||||
/* Signed scalefactor
|
||||
*/
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (is_dig(ch)) {
|
||||
do {
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
} while (is_dig(ch));
|
||||
}
|
||||
else {
|
||||
lexerror("bad scale factor");
|
||||
}
|
||||
}
|
||||
|
||||
*np++ = '\0';
|
||||
if (ch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
|
||||
if (np >= &buf[NUMSIZE]) {
|
||||
tk->TOK_REL = Salloc("0.0", 5);
|
||||
lexerror("floating constant too long");
|
||||
}
|
||||
else tk->TOK_REL = Salloc(buf, np - buf) + 1;
|
||||
toktype = real_type;
|
||||
return tk->tk_symb = REAL;
|
||||
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
case STEOI:
|
||||
return tk->tk_symb = -1;
|
||||
|
||||
case STCHAR:
|
||||
default:
|
||||
crash("(LLlex) Impossible character class");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/* T O K E N D E S C R I P T O R D E F I N I T I O N */
|
||||
|
||||
/* Structure to store a string constant
|
||||
*/
|
||||
struct string {
|
||||
arith s_length; /* length of a string */
|
||||
char *s_str; /* the string itself */
|
||||
};
|
||||
|
||||
/* Token structure. Keep it small, as it is part of a parse-tree node
|
||||
*/
|
||||
struct token {
|
||||
short tk_symb; /* token itself */
|
||||
unsigned short tk_lineno; /* linenumber on which it occurred */
|
||||
union {
|
||||
struct idf *tk_idf; /* IDENT */
|
||||
struct string *tk_str; /* STRING */
|
||||
arith tk_int; /* INTEGER */
|
||||
char *tk_real; /* REAL */
|
||||
arith *tk_set; /* only used in parse tree node */
|
||||
struct def *tk_def; /* only used in parse tree node */
|
||||
label tk_lab; /* only used in parse tree node */
|
||||
} tk_data;
|
||||
};
|
||||
|
||||
#define TOK_IDF tk_data.tk_idf
|
||||
#define TOK_STR tk_data.tk_str->s_str
|
||||
#define TOK_SLE tk_data.tk_str->s_length
|
||||
#define TOK_INT tk_data.tk_int
|
||||
#define TOK_REL tk_data.tk_real
|
||||
|
||||
extern struct token dot, aside;
|
||||
extern struct type *toktype;
|
||||
|
||||
#define DOT dot.tk_symb
|
||||
#define ASIDE aside.tk_symb
|
|
@ -1,58 +0,0 @@
|
|||
/* S Y N T A X E R R O R R E P O R T I N G */
|
||||
|
||||
/* Defines the LLmessage routine. LLgen-generated parsers require the
|
||||
existence of a routine of that name.
|
||||
The routine must do syntax-error reporting and must be able to
|
||||
insert tokens in the token stream.
|
||||
*/
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
|
||||
extern char *symbol2str();
|
||||
extern struct idf *gen_anon_idf();
|
||||
|
||||
LLmessage(tk)
|
||||
register int tk;
|
||||
{
|
||||
if (tk > 0) {
|
||||
/* if (tk > 0), it represents the token to be inserted.
|
||||
*/
|
||||
register struct token *dotp = ˙
|
||||
|
||||
error("%s missing", symbol2str(tk));
|
||||
|
||||
aside = *dotp;
|
||||
|
||||
dotp->tk_symb = tk;
|
||||
|
||||
switch (tk) {
|
||||
/* The operands need some body */
|
||||
case IDENT:
|
||||
dotp->TOK_IDF = gen_anon_idf();
|
||||
break;
|
||||
case STRING:
|
||||
dotp->tk_data.tk_str = (struct string *)
|
||||
Malloc(sizeof (struct string));
|
||||
dotp->TOK_SLE = 1;
|
||||
dotp->TOK_STR = Salloc("", 1);
|
||||
break;
|
||||
case INTEGER:
|
||||
dotp->TOK_INT = 1;
|
||||
break;
|
||||
case REAL:
|
||||
dotp->TOK_REL = Salloc("0.0", 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (tk < 0) {
|
||||
error("garbage at end of program");
|
||||
}
|
||||
else error("%s deleted", symbol2str(dot.tk_symb));
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
V=`cat Version.c`
|
||||
VERSION=`expr "$V" ':' '.*[0-9][0-9]*\.\([0-9][0-9]*\).*'`
|
||||
NEWVERSION=`expr $VERSION + 1`
|
||||
sed "s/\.$VERSION/.$NEWVERSION/" < Version.c > tmp$$
|
||||
mv tmp$$ Version.c
|
||||
CM "$*"
|
||||
V=`cat Version.c`
|
||||
SV > ../versions/V`expr "$V" ':' '.*\([0-9][0-9]*\.[0-9][0-9]*\).*'`
|
|
@ -1,167 +0,0 @@
|
|||
# make modula-2 "compiler"
|
||||
EMHOME = ../../..
|
||||
MHDIR = $(EMHOME)/modules/h
|
||||
PKGDIR = $(EMHOME)/modules/pkg
|
||||
LIBDIR = $(EMHOME)/modules/lib
|
||||
OBJECTCODE = $(LIBDIR)/libemk.a
|
||||
LLGEN = $(EMHOME)/bin/LLgen
|
||||
MKDEP = $(EMHOME)/bin/mkdep
|
||||
PRID = $(EMHOME)/bin/prid
|
||||
CID = $(EMHOME)/bin/cid
|
||||
CURRDIR = .
|
||||
|
||||
INCLUDES = -I$(MHDIR) -I$(EMHOME)/h -I$(PKGDIR)
|
||||
|
||||
GFILES = tokenfile.g program.g declar.g expression.g statement.g
|
||||
LLGENOPTIONS =
|
||||
PROFILE =
|
||||
CFLAGS = $(PROFILE) $(INCLUDES) -DSTATIC=
|
||||
LINTFLAGS = -DSTATIC= -DNORCSID
|
||||
MALLOC = $(LIBDIR)/malloc.o
|
||||
LFLAGS = $(PROFILE)
|
||||
LSRC = tokenfile.c program.c declar.c expression.c statement.c
|
||||
LOBJ = tokenfile.o program.o declar.o expression.o statement.o
|
||||
CSRC = LLlex.c LLmessage.c char.c error.c main.c \
|
||||
symbol2str.c tokenname.c idf.c input.c type.c def.c \
|
||||
scope.c misc.c enter.c defmodule.c typequiv.c node.c \
|
||||
cstoper.c chk_expr.c options.c walk.c casestat.c desig.c \
|
||||
code.c tmpvar.c lookup.c Version.c next.c
|
||||
COBJ = LLlex.o LLmessage.o char.o error.o main.o \
|
||||
symbol2str.o tokenname.o idf.o input.o type.o def.o \
|
||||
scope.o misc.o enter.o defmodule.o typequiv.o node.o \
|
||||
cstoper.o chk_expr.o options.o walk.o casestat.o desig.o \
|
||||
code.o tmpvar.o lookup.o Version.o next.o
|
||||
SRC = $(CSRC) $(LSRC) Lpars.c
|
||||
OBJ = $(COBJ) $(LOBJ) Lpars.o
|
||||
|
||||
# Keep the next entries up to date!
|
||||
GENCFILES= tokenfile.c \
|
||||
program.c declar.c expression.c statement.c \
|
||||
symbol2str.c char.c Lpars.c casestat.c tmpvar.c scope.c next.c
|
||||
GENGFILES= tokenfile.g
|
||||
GENHFILES= errout.h\
|
||||
idfsize.h numsize.h strsize.h target_sizes.h \
|
||||
inputtype.h maxset.h ndir.h density.h\
|
||||
def.h debugcst.h type.h Lpars.h node.h
|
||||
HFILES= LLlex.h\
|
||||
chk_expr.h class.h const.h debug.h desig.h f_info.h idf.h\
|
||||
input.h main.h misc.h scope.h standards.h tokenname.h\
|
||||
walk.h warning.h $(GENHFILES)
|
||||
#
|
||||
GENFILES = $(GENGFILES) $(GENCFILES) $(GENHFILES)
|
||||
NEXTFILES = def.H type.H node.H scope.C tmpvar.C casestat.C
|
||||
|
||||
#EXCLEXCLEXCLEXCL
|
||||
|
||||
all: Cfiles
|
||||
sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make $(CURRDIR)/main ; else sh Resolve main ; fi'
|
||||
@rm -f nmclash.o a.out
|
||||
|
||||
install: all
|
||||
cp $(CURRDIR)/main $(EMHOME)/lib/em_m2
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(GENFILES) LLfiles hfiles Cfiles tab clashes $(CURRDIR)/main
|
||||
(cd .. ; rm -rf Xsrc)
|
||||
|
||||
lint: Cfiles
|
||||
sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make Xlint ; else sh Resolve Xlint ; fi'
|
||||
@rm -f nmclash.o a.out
|
||||
|
||||
longnames: $(SRC) $(HFILES)
|
||||
sh -c 'if test -f longnames ; then $(PRID) -l7 longnames $? > Xlongnames ; mv Xlongnames longnames ; else $(PRID) -l7 $? > longnames ; fi'
|
||||
|
||||
# entry points not to be used directly
|
||||
|
||||
Cfiles: hfiles LLfiles $(GENCFILES) $(GENHFILES) Makefile
|
||||
echo $(SRC) $(HFILES) > Cfiles
|
||||
|
||||
LLfiles: $(GFILES)
|
||||
$(LLGEN) $(LLGENOPTIONS) $(GFILES)
|
||||
@touch LLfiles
|
||||
|
||||
hfiles: Parameters make.hfiles
|
||||
make.hfiles Parameters
|
||||
touch hfiles
|
||||
|
||||
tokenfile.g: tokenname.c make.tokfile
|
||||
make.tokfile <tokenname.c >tokenfile.g
|
||||
|
||||
symbol2str.c: tokenname.c make.tokcase
|
||||
make.tokcase <tokenname.c >symbol2str.c
|
||||
|
||||
.SUFFIXES: .H .h
|
||||
.H.h:
|
||||
./make.allocd < $*.H > $*.h
|
||||
|
||||
.SUFFIXES: .C .c
|
||||
.C.c:
|
||||
./make.allocd < $*.C > $*.c
|
||||
|
||||
def.h: make.allocd
|
||||
type.h: make.allocd
|
||||
node.h: make.allocd
|
||||
scope.c: make.allocd
|
||||
tmpvar.c: make.allocd
|
||||
casestat.c: make.allocd
|
||||
|
||||
next.c: $(NEXTFILES) ./make.next
|
||||
./make.next $(NEXTFILES) > next.c
|
||||
|
||||
char.c: char.tab tab
|
||||
tab -fchar.tab >char.c
|
||||
|
||||
tab:
|
||||
$(CC) tab.c -o tab
|
||||
|
||||
depend:
|
||||
sed '/^#AUTOAUTO/,$$d' Makefile > Makefile.new
|
||||
echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >> Makefile.new
|
||||
$(MKDEP) $(SRC) |\
|
||||
sed 's/\.c:/\.o:/' >> Makefile.new
|
||||
mv Makefile Makefile.old
|
||||
mv Makefile.new Makefile
|
||||
|
||||
#INCLINCLINCLINCL
|
||||
|
||||
Xlint:
|
||||
lint $(INCLUDES) $(LINTFLAGS) $(SRC)
|
||||
|
||||
$(CURRDIR)/main: $(OBJ)
|
||||
$(CC) $(LFLAGS) $(OBJ) $(LIBDIR)/libem_mes.a $(OBJECTCODE) $(LIBDIR)/libinput.a $(LIBDIR)/libassert.a $(LIBDIR)/liballoc.a $(MALLOC) $(LIBDIR)/libprint.a $(LIBDIR)/libstring.a $(LIBDIR)/libsystem.a -o $(CURRDIR)/main
|
||||
size $(CURRDIR)/main
|
||||
|
||||
#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
|
||||
LLlex.o: LLlex.h Lpars.h class.h const.h debug.h debugcst.h f_info.h idf.h idfsize.h input.h inputtype.h numsize.h strsize.h type.h warning.h
|
||||
LLmessage.o: LLlex.h Lpars.h idf.h
|
||||
char.o: class.h
|
||||
error.o: LLlex.h debug.h debugcst.h errout.h f_info.h input.h inputtype.h main.h node.h warning.h
|
||||
main.o: LLlex.h Lpars.h debug.h debugcst.h def.h f_info.h idf.h input.h inputtype.h ndir.h node.h scope.h standards.h tokenname.h type.h warning.h
|
||||
symbol2str.o: Lpars.h
|
||||
tokenname.o: Lpars.h idf.h tokenname.h
|
||||
idf.o: idf.h
|
||||
input.o: def.h f_info.h idf.h input.h inputtype.h scope.h
|
||||
type.o: LLlex.h const.h debug.h debugcst.h def.h idf.h maxset.h node.h scope.h target_sizes.h type.h walk.h
|
||||
def.o: LLlex.h Lpars.h debug.h debugcst.h def.h idf.h main.h node.h scope.h type.h
|
||||
scope.o: LLlex.h debug.h debugcst.h def.h idf.h node.h scope.h type.h
|
||||
misc.o: LLlex.h f_info.h idf.h misc.h node.h
|
||||
enter.o: LLlex.h debug.h debugcst.h def.h idf.h main.h misc.h node.h scope.h type.h
|
||||
defmodule.o: LLlex.h Lpars.h debug.h debugcst.h def.h f_info.h idf.h input.h inputtype.h main.h misc.h node.h scope.h type.h
|
||||
typequiv.o: LLlex.h debug.h debugcst.h def.h node.h type.h warning.h
|
||||
node.o: LLlex.h debug.h debugcst.h def.h node.h type.h
|
||||
cstoper.o: LLlex.h Lpars.h debug.h debugcst.h idf.h node.h standards.h target_sizes.h type.h warning.h
|
||||
chk_expr.o: LLlex.h Lpars.h chk_expr.h const.h debug.h debugcst.h def.h idf.h misc.h node.h scope.h standards.h type.h warning.h
|
||||
options.o: idfsize.h main.h ndir.h type.h warning.h
|
||||
walk.o: LLlex.h Lpars.h chk_expr.h debug.h debugcst.h def.h desig.h f_info.h idf.h main.h node.h scope.h type.h walk.h warning.h
|
||||
casestat.o: LLlex.h Lpars.h debug.h debugcst.h density.h desig.h node.h type.h walk.h
|
||||
desig.o: LLlex.h debug.h debugcst.h def.h desig.h node.h scope.h type.h
|
||||
code.o: LLlex.h Lpars.h debug.h debugcst.h def.h desig.h node.h scope.h standards.h type.h walk.h
|
||||
tmpvar.o: debug.h debugcst.h def.h main.h scope.h type.h
|
||||
lookup.o: LLlex.h debug.h debugcst.h def.h idf.h misc.h node.h scope.h type.h
|
||||
next.o: debug.h debugcst.h
|
||||
tokenfile.o: Lpars.h
|
||||
program.o: LLlex.h Lpars.h debug.h debugcst.h def.h f_info.h idf.h main.h node.h scope.h type.h warning.h
|
||||
declar.o: LLlex.h Lpars.h chk_expr.h debug.h debugcst.h def.h idf.h main.h misc.h node.h scope.h type.h warning.h
|
||||
expression.o: LLlex.h Lpars.h chk_expr.h const.h debug.h debugcst.h def.h idf.h node.h type.h warning.h
|
||||
statement.o: LLlex.h Lpars.h def.h idf.h node.h scope.h type.h
|
||||
Lpars.o: Lpars.h
|
|
@ -1,65 +0,0 @@
|
|||
!File: errout.h
|
||||
#define ERROUT STDERR /* file pointer for writing messages */
|
||||
#define MAXERR_LINE 100 /* maximum number of error messages given
|
||||
on the same input line. */
|
||||
|
||||
|
||||
!File: idfsize.h
|
||||
#define IDFSIZE 128 /* maximum significant length of an identifier */
|
||||
|
||||
|
||||
!File: numsize.h
|
||||
#define NUMSIZE 256 /* maximum length of a numeric constant */
|
||||
|
||||
|
||||
!File: strsize.h
|
||||
#define ISTRSIZE 32 /* minimum number of bytes allocated for
|
||||
storing a string */
|
||||
#define RSTRSIZE 8 /* step size in enlarging the memory for
|
||||
the storage of a string */
|
||||
|
||||
|
||||
!File: target_sizes.h
|
||||
#define MAXSIZE 8 /* the maximum of the SZ_* constants */
|
||||
|
||||
/* target machine sizes */
|
||||
#define SZ_CHAR (arith)1
|
||||
#define SZ_SHORT (arith)2
|
||||
#define SZ_WORD (arith)4
|
||||
#define SZ_INT (arith)4
|
||||
#define SZ_LONG (arith)4
|
||||
#define SZ_FLOAT (arith)4
|
||||
#define SZ_DOUBLE (arith)8
|
||||
#define SZ_POINTER (arith)4
|
||||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT (int)SZ_SHORT
|
||||
#define AL_WORD (int)SZ_WORD
|
||||
#define AL_INT (int)SZ_WORD
|
||||
#define AL_LONG (int)SZ_WORD
|
||||
#define AL_FLOAT (int)SZ_WORD
|
||||
#define AL_DOUBLE (int)SZ_WORD
|
||||
#define AL_POINTER (int)SZ_WORD
|
||||
#define AL_STRUCT 1
|
||||
#define AL_UNION 1
|
||||
|
||||
|
||||
!File: debugcst.h
|
||||
#define DEBUG 1 /* perform various self-tests */
|
||||
|
||||
!File: inputtype.h
|
||||
#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: maxset.h
|
||||
#define MAXSET 1024 /* maximum number of elements in a set,
|
||||
but what is a reasonable choice ???
|
||||
*/
|
||||
|
||||
!File: ndir.h
|
||||
#define NDIRS 16 /* maximum number of directories searched */
|
||||
|
||||
|
||||
!File: density.h
|
||||
#define DENSITY 3 /* see casestat.C for an explanation */
|
|
@ -1,54 +0,0 @@
|
|||
: create a directory Xsrc with name clashes resolved
|
||||
: and run make in that directory
|
||||
|
||||
case $# in
|
||||
1)
|
||||
;;
|
||||
*) echo "$0: one argument expected" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
currdir=`pwd`
|
||||
case $1 in
|
||||
main) target=$currdir/$1
|
||||
;;
|
||||
Xlint) target=$1
|
||||
;;
|
||||
*) echo "$0: $1: Illegal argument" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if test -d ../Xsrc
|
||||
then
|
||||
:
|
||||
else mkdir ../Xsrc
|
||||
fi
|
||||
make longnames
|
||||
: remove code generating routines from the clashes list as they are defines.
|
||||
: code generating routine names start with C_
|
||||
sed '/^C_/d' < longnames > tmp$$
|
||||
cclash -c -l7 tmp$$ > ../Xsrc/Xclashes
|
||||
rm -f tmp$$
|
||||
PW=`pwd`
|
||||
cd ../Xsrc
|
||||
if cmp -s Xclashes clashes
|
||||
then
|
||||
:
|
||||
else
|
||||
mv Xclashes clashes
|
||||
fi
|
||||
rm -f Makefile
|
||||
ed - $PW/Makefile <<'EOF'
|
||||
/^#EXCLEXCL/,/^#INCLINCL/d
|
||||
w Makefile
|
||||
q
|
||||
EOF
|
||||
for i in `cat $PW/Cfiles`
|
||||
do
|
||||
cat >> Makefile <<EOF
|
||||
|
||||
$i: clashes $PW/$i
|
||||
\$(CID) -Fclashes < $PW/$i > $i
|
||||
EOF
|
||||
done
|
||||
make CURRDIR=$currdir $target
|
|
@ -1 +0,0 @@
|
|||
static char Version[] = "ACK Modula-2 compiler Version 0.10";
|
|
@ -1,309 +0,0 @@
|
|||
/* C A S E S T A T E M E N T C O D E G E N E R A T I O N */
|
||||
|
||||
/* Generation of case statements is done by first creating a
|
||||
description structure for the statement, build a list of the
|
||||
case-labels, then generating a case description in the code,
|
||||
and generating either CSA or CSB, and then generating code for the
|
||||
cases themselves.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_label.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_code.h>
|
||||
#include <alloc.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "Lpars.h"
|
||||
#include "type.h"
|
||||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
#include "desig.h"
|
||||
#include "walk.h"
|
||||
|
||||
#include "density.h"
|
||||
|
||||
struct switch_hdr {
|
||||
struct switch_hdr *next; /* in the free list */
|
||||
label sh_break; /* label of statement after this one */
|
||||
label sh_default; /* label of ELSE part, or 0 */
|
||||
int sh_nrofentries; /* number of cases */
|
||||
struct type *sh_type; /* type of case expression */
|
||||
arith sh_lowerbd; /* lowest case label */
|
||||
arith sh_upperbd; /* highest case label */
|
||||
struct case_entry *sh_entries; /* the cases with their generated
|
||||
labels
|
||||
*/
|
||||
};
|
||||
|
||||
/* STATICALLOCDEF "switch_hdr" 5 */
|
||||
|
||||
struct case_entry {
|
||||
struct case_entry *next; /* next in list */
|
||||
label ce_label; /* generated label */
|
||||
arith ce_value; /* value of case label */
|
||||
};
|
||||
|
||||
/* STATICALLOCDEF "case_entry" 20 */
|
||||
|
||||
/* The constant DENSITY determines when CSA and when CSB instructions
|
||||
are generated. Reasonable values are: 2, 3, 4.
|
||||
On machines that have lots of address space and memory, higher values
|
||||
might also be reasonable. On these machines the density of jump tables
|
||||
may be lower.
|
||||
*/
|
||||
#define compact(nr, low, up) (nr != 0 && (up - low) / nr <= DENSITY)
|
||||
|
||||
CaseCode(nd, exitlabel)
|
||||
struct node *nd;
|
||||
label exitlabel;
|
||||
{
|
||||
/* Check the expression, stack a new case header and
|
||||
fill in the necessary fields.
|
||||
"exitlabel" is the exit-label of the closest enclosing
|
||||
LOOP-statement, or 0.
|
||||
*/
|
||||
register struct switch_hdr *sh = new_switch_hdr();
|
||||
register struct node *pnode = nd;
|
||||
register struct case_entry *ce;
|
||||
register arith val;
|
||||
label CaseDescrLab;
|
||||
int casecnt = 0;
|
||||
|
||||
assert(pnode->nd_class == Stat && pnode->nd_symb == CASE);
|
||||
|
||||
WalkExpr(pnode->nd_left); /* evaluate case expression */
|
||||
sh->sh_type = pnode->nd_left->nd_type;
|
||||
sh->sh_break = ++text_label;
|
||||
|
||||
/* Now, create case label list
|
||||
*/
|
||||
while (pnode->nd_right) {
|
||||
pnode = pnode->nd_right;
|
||||
if (pnode->nd_class == Link && pnode->nd_symb == '|') {
|
||||
if (pnode->nd_left) {
|
||||
/* non-empty case
|
||||
*/
|
||||
pnode->nd_lab = ++text_label;
|
||||
casecnt++;
|
||||
if (! AddCases(sh, /* to descriptor */
|
||||
pnode->nd_left->nd_left,
|
||||
/* of case labels */
|
||||
pnode->nd_lab
|
||||
/* and code label */
|
||||
)) {
|
||||
FreeSh(sh);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Else part
|
||||
*/
|
||||
|
||||
sh->sh_default = ++text_label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!casecnt) {
|
||||
/* There were no cases, so we have to check the case-expression
|
||||
here
|
||||
*/
|
||||
if (! (sh->sh_type->tp_fund & T_DISCRETE)) {
|
||||
node_error(nd, "illegal type in CASE-expression");
|
||||
FreeSh(sh);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now generate code for the switch itself
|
||||
First the part that CSA and CSB descriptions have in common.
|
||||
*/
|
||||
CaseDescrLab = ++data_label; /* the rom must have a label */
|
||||
C_df_dlb(CaseDescrLab);
|
||||
if (sh->sh_default) C_rom_ilb(sh->sh_default);
|
||||
else C_rom_ucon("0", pointer_size);
|
||||
if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
|
||||
/* CSA
|
||||
*/
|
||||
C_rom_cst(sh->sh_lowerbd);
|
||||
C_rom_cst(sh->sh_upperbd - sh->sh_lowerbd);
|
||||
ce = sh->sh_entries;
|
||||
for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
|
||||
assert(ce);
|
||||
if (val == ce->ce_value) {
|
||||
C_rom_ilb(ce->ce_label);
|
||||
ce = ce->next;
|
||||
}
|
||||
else if (sh->sh_default) C_rom_ilb(sh->sh_default);
|
||||
else C_rom_ucon("0", pointer_size);
|
||||
}
|
||||
C_lae_dlb(CaseDescrLab, (arith)0); /* perform the switch */
|
||||
C_csa(word_size);
|
||||
}
|
||||
else {
|
||||
/* CSB
|
||||
*/
|
||||
C_rom_cst((arith)sh->sh_nrofentries);
|
||||
for (ce = sh->sh_entries; ce; ce = ce->next) {
|
||||
/* generate the entries: value + prog.label
|
||||
*/
|
||||
C_rom_cst(ce->ce_value);
|
||||
C_rom_ilb(ce->ce_label);
|
||||
}
|
||||
C_lae_dlb(CaseDescrLab, (arith)0); /* perform the switch */
|
||||
C_csb(word_size);
|
||||
}
|
||||
|
||||
/* Now generate code for the cases
|
||||
*/
|
||||
pnode = nd;
|
||||
while (pnode->nd_right) {
|
||||
pnode = pnode->nd_right;
|
||||
if (pnode->nd_class == Link && pnode->nd_symb == '|') {
|
||||
if (pnode->nd_left) {
|
||||
C_df_ilb(pnode->nd_lab);
|
||||
WalkNode(pnode->nd_left->nd_right, exitlabel);
|
||||
C_bra(sh->sh_break);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Else part
|
||||
*/
|
||||
assert(sh->sh_default != 0);
|
||||
|
||||
C_df_ilb(sh->sh_default);
|
||||
WalkNode(pnode, exitlabel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
C_df_ilb(sh->sh_break);
|
||||
FreeSh(sh);
|
||||
}
|
||||
|
||||
FreeSh(sh)
|
||||
register struct switch_hdr *sh;
|
||||
{
|
||||
/* free the allocated switch structure
|
||||
*/
|
||||
register struct case_entry *ce;
|
||||
|
||||
ce = sh->sh_entries;
|
||||
while (ce) {
|
||||
struct case_entry *tmp = ce->next;
|
||||
|
||||
free_case_entry(ce);
|
||||
ce = tmp;
|
||||
}
|
||||
|
||||
free_switch_hdr(sh);
|
||||
}
|
||||
|
||||
AddCases(sh, node, lbl)
|
||||
struct switch_hdr *sh;
|
||||
register struct node *node;
|
||||
label lbl;
|
||||
{
|
||||
/* Add case labels to the case label list
|
||||
*/
|
||||
register arith v1, v2;
|
||||
|
||||
if (node->nd_class == Link) {
|
||||
if (node->nd_symb == UPTO) {
|
||||
assert(node->nd_left->nd_class == Value);
|
||||
assert(node->nd_right->nd_class == Value);
|
||||
|
||||
v2 = node->nd_right->nd_INT;
|
||||
node->nd_type = node->nd_left->nd_type;
|
||||
for (v1 = node->nd_left->nd_INT; v1 <= v2; v1++) {
|
||||
node->nd_INT = v1;
|
||||
if (! AddOneCase(sh, node, lbl)) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
assert(node->nd_symb == ',');
|
||||
return AddCases(sh, node->nd_left, lbl) &&
|
||||
AddCases(sh, node->nd_right, lbl);
|
||||
}
|
||||
|
||||
assert(node->nd_class == Value);
|
||||
return AddOneCase(sh, node, lbl);
|
||||
}
|
||||
|
||||
AddOneCase(sh, node, lbl)
|
||||
register struct switch_hdr *sh;
|
||||
register struct node *node;
|
||||
label lbl;
|
||||
{
|
||||
register struct case_entry *ce = new_case_entry();
|
||||
register struct case_entry *c1 = sh->sh_entries, *c2 = 0;
|
||||
|
||||
ce->ce_label = lbl;
|
||||
ce->ce_value = node->nd_INT;
|
||||
if (! TstCompat(sh->sh_type, node->nd_type)) {
|
||||
node_error(node, "type incompatibility in case");
|
||||
free_case_entry(ce);
|
||||
return 0;
|
||||
}
|
||||
if (sh->sh_entries == 0) {
|
||||
/* first case entry
|
||||
*/
|
||||
ce->next = (struct case_entry *) 0;
|
||||
sh->sh_entries = ce;
|
||||
sh->sh_lowerbd = sh->sh_upperbd = ce->ce_value;
|
||||
sh->sh_nrofentries = 1;
|
||||
}
|
||||
else {
|
||||
/* second etc. case entry
|
||||
find the proper place to put ce into the list
|
||||
*/
|
||||
|
||||
if (ce->ce_value < sh->sh_lowerbd) {
|
||||
sh->sh_lowerbd = ce->ce_value;
|
||||
}
|
||||
else if (ce->ce_value > sh->sh_upperbd) {
|
||||
sh->sh_upperbd = ce->ce_value;
|
||||
}
|
||||
while (c1 && c1->ce_value < ce->ce_value) {
|
||||
c2 = c1;
|
||||
c1 = c1->next;
|
||||
}
|
||||
/* At this point three cases are possible:
|
||||
1: c1 != 0 && c2 != 0:
|
||||
insert ce somewhere in the middle
|
||||
2: c1 != 0 && c2 == 0:
|
||||
insert ce right after the head
|
||||
3: c1 == 0 && c2 != 0:
|
||||
append ce to last element
|
||||
The case c1 == 0 && c2 == 0 cannot occur, since
|
||||
the list is guaranteed not to be empty.
|
||||
*/
|
||||
if (c1) {
|
||||
if (c1->ce_value == ce->ce_value) {
|
||||
node_error(node, "multiple case entry for value %ld", ce->ce_value);
|
||||
free_case_entry(ce);
|
||||
return 0;
|
||||
}
|
||||
if (c2) {
|
||||
ce->next = c2->next;
|
||||
c2->next = ce;
|
||||
}
|
||||
else {
|
||||
ce->next = sh->sh_entries;
|
||||
sh->sh_entries = ce;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(c2);
|
||||
|
||||
ce->next = (struct case_entry *) 0;
|
||||
c2->next = ce;
|
||||
}
|
||||
(sh->sh_nrofentries)++;
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
% character tables for mod2 compiler
|
||||
% $Header$
|
||||
%S129
|
||||
%F %s,
|
||||
%
|
||||
% CHARACTER CLASSES
|
||||
%
|
||||
%C
|
||||
STGARB:\000-\200
|
||||
STSKIP: \r\t
|
||||
STNL:\012\013\014
|
||||
STSIMP:#&()*+,-/;=[]^{|}~
|
||||
STCOMP:.:<>
|
||||
STIDF:a-zA-Z
|
||||
STSTR:"'
|
||||
STNUM:0-9
|
||||
STEOI:\200
|
||||
%T#include "class.h"
|
||||
%Tchar tkclass[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% INIDF
|
||||
%
|
||||
%C
|
||||
1:a-zA-Z0-9
|
||||
%Tchar inidf[] = {
|
||||
%F %s,
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISDIG
|
||||
%
|
||||
%C
|
||||
1:0-9
|
||||
%Tchar isdig[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISHEX
|
||||
%
|
||||
%C
|
||||
1:a-fA-F
|
||||
%Tchar ishex[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISOCT
|
||||
%
|
||||
%C
|
||||
1:0-7
|
||||
%Tchar isoct[] = {
|
||||
%p
|
||||
%T};
|
File diff suppressed because it is too large
Load diff
|
@ -1,11 +0,0 @@
|
|||
/* E X P R E S S I O N C H E C K I N G */
|
||||
|
||||
extern int (*ExprChkTable[])(); /* table of expression checking
|
||||
functions, indexed by node class
|
||||
*/
|
||||
extern int (*DesigChkTable[])(); /* table of designator checking
|
||||
functions, indexed by node class
|
||||
*/
|
||||
|
||||
#define ChkExpression(expp) ((*ExprChkTable[(expp)->nd_class])(expp))
|
||||
#define ChkDesignator(expp) ((*DesigChkTable[(expp)->nd_class])(expp))
|
|
@ -1,36 +0,0 @@
|
|||
/* U S E O F C H A R A C T E R C L A S S E S */
|
||||
|
||||
/* As a starter, chars are divided into classes, according to which
|
||||
token they can be the start of.
|
||||
At present such a class number is supposed to fit in 4 bits.
|
||||
*/
|
||||
|
||||
#define class(ch) (tkclass[ch])
|
||||
|
||||
/* Being the start of a token is, fortunately, a mutual exclusive
|
||||
property, so, as there are less than 16 classes they can be
|
||||
packed in 4 bits.
|
||||
*/
|
||||
|
||||
#define STSKIP 0 /* spaces and so on: skipped characters */
|
||||
#define STNL 1 /* newline character(s): update linenumber etc. */
|
||||
#define STGARB 2 /* garbage ascii character: not allowed */
|
||||
#define STSIMP 3 /* this character can occur as token */
|
||||
#define STCOMP 4 /* this one can start a compound token */
|
||||
#define STIDF 5 /* being the initial character of an identifier */
|
||||
#define STCHAR 6 /* the starter of a character constant */
|
||||
#define STSTR 7 /* the starter of a string */
|
||||
#define STNUM 8 /* the starter of a numeric constant */
|
||||
#define STEOI 9 /* End-Of-Information mark */
|
||||
|
||||
/* But occurring inside a token is not, so we need 1 bit for each
|
||||
class. This is implemented as a collection of tables to speed up
|
||||
the decision whether a character has a special meaning.
|
||||
*/
|
||||
#define in_idf(ch) ((unsigned)ch < 0177 && inidf[ch])
|
||||
#define is_oct(ch) ((unsigned)ch < 0177 && isoct[ch])
|
||||
#define is_dig(ch) ((unsigned)ch < 0177 && isdig[ch])
|
||||
#define is_hex(ch) ((unsigned)ch < 0177 && ishex[ch])
|
||||
|
||||
extern char tkclass[];
|
||||
extern char inidf[], isoct[], isdig[], ishex[];
|
1021
lang/m2/comp/code.c
1021
lang/m2/comp/code.c
File diff suppressed because it is too large
Load diff
|
@ -1,11 +0,0 @@
|
|||
/* C O N S T A N T S F O R E X P R E S S I O N H A N D L I N G */
|
||||
|
||||
extern long
|
||||
mach_long_sign; /* sign bit of the machine long */
|
||||
extern int
|
||||
mach_long_size; /* size of long on this machine == sizeof(long) */
|
||||
extern arith
|
||||
max_int, /* maximum integer on target machine */
|
||||
max_unsigned, /* maximum unsigned on target machine */
|
||||
max_longint, /* maximum longint on target machine */
|
||||
wrd_bits; /* Number of bits in a word */
|
|
@ -1,556 +0,0 @@
|
|||
/* C O N S T A N T E X P R E S S I O N H A N D L I N G */
|
||||
|
||||
#include "debug.h"
|
||||
#include "target_sizes.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "idf.h"
|
||||
#include "type.h"
|
||||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
#include "Lpars.h"
|
||||
#include "standards.h"
|
||||
#include "warning.h"
|
||||
|
||||
long mach_long_sign; /* sign bit of the machine long */
|
||||
int mach_long_size; /* size of long on this machine == sizeof(long) */
|
||||
long full_mask[MAXSIZE];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */
|
||||
arith max_int; /* maximum integer on target machine */
|
||||
arith max_unsigned; /* maximum unsigned on target machine */
|
||||
arith max_longint; /* maximum longint on target machine */
|
||||
arith wrd_bits; /* number of bits in a word */
|
||||
|
||||
static char ovflow[] = "overflow in constant expression";
|
||||
|
||||
cstunary(expp)
|
||||
register struct node *expp;
|
||||
{
|
||||
/* The unary operation in "expp" is performed on the constant
|
||||
expression below it, and the result restored in expp.
|
||||
*/
|
||||
register arith o1 = expp->nd_right->nd_INT;
|
||||
|
||||
switch(expp->nd_symb) {
|
||||
/* Should not get here
|
||||
case '+':
|
||||
break;
|
||||
*/
|
||||
|
||||
case '-':
|
||||
o1 = -o1;
|
||||
if (expp->nd_type->tp_fund == T_INTORCARD) {
|
||||
expp->nd_type = int_type;
|
||||
}
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
case '~':
|
||||
o1 = !o1;
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(cstunary)");
|
||||
}
|
||||
|
||||
expp->nd_class = Value;
|
||||
expp->nd_token = expp->nd_right->nd_token;
|
||||
expp->nd_INT = o1;
|
||||
CutSize(expp);
|
||||
FreeNode(expp->nd_right);
|
||||
expp->nd_right = 0;
|
||||
}
|
||||
|
||||
cstbin(expp)
|
||||
register struct node *expp;
|
||||
{
|
||||
/* The binary operation in "expp" is performed on the constant
|
||||
expressions below it, and the result restored in
|
||||
expp.
|
||||
*/
|
||||
register arith o1 = expp->nd_left->nd_INT;
|
||||
register arith o2 = expp->nd_right->nd_INT;
|
||||
register int uns = expp->nd_left->nd_type != int_type;
|
||||
|
||||
assert(expp->nd_class == Oper);
|
||||
assert(expp->nd_left->nd_class == Value);
|
||||
assert(expp->nd_right->nd_class == Value);
|
||||
|
||||
switch (expp->nd_symb) {
|
||||
case '*':
|
||||
o1 *= o2;
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
if (o2 == 0) {
|
||||
node_error(expp, "division by 0");
|
||||
return;
|
||||
}
|
||||
if (uns) {
|
||||
/* this is more of a problem than you might
|
||||
think on C compilers which do not have
|
||||
unsigned long.
|
||||
*/
|
||||
if (o2 & mach_long_sign) {/* o2 > max_long */
|
||||
o1 = ! (o1 >= 0 || o1 < o2);
|
||||
/* this is the unsigned test
|
||||
o1 < o2 for o2 > max_long
|
||||
*/
|
||||
}
|
||||
else { /* o2 <= max_long */
|
||||
long half, bit, hdiv, hrem, rem;
|
||||
|
||||
half = (o1 >> 1) & ~mach_long_sign;
|
||||
bit = o1 & 01;
|
||||
/* now o1 == 2 * half + bit
|
||||
and half <= max_long
|
||||
and bit <= max_long
|
||||
*/
|
||||
hdiv = half / o2;
|
||||
hrem = half % o2;
|
||||
rem = 2 * hrem + bit;
|
||||
o1 = 2 * hdiv + (rem < 0 || rem >= o2);
|
||||
/* that is the unsigned compare
|
||||
rem >= o2 for o2 <= max_long
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
o1 /= o2;
|
||||
break;
|
||||
|
||||
case MOD:
|
||||
if (o2 == 0) {
|
||||
node_error(expp, "modulo by 0");
|
||||
return;
|
||||
}
|
||||
if (uns) {
|
||||
if (o2 & mach_long_sign) {/* o2 > max_long */
|
||||
o1 = (o1 >= 0 || o1 < o2) ? o1 : o1 - o2;
|
||||
/* this is the unsigned test
|
||||
o1 < o2 for o2 > max_long
|
||||
*/
|
||||
}
|
||||
else { /* o2 <= max_long */
|
||||
long half, bit, hrem, rem;
|
||||
|
||||
half = (o1 >> 1) & ~mach_long_sign;
|
||||
bit = o1 & 01;
|
||||
/* now o1 == 2 * half + bit
|
||||
and half <= max_long
|
||||
and bit <= max_long
|
||||
*/
|
||||
hrem = half % o2;
|
||||
rem = 2 * hrem + bit;
|
||||
o1 = (rem < 0 || rem >= o2) ? rem - o2 : rem;
|
||||
}
|
||||
}
|
||||
else
|
||||
o1 %= o2;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
o1 += o2;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
o1 -= o2;
|
||||
if (expp->nd_type->tp_fund == T_INTORCARD) {
|
||||
if (o1 < 0) expp->nd_type = int_type;
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
{ arith tmp = o1;
|
||||
|
||||
o1 = o2;
|
||||
o2 = tmp;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case '>':
|
||||
if (uns) {
|
||||
o1 = (o1 & mach_long_sign ?
|
||||
(o2 & mach_long_sign ? o1 > o2 : 1) :
|
||||
(o2 & mach_long_sign ? 0 : o1 > o2)
|
||||
);
|
||||
}
|
||||
else
|
||||
o1 = (o1 > o2);
|
||||
break;
|
||||
|
||||
case LESSEQUAL:
|
||||
{ arith tmp = o1;
|
||||
|
||||
o1 = o2;
|
||||
o2 = tmp;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case GREATEREQUAL:
|
||||
if (uns) {
|
||||
o1 = (o1 & mach_long_sign ?
|
||||
(o2 & mach_long_sign ? o1 >= o2 : 1) :
|
||||
(o2 & mach_long_sign ? 0 : o1 >= o2)
|
||||
);
|
||||
}
|
||||
else
|
||||
o1 = (o1 >= o2);
|
||||
break;
|
||||
|
||||
case '=':
|
||||
o1 = (o1 == o2);
|
||||
break;
|
||||
|
||||
case '#':
|
||||
o1 = (o1 != o2);
|
||||
break;
|
||||
|
||||
case AND:
|
||||
case '&':
|
||||
o1 = (o1 && o2);
|
||||
break;
|
||||
|
||||
case OR:
|
||||
o1 = (o1 || o2);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(cstbin)");
|
||||
}
|
||||
|
||||
expp->nd_class = Value;
|
||||
expp->nd_token = expp->nd_right->nd_token;
|
||||
if (expp->nd_type == bool_type) expp->nd_symb = INTEGER;
|
||||
expp->nd_INT = o1;
|
||||
CutSize(expp);
|
||||
FreeNode(expp->nd_left);
|
||||
FreeNode(expp->nd_right);
|
||||
expp->nd_left = expp->nd_right = 0;
|
||||
}
|
||||
|
||||
cstset(expp)
|
||||
register struct node *expp;
|
||||
{
|
||||
register arith *set1, *set2;
|
||||
arith *resultset = 0;
|
||||
register int setsize, j;
|
||||
|
||||
assert(expp->nd_right->nd_class == Set);
|
||||
assert(expp->nd_symb == IN || expp->nd_left->nd_class == Set);
|
||||
set2 = expp->nd_right->nd_set;
|
||||
setsize = expp->nd_right->nd_type->tp_size / word_size;
|
||||
|
||||
if (expp->nd_symb == IN) {
|
||||
arith i;
|
||||
|
||||
assert(expp->nd_left->nd_class == Value);
|
||||
|
||||
i = expp->nd_left->nd_INT;
|
||||
expp->nd_class = Value;
|
||||
expp->nd_INT = (i >= 0 && set2 != 0 &&
|
||||
i < setsize * wrd_bits &&
|
||||
(set2[i / wrd_bits] & (1 << (i % wrd_bits))));
|
||||
if (set2) free((char *) set2);
|
||||
}
|
||||
else {
|
||||
set1 = expp->nd_left->nd_set;
|
||||
resultset = set1;
|
||||
expp->nd_left->nd_set = 0;
|
||||
switch(expp->nd_symb) {
|
||||
case '+':
|
||||
/* Set union
|
||||
*/
|
||||
if (!set1) {
|
||||
resultset = set2;
|
||||
expp->nd_right->nd_set = 0;
|
||||
break;
|
||||
}
|
||||
if (set2) for (j = 0; j < setsize; j++) {
|
||||
*set1++ |= *set2++;
|
||||
}
|
||||
break;
|
||||
|
||||
case '-':
|
||||
/* Set difference
|
||||
*/
|
||||
if (!set1 || !set2) {
|
||||
/* The set from which something is substracted
|
||||
is already empty, or the set that is
|
||||
substracted is empty. In either case, the
|
||||
result set is set1.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
for (j = 0; j < setsize; j++) {
|
||||
*set1++ &= ~*set2++;
|
||||
}
|
||||
break;
|
||||
|
||||
case '*':
|
||||
/* Set intersection
|
||||
*/
|
||||
if (!set1) {
|
||||
/* set1 is empty, and so is the result set
|
||||
*/
|
||||
break;
|
||||
}
|
||||
if (!set2) {
|
||||
/* set 2 is empty, so the result set must be
|
||||
empty too.
|
||||
*/
|
||||
resultset = set2;
|
||||
expp->nd_right->nd_set = 0;
|
||||
break;
|
||||
}
|
||||
for (j = 0; j < setsize; j++) {
|
||||
*set1++ &= *set2++;
|
||||
}
|
||||
break;
|
||||
|
||||
case '/':
|
||||
/* Symmetric set difference
|
||||
*/
|
||||
if (!set1) {
|
||||
resultset = set2;
|
||||
expp->nd_right->nd_set = 0;
|
||||
break;
|
||||
}
|
||||
if (set2) {
|
||||
for (j = 0; j < setsize; j++) {
|
||||
*set1++ ^= *set2++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GREATEREQUAL:
|
||||
case LESSEQUAL:
|
||||
case '=':
|
||||
case '#':
|
||||
/* Constant set comparisons
|
||||
*/
|
||||
expp->nd_left->nd_set = set1; /* may be disposed of */
|
||||
for (j = 0; j < setsize; j++) {
|
||||
switch(expp->nd_symb) {
|
||||
case GREATEREQUAL:
|
||||
if (!set2) {j = setsize; break; }
|
||||
if (!set1) break;
|
||||
if ((*set1 | *set2++) != *set1) break;
|
||||
set1++;
|
||||
continue;
|
||||
case LESSEQUAL:
|
||||
if (!set1) {j = setsize; break; }
|
||||
if (!set2) break;
|
||||
if ((*set2 | *set1++) != *set2) break;
|
||||
set2++;
|
||||
continue;
|
||||
case '=':
|
||||
case '#':
|
||||
if (!set1 && !set2) {
|
||||
j = setsize; break;
|
||||
}
|
||||
if (!set1 || !set2) break;
|
||||
if (*set1++ != *set2++) break;
|
||||
continue;
|
||||
}
|
||||
if (j < setsize) {
|
||||
expp->nd_INT = expp->nd_symb == '#';
|
||||
}
|
||||
else {
|
||||
expp->nd_INT = expp->nd_symb != '#';
|
||||
}
|
||||
break;
|
||||
}
|
||||
expp->nd_class = Value;
|
||||
expp->nd_symb = INTEGER;
|
||||
if (expp->nd_left->nd_set) {
|
||||
free((char *) expp->nd_left->nd_set);
|
||||
}
|
||||
if (expp->nd_right->nd_set) {
|
||||
free((char *) expp->nd_right->nd_set);
|
||||
}
|
||||
FreeNode(expp->nd_left);
|
||||
FreeNode(expp->nd_right);
|
||||
expp->nd_left = expp->nd_right = 0;
|
||||
return;
|
||||
default:
|
||||
crash("(cstset)");
|
||||
}
|
||||
if (expp->nd_right->nd_set) {
|
||||
free((char *) expp->nd_right->nd_set);
|
||||
}
|
||||
if (expp->nd_left->nd_set) {
|
||||
free((char *) expp->nd_left->nd_set);
|
||||
}
|
||||
expp->nd_class = Set;
|
||||
expp->nd_set = resultset;
|
||||
}
|
||||
FreeNode(expp->nd_left);
|
||||
FreeNode(expp->nd_right);
|
||||
expp->nd_left = expp->nd_right = 0;
|
||||
}
|
||||
|
||||
cstcall(expp, call)
|
||||
register struct node *expp;
|
||||
{
|
||||
/* a standard procedure call is found that can be evaluated
|
||||
compile time, so do so.
|
||||
*/
|
||||
register struct node *expr = 0;
|
||||
|
||||
assert(expp->nd_class == Call);
|
||||
|
||||
if (expp->nd_right) {
|
||||
expr = expp->nd_right->nd_left;
|
||||
expp->nd_right->nd_left = 0;
|
||||
FreeNode(expp->nd_right);
|
||||
}
|
||||
|
||||
expp->nd_class = Value;
|
||||
expp->nd_symb = INTEGER;
|
||||
switch(call) {
|
||||
case S_ABS:
|
||||
if (expr->nd_INT < 0) expp->nd_INT = - expr->nd_INT;
|
||||
else expp->nd_INT = expr->nd_INT;
|
||||
CutSize(expp);
|
||||
break;
|
||||
|
||||
case S_CAP:
|
||||
if (expr->nd_INT >= 'a' && expr->nd_INT <= 'z') {
|
||||
expp->nd_INT = expr->nd_INT + ('A' - 'a');
|
||||
}
|
||||
else expp->nd_INT = expr->nd_INT;
|
||||
CutSize(expp);
|
||||
break;
|
||||
|
||||
case S_CHR:
|
||||
expp->nd_INT = expr->nd_INT;
|
||||
CutSize(expp);
|
||||
break;
|
||||
|
||||
case S_MAX:
|
||||
if (expp->nd_type == int_type) {
|
||||
expp->nd_INT = max_int;
|
||||
}
|
||||
else if (expp->nd_type == longint_type) {
|
||||
expp->nd_INT = max_longint;
|
||||
}
|
||||
else if (expp->nd_type == card_type) {
|
||||
expp->nd_INT = max_unsigned;
|
||||
}
|
||||
else if (expp->nd_type->tp_fund == T_SUBRANGE) {
|
||||
expp->nd_INT = expp->nd_type->sub_ub;
|
||||
}
|
||||
else expp->nd_INT = expp->nd_type->enm_ncst - 1;
|
||||
break;
|
||||
|
||||
case S_MIN:
|
||||
if (expp->nd_type == int_type) {
|
||||
expp->nd_INT = (-max_int) - 1;
|
||||
}
|
||||
else if (expp->nd_type == longint_type) {
|
||||
expp->nd_INT = (-max_longint) - 1;
|
||||
}
|
||||
else if (expp->nd_type->tp_fund == T_SUBRANGE) {
|
||||
expp->nd_INT = expp->nd_type->sub_lb;
|
||||
}
|
||||
else expp->nd_INT = 0;
|
||||
break;
|
||||
|
||||
case S_ODD:
|
||||
expp->nd_INT = (expr->nd_INT & 1);
|
||||
break;
|
||||
|
||||
case S_ORD:
|
||||
expp->nd_INT = expr->nd_INT;
|
||||
CutSize(expp);
|
||||
break;
|
||||
|
||||
case S_SIZE:
|
||||
expp->nd_INT = expr->nd_type->tp_size;
|
||||
break;
|
||||
|
||||
case S_VAL:
|
||||
expp->nd_INT = expr->nd_INT;
|
||||
if ( /* Check overflow of subranges or enumerations */
|
||||
( expp->nd_type->tp_fund == T_SUBRANGE
|
||||
&&
|
||||
( expp->nd_INT < expp->nd_type->sub_lb
|
||||
|| expp->nd_INT > expp->nd_type->sub_ub
|
||||
)
|
||||
)
|
||||
||
|
||||
( expp->nd_type->tp_fund == T_ENUMERATION
|
||||
&&
|
||||
( expp->nd_INT < 0
|
||||
|| expp->nd_INT >= expp->nd_type->enm_ncst
|
||||
)
|
||||
)
|
||||
) node_warning(expp, W_ORDINARY, ovflow);
|
||||
else CutSize(expp);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(cstcall)");
|
||||
}
|
||||
FreeNode(expr);
|
||||
FreeNode(expp->nd_left);
|
||||
expp->nd_right = expp->nd_left = 0;
|
||||
}
|
||||
|
||||
CutSize(expr)
|
||||
register struct node *expr;
|
||||
{
|
||||
/* The constant value of the expression expr is made to
|
||||
conform to the size of the type of the expression.
|
||||
*/
|
||||
register arith o1 = expr->nd_INT;
|
||||
register struct type *tp = BaseType(expr->nd_type);
|
||||
int uns;
|
||||
int size = tp->tp_size;
|
||||
|
||||
assert(expr->nd_class == Value);
|
||||
uns = (tp->tp_fund & (T_CARDINAL|T_CHAR));
|
||||
if (uns) {
|
||||
if (o1 & ~full_mask[size]) {
|
||||
node_warning(expr, W_ORDINARY, ovflow);
|
||||
o1 &= full_mask[size];
|
||||
}
|
||||
}
|
||||
else {
|
||||
int nbits = (int) (mach_long_size - size) * 8;
|
||||
long remainder = o1 & ~full_mask[size];
|
||||
|
||||
if (remainder != 0 && remainder != ~full_mask[size]) {
|
||||
node_warning(expr, W_ORDINARY, ovflow);
|
||||
o1 <<= nbits;
|
||||
o1 >>= nbits;
|
||||
}
|
||||
}
|
||||
expr->nd_INT = o1;
|
||||
}
|
||||
|
||||
InitCst()
|
||||
{
|
||||
register int i = 0;
|
||||
register arith bt = (arith)0;
|
||||
|
||||
while (!(bt < 0)) {
|
||||
bt = (bt << 8) + 0377, i++;
|
||||
if (i == MAXSIZE)
|
||||
fatal("array full_mask too small for this machine");
|
||||
full_mask[i] = bt;
|
||||
}
|
||||
mach_long_size = i;
|
||||
mach_long_sign = 1 << (mach_long_size * 8 - 1);
|
||||
if (long_size > mach_long_size) {
|
||||
fatal("sizeof (long) insufficient on this machine");
|
||||
}
|
||||
|
||||
max_int = full_mask[int_size] & ~(1 << (int_size * 8 - 1));
|
||||
max_unsigned = full_mask[int_size];
|
||||
max_longint = full_mask[long_size] & ~(1 << (long_size * 8 - 1));
|
||||
wrd_bits = 8 * word_size;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
/* A debugging macro
|
||||
*/
|
||||
|
||||
#include "debugcst.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DO_DEBUG(x, y) ((x) && (y))
|
||||
#else
|
||||
#define DO_DEBUG(x, y)
|
||||
#endif
|
|
@ -1,546 +0,0 @@
|
|||
/* D E C L A R A T I O N S */
|
||||
|
||||
{
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <alloc.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "scope.h"
|
||||
#include "node.h"
|
||||
#include "misc.h"
|
||||
#include "main.h"
|
||||
#include "chk_expr.h"
|
||||
#include "warning.h"
|
||||
|
||||
int proclevel = 0; /* nesting level of procedures */
|
||||
int return_occurred; /* set if a return occurs in a block */
|
||||
}
|
||||
|
||||
ProcedureDeclaration
|
||||
{
|
||||
struct def *df;
|
||||
} :
|
||||
{ ++proclevel; }
|
||||
ProcedureHeading(&df, D_PROCEDURE)
|
||||
';' block(&(df->prc_body))
|
||||
IDENT
|
||||
{ EndProc(df, dot.TOK_IDF);
|
||||
--proclevel;
|
||||
}
|
||||
;
|
||||
|
||||
ProcedureHeading(struct def **pdf; int type;)
|
||||
{
|
||||
struct type *tp = 0;
|
||||
#define needs_static_link() (proclevel > 1)
|
||||
arith parmaddr = needs_static_link() ? pointer_size : 0;
|
||||
struct paramlist *pr = 0;
|
||||
} :
|
||||
PROCEDURE IDENT
|
||||
{ *pdf = DeclProc(type, dot.TOK_IDF); }
|
||||
FormalParameters(&pr, &parmaddr, &tp)?
|
||||
{ CheckWithDef(*pdf, proc_type(tp, pr, parmaddr));
|
||||
if (tp && IsConstructed(tp)) {
|
||||
warning(W_STRICT, "procedure \"%s\" has a constructed result type",
|
||||
(*pdf)->df_idf->id_text);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
block(struct node **pnd;) :
|
||||
[ %persistent
|
||||
declaration
|
||||
]*
|
||||
{ return_occurred = 0; *pnd = 0; }
|
||||
[ %persistent
|
||||
BEGIN
|
||||
StatementSequence(pnd)
|
||||
]?
|
||||
END
|
||||
;
|
||||
|
||||
declaration:
|
||||
CONST [ %persistent ConstantDeclaration ';' ]*
|
||||
|
|
||||
TYPE [ %persistent TypeDeclaration ';' ]*
|
||||
|
|
||||
VAR [ %persistent VariableDeclaration ';' ]*
|
||||
|
|
||||
ProcedureDeclaration ';'
|
||||
|
|
||||
ModuleDeclaration ';'
|
||||
;
|
||||
|
||||
FormalParameters(struct paramlist **ppr; arith *parmaddr; struct type **ptp;):
|
||||
'('
|
||||
[
|
||||
FPSection(ppr, parmaddr)
|
||||
[
|
||||
';' FPSection(ppr, parmaddr)
|
||||
]*
|
||||
]?
|
||||
')'
|
||||
[ ':' qualtype(ptp)
|
||||
]?
|
||||
;
|
||||
|
||||
FPSection(struct paramlist **ppr; arith *parmaddr;)
|
||||
{
|
||||
struct node *FPList;
|
||||
struct type *tp;
|
||||
int VARp;
|
||||
} :
|
||||
var(&VARp) IdentList(&FPList) ':' FormalType(&tp)
|
||||
{ EnterParamList(ppr, FPList, tp, VARp, parmaddr); }
|
||||
;
|
||||
|
||||
FormalType(struct type **ptp;)
|
||||
{
|
||||
extern arith ArrayElSize();
|
||||
} :
|
||||
ARRAY OF qualtype(ptp)
|
||||
{ register struct type *tp = construct_type(T_ARRAY, NULLTYPE);
|
||||
|
||||
tp->arr_elem = *ptp;
|
||||
*ptp = tp;
|
||||
tp->arr_elsize = ArrayElSize(tp->arr_elem);
|
||||
tp->tp_align = tp->arr_elem->tp_align;
|
||||
}
|
||||
|
|
||||
qualtype(ptp)
|
||||
;
|
||||
|
||||
TypeDeclaration
|
||||
{
|
||||
struct def *df;
|
||||
struct type *tp;
|
||||
struct node *nd;
|
||||
}:
|
||||
IDENT { df = define(dot.TOK_IDF, CurrentScope, D_TYPE);
|
||||
nd = MkLeaf(Name, &dot);
|
||||
}
|
||||
'=' type(&tp)
|
||||
{ DeclareType(nd, df, tp);
|
||||
free_node(nd);
|
||||
}
|
||||
;
|
||||
|
||||
type(struct type **ptp;):
|
||||
%default SimpleType(ptp)
|
||||
|
|
||||
ArrayType(ptp)
|
||||
|
|
||||
RecordType(ptp)
|
||||
|
|
||||
SetType(ptp)
|
||||
|
|
||||
PointerType(ptp)
|
||||
|
|
||||
ProcedureType(ptp)
|
||||
;
|
||||
|
||||
SimpleType(struct type **ptp;)
|
||||
{
|
||||
struct type *tp;
|
||||
} :
|
||||
qualtype(ptp)
|
||||
[
|
||||
/* nothing */
|
||||
|
|
||||
SubrangeType(&tp)
|
||||
/* The subrange type is given a base type by the
|
||||
qualident (this is new modula-2).
|
||||
*/
|
||||
{ chk_basesubrange(tp, *ptp); }
|
||||
]
|
||||
|
|
||||
enumeration(ptp)
|
||||
|
|
||||
SubrangeType(ptp)
|
||||
;
|
||||
|
||||
enumeration(struct type **ptp;)
|
||||
{
|
||||
struct node *EnumList;
|
||||
} :
|
||||
'(' IdentList(&EnumList) ')'
|
||||
{ register struct type *tp =
|
||||
standard_type(T_ENUMERATION, int_align, int_size);
|
||||
|
||||
*ptp = tp;
|
||||
EnterEnumList(EnumList, tp);
|
||||
if (ufit(tp->enm_ncst-1, 1)) {
|
||||
tp->tp_size = 1;
|
||||
tp->tp_align = 1;
|
||||
}
|
||||
else if (ufit(tp->enm_ncst-1, short_size)) {
|
||||
tp->tp_size = short_size;
|
||||
tp->tp_align = short_align;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
IdentList(struct node **p;)
|
||||
{
|
||||
register struct node *q;
|
||||
} :
|
||||
IDENT { *p = q = MkLeaf(Value, &dot); }
|
||||
[ %persistent
|
||||
',' IDENT
|
||||
{ q->next = MkLeaf(Value, &dot);
|
||||
q = q->next;
|
||||
}
|
||||
]*
|
||||
{ q->next = 0; }
|
||||
;
|
||||
|
||||
SubrangeType(struct type **ptp;)
|
||||
{
|
||||
struct node *nd1, *nd2;
|
||||
}:
|
||||
/*
|
||||
This is not exactly the rule in the new report, but see
|
||||
the rule for "SimpleType".
|
||||
*/
|
||||
'[' ConstExpression(&nd1)
|
||||
UPTO ConstExpression(&nd2)
|
||||
']'
|
||||
{ *ptp = subr_type(nd1, nd2);
|
||||
free_node(nd1);
|
||||
free_node(nd2);
|
||||
}
|
||||
;
|
||||
|
||||
ArrayType(struct type **ptp;)
|
||||
{
|
||||
struct type *tp;
|
||||
register struct type *tp2;
|
||||
} :
|
||||
ARRAY SimpleType(&tp)
|
||||
{ *ptp = tp2 = construct_type(T_ARRAY, tp); }
|
||||
[
|
||||
',' SimpleType(&tp)
|
||||
{ tp2->arr_elem = construct_type(T_ARRAY, tp);
|
||||
tp2 = tp2->arr_elem;
|
||||
}
|
||||
]* OF type(&tp)
|
||||
{ tp2->arr_elem = tp;
|
||||
ArraySizes(*ptp);
|
||||
}
|
||||
;
|
||||
|
||||
RecordType(struct type **ptp;)
|
||||
{
|
||||
register struct scope *scope;
|
||||
arith size = 0;
|
||||
int xalign = struct_align;
|
||||
}
|
||||
:
|
||||
RECORD
|
||||
{ open_scope(OPENSCOPE); /* scope for fields of record */
|
||||
scope = CurrentScope;
|
||||
close_scope(0);
|
||||
}
|
||||
FieldListSequence(scope, &size, &xalign)
|
||||
{ if (size == 0) {
|
||||
warning(W_ORDINARY, "empty record declaration");
|
||||
size = 1;
|
||||
}
|
||||
*ptp = standard_type(T_RECORD, xalign, size);
|
||||
(*ptp)->rec_scope = scope;
|
||||
}
|
||||
END
|
||||
;
|
||||
|
||||
FieldListSequence(struct scope *scope; arith *cnt; int *palign;):
|
||||
FieldList(scope, cnt, palign)
|
||||
[
|
||||
';' FieldList(scope, cnt, palign)
|
||||
]*
|
||||
;
|
||||
|
||||
FieldList(struct scope *scope; arith *cnt; int *palign;)
|
||||
{
|
||||
struct node *FldList;
|
||||
register struct idf *id = 0;
|
||||
struct type *tp;
|
||||
struct node *nd1;
|
||||
register struct node *nd;
|
||||
arith tcnt, max;
|
||||
} :
|
||||
[
|
||||
IdentList(&FldList) ':' type(&tp)
|
||||
{ *palign = lcm(*palign, tp->tp_align);
|
||||
EnterFieldList(FldList, tp, scope, cnt);
|
||||
}
|
||||
|
|
||||
CASE
|
||||
/* Also accept old fashioned Modula-2 syntax, but give a warning.
|
||||
Sorry for the complicated code.
|
||||
*/
|
||||
[ qualident(&nd1)
|
||||
{ nd = nd1; }
|
||||
[ ':' qualtype(&tp)
|
||||
/* This is correct, in both kinds of Modula-2, if
|
||||
the first qualident is a single identifier.
|
||||
*/
|
||||
{ if (nd->nd_class != Name) {
|
||||
error("illegal variant tag");
|
||||
}
|
||||
else id = nd->nd_IDF;
|
||||
FreeNode(nd);
|
||||
}
|
||||
| /* Old fashioned! the first qualident now represents
|
||||
the type
|
||||
*/
|
||||
{ warning(W_OLDFASHIONED, "old fashioned Modula-2 syntax; ':' missing");
|
||||
if (ChkDesignator(nd) &&
|
||||
(nd->nd_class != Def ||
|
||||
!(nd->nd_def->df_kind&(D_ERROR|D_ISTYPE)) ||
|
||||
!nd->nd_def->df_type)) {
|
||||
node_error(nd, "type expected");
|
||||
tp = error_type;
|
||||
}
|
||||
else tp = nd->nd_def->df_type;
|
||||
FreeNode(nd);
|
||||
}
|
||||
]
|
||||
| ':' qualtype(&tp)
|
||||
/* Aha, third edition. Well done! */
|
||||
]
|
||||
{ if (id) {
|
||||
register struct def *df = define(id,
|
||||
scope,
|
||||
D_FIELD);
|
||||
if (!(tp->tp_fund & T_DISCRETE)) {
|
||||
error("illegal type in variant");
|
||||
}
|
||||
df->df_type = tp;
|
||||
df->fld_off = align(*cnt, tp->tp_align);
|
||||
*cnt = df->fld_off + tp->tp_size;
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
}
|
||||
tcnt = *cnt;
|
||||
}
|
||||
OF variant(scope, &tcnt, tp, palign)
|
||||
{ max = tcnt; tcnt = *cnt; }
|
||||
[
|
||||
'|' variant(scope, &tcnt, tp, palign)
|
||||
{ if (tcnt > max) max = tcnt; tcnt = *cnt; }
|
||||
]*
|
||||
[ ELSE FieldListSequence(scope, &tcnt, palign)
|
||||
{ if (tcnt > max) max = tcnt; }
|
||||
]?
|
||||
END
|
||||
{ *cnt = max; }
|
||||
]?
|
||||
;
|
||||
|
||||
variant(struct scope *scope; arith *cnt; struct type *tp; int *palign;)
|
||||
{
|
||||
struct node *nd;
|
||||
} :
|
||||
[
|
||||
CaseLabelList(&tp, &nd)
|
||||
{ /* Ignore the cases for the time being.
|
||||
Maybe a checking version will be supplied
|
||||
later ??? (Improbable)
|
||||
*/
|
||||
FreeNode(nd);
|
||||
}
|
||||
':' FieldListSequence(scope, cnt, palign)
|
||||
]?
|
||||
/* Changed rule in new modula-2 */
|
||||
;
|
||||
|
||||
CaseLabelList(struct type **ptp; struct node **pnd;):
|
||||
CaseLabels(ptp, pnd)
|
||||
[
|
||||
{ *pnd = MkNode(Link, *pnd, NULLNODE, &dot); }
|
||||
',' CaseLabels(ptp, &((*pnd)->nd_right))
|
||||
{ pnd = &((*pnd)->nd_right); }
|
||||
]*
|
||||
;
|
||||
|
||||
CaseLabels(struct type **ptp; register struct node **pnd;)
|
||||
{
|
||||
register struct node *nd1;
|
||||
}:
|
||||
ConstExpression(pnd)
|
||||
{ nd1 = *pnd; }
|
||||
[
|
||||
UPTO { *pnd = MkNode(Link,nd1,NULLNODE,&dot); }
|
||||
ConstExpression(&(*pnd)->nd_right)
|
||||
{ if (!TstCompat(nd1->nd_type,
|
||||
(*pnd)->nd_right->nd_type)) {
|
||||
node_error((*pnd)->nd_right,
|
||||
"type incompatibility in case label");
|
||||
nd1->nd_type = error_type;
|
||||
}
|
||||
}
|
||||
]?
|
||||
{ if (*ptp != 0 && !TstCompat(*ptp, nd1->nd_type)) {
|
||||
node_error(nd1,
|
||||
"type incompatibility in case label");
|
||||
}
|
||||
*ptp = nd1->nd_type;
|
||||
}
|
||||
;
|
||||
|
||||
SetType(struct type **ptp;) :
|
||||
SET OF SimpleType(ptp)
|
||||
{ *ptp = set_type(*ptp); }
|
||||
;
|
||||
|
||||
/* In a pointer type definition, the type pointed at does not
|
||||
have to be declared yet, so be careful about identifying
|
||||
type-identifiers
|
||||
*/
|
||||
PointerType(struct type **ptp;)
|
||||
{
|
||||
register struct node *nd = 0;
|
||||
} :
|
||||
POINTER TO
|
||||
{ *ptp = construct_type(T_POINTER, NULLTYPE); }
|
||||
[ %if ( lookup(dot.TOK_IDF, CurrentScope, 1)
|
||||
/* Either a Module or a Type, but in both cases defined
|
||||
in this scope, so this is the correct identification
|
||||
*/
|
||||
||
|
||||
( nd = new_node(),
|
||||
nd->nd_token = dot,
|
||||
lookfor(nd, CurrVis, 0)->df_kind == D_MODULE
|
||||
)
|
||||
/* A Modulename in one of the enclosing scopes.
|
||||
It is not clear from the language definition that
|
||||
it is correct to handle these like this, but
|
||||
existing compilers do it like this, and the
|
||||
alternative is difficult with a lookahead of only
|
||||
one token.
|
||||
???
|
||||
*/
|
||||
)
|
||||
type(&((*ptp)->next))
|
||||
{ if (nd) free_node(nd); }
|
||||
|
|
||||
IDENT { if (nd) {
|
||||
/* nd could be a null pointer, if we had a
|
||||
syntax error exactly at this alternation.
|
||||
MORAL: Be careful with %if resolvers with
|
||||
side effects!
|
||||
*/
|
||||
Forward(nd, (*ptp));
|
||||
}
|
||||
}
|
||||
]
|
||||
;
|
||||
|
||||
qualtype(struct type **ptp;)
|
||||
{
|
||||
register struct node *nd;
|
||||
struct node *nd1; /* because &nd is illegal */
|
||||
} :
|
||||
qualident(&nd1)
|
||||
{ nd = nd1;
|
||||
*ptp = error_type;
|
||||
if (ChkDesignator(nd)) {
|
||||
if (nd->nd_class != Def) {
|
||||
node_error(nd, "type expected");
|
||||
}
|
||||
else {
|
||||
register struct def *df = nd->nd_def;
|
||||
|
||||
if (df->df_kind&(D_ISTYPE|D_FORWARD|D_ERROR)) {
|
||||
if (! df->df_type) {
|
||||
node_error(nd,"type \"%s\" not (yet) declared", df->df_idf->id_text);
|
||||
}
|
||||
else *ptp = df->df_type;
|
||||
}
|
||||
else {
|
||||
node_error(nd,"identifier \"%s\" is not a type", df->df_idf->id_text);
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeNode(nd);
|
||||
}
|
||||
;
|
||||
|
||||
ProcedureType(struct type **ptp;)
|
||||
{
|
||||
struct paramlist *pr = 0;
|
||||
arith parmaddr = 0;
|
||||
}
|
||||
:
|
||||
{ *ptp = 0; }
|
||||
PROCEDURE
|
||||
[
|
||||
FormalTypeList(&pr, &parmaddr, ptp)
|
||||
]?
|
||||
{ *ptp = proc_type(*ptp, pr, parmaddr); }
|
||||
;
|
||||
|
||||
FormalTypeList(struct paramlist **ppr; arith *parmaddr; struct type **ptp;)
|
||||
{
|
||||
struct type *tp;
|
||||
int VARp;
|
||||
} :
|
||||
'('
|
||||
[
|
||||
var(&VARp) FormalType(&tp)
|
||||
{ EnterParamList(ppr,NULLNODE,tp,VARp,parmaddr); }
|
||||
[
|
||||
',' var(&VARp) FormalType(&tp)
|
||||
{ EnterParamList(ppr,NULLNODE,tp,VARp,parmaddr); }
|
||||
]*
|
||||
]?
|
||||
')'
|
||||
[ ':' qualtype(ptp)
|
||||
]?
|
||||
;
|
||||
|
||||
var(int *VARp;):
|
||||
VAR { *VARp = D_VARPAR; }
|
||||
|
|
||||
/* empty */ { *VARp = D_VALPAR; }
|
||||
;
|
||||
|
||||
ConstantDeclaration
|
||||
{
|
||||
struct idf *id;
|
||||
struct node *nd;
|
||||
}:
|
||||
IDENT { id = dot.TOK_IDF; }
|
||||
'=' ConstExpression(&nd)
|
||||
{ define(id,CurrentScope,D_CONST)->con_const = nd; }
|
||||
;
|
||||
|
||||
VariableDeclaration
|
||||
{
|
||||
struct node *VarList;
|
||||
register struct node *nd;
|
||||
struct type *tp;
|
||||
} :
|
||||
IdentAddr(&VarList)
|
||||
{ nd = VarList; }
|
||||
[ %persistent
|
||||
',' IdentAddr(&(nd->nd_right))
|
||||
{ nd = nd->nd_right; }
|
||||
]*
|
||||
':' type(&tp)
|
||||
{ EnterVarList(VarList, tp, proclevel > 0); }
|
||||
;
|
||||
|
||||
IdentAddr(struct node **pnd;) :
|
||||
IDENT { *pnd = MkLeaf(Name, &dot); }
|
||||
[ '['
|
||||
ConstExpression(&((*pnd)->nd_left))
|
||||
']'
|
||||
]?
|
||||
;
|
|
@ -1,135 +0,0 @@
|
|||
/* I D E N T I F I E R D E S C R I P T O R S T R U C T U R E */
|
||||
|
||||
struct module {
|
||||
struct node *mo_priority;/* priority of a module */
|
||||
struct scopelist *mo_vis;/* scope of this module */
|
||||
struct node *mo_body; /* body of this module */
|
||||
#define mod_priority df_value.df_module.mo_priority
|
||||
#define mod_vis df_value.df_module.mo_vis
|
||||
#define mod_body df_value.df_module.mo_body
|
||||
};
|
||||
|
||||
struct variable {
|
||||
arith va_off; /* address or offset of variable */
|
||||
char *va_name; /* name of variable if given */
|
||||
char va_addrgiven; /* an address was given in the program */
|
||||
#define var_off df_value.df_variable.va_off
|
||||
#define var_name df_value.df_variable.va_name
|
||||
#define var_addrgiven df_value.df_variable.va_addrgiven
|
||||
};
|
||||
|
||||
struct constant {
|
||||
struct node *co_const; /* result of a constant expression */
|
||||
#define con_const df_value.df_constant.co_const
|
||||
};
|
||||
|
||||
struct enumval {
|
||||
unsigned int en_val; /* value of this enumeration literal */
|
||||
struct def *en_next; /* next enumeration literal */
|
||||
#define enm_val df_value.df_enum.en_val
|
||||
#define enm_next df_value.df_enum.en_next
|
||||
};
|
||||
|
||||
struct field {
|
||||
arith fd_off;
|
||||
struct variant {
|
||||
struct caselabellist *v_cases;
|
||||
label v_casedescr;
|
||||
struct def *v_varianttag;
|
||||
} *fd_variant;
|
||||
#define fld_off df_value.df_field.fd_off
|
||||
#define fld_variant df_value.df_field.fd_variant
|
||||
};
|
||||
|
||||
struct dfproc {
|
||||
struct scopelist *pr_vis; /* scope of procedure */
|
||||
struct node *pr_body; /* body of this procedure */
|
||||
#define prc_vis df_value.df_proc.pr_vis
|
||||
#define prc_body df_value.df_proc.pr_body
|
||||
#define NameOfProc(xdf) ((xdf)->prc_vis->sc_scope->sc_name)
|
||||
};
|
||||
|
||||
struct import {
|
||||
struct def *im_def; /* imported definition */
|
||||
#define imp_def df_value.df_import.im_def
|
||||
};
|
||||
|
||||
struct dforward {
|
||||
struct scopelist *fo_vis;
|
||||
struct node *fo_node;
|
||||
char *fo_name;
|
||||
#define for_node df_value.df_forward.fo_node
|
||||
#define for_vis df_value.df_forward.fo_vis
|
||||
#define for_name df_value.df_forward.fo_name
|
||||
};
|
||||
|
||||
struct forwtype {
|
||||
struct node *f_node;
|
||||
struct type *f_type;
|
||||
#define df_forw_type df_value.df_fortype.f_type
|
||||
#define df_forw_node df_value.df_fortype.f_node
|
||||
};
|
||||
|
||||
struct def { /* list of definitions for a name */
|
||||
struct def *next; /* next definition in definitions chain */
|
||||
struct def *df_nextinscope;
|
||||
/* link all definitions in a scope */
|
||||
struct idf *df_idf; /* link back to the name */
|
||||
struct scope *df_scope; /* scope in which this definition resides */
|
||||
unsigned short df_kind; /* the kind of this definition: */
|
||||
#define D_MODULE 0x0001 /* a module */
|
||||
#define D_PROCEDURE 0x0002 /* procedure of function */
|
||||
#define D_VARIABLE 0x0004 /* a variable */
|
||||
#define D_FIELD 0x0008 /* a field in a record */
|
||||
#define D_TYPE 0x0010 /* a type */
|
||||
#define D_ENUM 0x0020 /* an enumeration literal */
|
||||
#define D_CONST 0x0040 /* a constant */
|
||||
#define D_IMPORT 0x0080 /* an imported definition */
|
||||
#define D_PROCHEAD 0x0100 /* a procedure heading in a definition module */
|
||||
#define D_HIDDEN 0x0200 /* a hidden type */
|
||||
#define D_FORWARD 0x0400 /* not yet defined */
|
||||
#define D_FORWMODULE 0x0800 /* module must be declared later */
|
||||
#define D_FORWTYPE 0x1000 /* forward type */
|
||||
#define D_FTYPE 0x2000 /* resolved forward type */
|
||||
#define D_ERROR 0x4000 /* a compiler generated definition for an
|
||||
undefined variable
|
||||
*/
|
||||
#define D_VALUE (D_PROCEDURE|D_VARIABLE|D_FIELD|D_ENUM|D_CONST|D_PROCHEAD)
|
||||
#define D_ISTYPE (D_HIDDEN|D_TYPE|D_FTYPE)
|
||||
#define is_type(dfx) ((dfx)->df_kind & D_ISTYPE)
|
||||
unsigned short df_flags;
|
||||
#define D_NOREG 0x01 /* set if it may not reside in a register */
|
||||
#define D_USED 0x02 /* set if used (future use ???) */
|
||||
#define D_DEFINED 0x04 /* set if it is assigned a value (future use ???) */
|
||||
#define D_VARPAR 0x08 /* set if it is a VAR parameter */
|
||||
#define D_VALPAR 0x10 /* set if it is a value parameter */
|
||||
#define D_EXPORTED 0x20 /* set if exported */
|
||||
#define D_QEXPORTED 0x40 /* set if qualified exported */
|
||||
#define D_BUSY 0x80 /* set if busy reading this definition module */
|
||||
struct type *df_type;
|
||||
union {
|
||||
struct module df_module;
|
||||
struct variable df_variable;
|
||||
struct constant df_constant;
|
||||
struct enumval df_enum;
|
||||
struct field df_field;
|
||||
struct import df_import;
|
||||
struct dfproc df_proc;
|
||||
struct dforward df_forward;
|
||||
struct forwtype df_fortype;
|
||||
int df_stdname; /* define for standard name */
|
||||
} df_value;
|
||||
};
|
||||
|
||||
/* ALLOCDEF "def" 50 */
|
||||
|
||||
extern struct def
|
||||
*define(),
|
||||
*DefineLocalModule(),
|
||||
*MkDef(),
|
||||
*DeclProc();
|
||||
|
||||
extern struct def
|
||||
*lookup(),
|
||||
*lookfor();
|
||||
#define NULLDEF ((struct def *) 0)
|
|
@ -1,364 +0,0 @@
|
|||
/* D E F I N I T I O N M E C H A N I S M */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "idf.h"
|
||||
#include "scope.h"
|
||||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
#include "Lpars.h"
|
||||
|
||||
extern int (*c_inp)();
|
||||
|
||||
STATIC
|
||||
DefInFront(df)
|
||||
register struct def *df;
|
||||
{
|
||||
/* Put definition "df" in front of the list of definitions
|
||||
in its scope.
|
||||
This is neccessary because in some cases the order in this
|
||||
list is important.
|
||||
*/
|
||||
register struct def *df1 = df->df_scope->sc_def;
|
||||
|
||||
if (df1 != df) {
|
||||
/* Definition "df" is not in front of the list
|
||||
*/
|
||||
while (df1) {
|
||||
/* Find definition "df"
|
||||
*/
|
||||
if (df1->df_nextinscope == df) {
|
||||
/* It already was in the list. Remove it
|
||||
*/
|
||||
df1->df_nextinscope = df->df_nextinscope;
|
||||
break;
|
||||
}
|
||||
df1 = df1->df_nextinscope;
|
||||
}
|
||||
|
||||
/* Now put it in front
|
||||
*/
|
||||
df->df_nextinscope = df->df_scope->sc_def;
|
||||
df->df_scope->sc_def = df;
|
||||
}
|
||||
}
|
||||
|
||||
struct def *
|
||||
MkDef(id, scope, kind)
|
||||
register struct idf *id;
|
||||
register struct scope *scope;
|
||||
{
|
||||
/* Create a new definition structure in scope "scope", with
|
||||
id "id" and kind "kind".
|
||||
*/
|
||||
register struct def *df;
|
||||
|
||||
df = new_def();
|
||||
df->df_idf = id;
|
||||
df->df_scope = scope;
|
||||
df->df_kind = kind;
|
||||
df->next = id->id_def;
|
||||
id->id_def = df;
|
||||
|
||||
/* enter the definition in the list of definitions in this scope
|
||||
*/
|
||||
df->df_nextinscope = scope->sc_def;
|
||||
scope->sc_def = df;
|
||||
return df;
|
||||
}
|
||||
|
||||
struct def *
|
||||
define(id, scope, kind)
|
||||
register struct idf *id;
|
||||
register struct scope *scope;
|
||||
int kind;
|
||||
{
|
||||
/* Declare an identifier in a scope, but first check if it
|
||||
already has been defined.
|
||||
If so, then check for the cases in which this is legal,
|
||||
and otherwise give an error message.
|
||||
*/
|
||||
register struct def *df;
|
||||
|
||||
df = lookup(id, scope, 1);
|
||||
if ( /* Already in this scope */
|
||||
df
|
||||
|| /* A closed scope, and id defined in the pervasive scope */
|
||||
(
|
||||
scopeclosed(scope)
|
||||
&&
|
||||
(df = lookup(id, PervasiveScope, 1)))
|
||||
) {
|
||||
switch(df->df_kind) {
|
||||
case D_HIDDEN:
|
||||
/* An opaque type. We may now have found the
|
||||
definition of this type.
|
||||
*/
|
||||
if (kind == D_TYPE && !DefinitionModule) {
|
||||
df->df_kind = D_TYPE;
|
||||
return df;
|
||||
}
|
||||
break;
|
||||
|
||||
case D_FORWMODULE:
|
||||
/* A forward reference to a module. We may have found
|
||||
another one, or we may have found the definition
|
||||
for this module.
|
||||
*/
|
||||
if (kind == D_FORWMODULE) {
|
||||
return df;
|
||||
}
|
||||
|
||||
if (kind == D_MODULE) {
|
||||
FreeNode(df->for_node);
|
||||
df->mod_vis = df->for_vis;
|
||||
df->df_kind = kind;
|
||||
DefInFront(df);
|
||||
return df;
|
||||
}
|
||||
break;
|
||||
|
||||
case D_TYPE:
|
||||
if (kind == D_FORWTYPE) return df;
|
||||
break;
|
||||
case D_FORWTYPE:
|
||||
if (kind == D_FORWTYPE) return df;
|
||||
if (kind == D_TYPE) {
|
||||
df->df_kind = D_FTYPE;
|
||||
FreeNode(df->df_forw_node);
|
||||
}
|
||||
else {
|
||||
error("identifier \"%s\" must be a type",
|
||||
id->id_text);
|
||||
}
|
||||
return df;
|
||||
|
||||
case D_FORWARD:
|
||||
/* A forward reference, for which we may now have
|
||||
found a definition.
|
||||
*/
|
||||
if (kind != D_FORWARD) {
|
||||
FreeNode(df->for_node);
|
||||
}
|
||||
|
||||
/* Fall through */
|
||||
|
||||
case D_ERROR:
|
||||
/* A definition generated by the compiler, because
|
||||
it found an error. Maybe, the user gives a
|
||||
definition after all.
|
||||
*/
|
||||
df->df_kind = kind;
|
||||
return df;
|
||||
}
|
||||
|
||||
if (kind != D_ERROR) {
|
||||
/* Avoid spurious error messages
|
||||
*/
|
||||
error("identifier \"%s\" already declared",
|
||||
id->id_text);
|
||||
}
|
||||
|
||||
return df;
|
||||
}
|
||||
|
||||
return MkDef(id, scope, kind);
|
||||
}
|
||||
|
||||
RemoveImports(pdf)
|
||||
register struct def **pdf;
|
||||
{
|
||||
/* Remove all imports from a definition module. This is
|
||||
neccesary because the implementation module might import
|
||||
them again.
|
||||
*/
|
||||
register struct def *df = *pdf;
|
||||
|
||||
while (df) {
|
||||
if (df->df_kind == D_IMPORT) {
|
||||
RemoveFromIdList(df);
|
||||
*pdf = df->df_nextinscope;
|
||||
free_def(df);
|
||||
}
|
||||
else {
|
||||
pdf = &(df->df_nextinscope);
|
||||
}
|
||||
df = *pdf;
|
||||
}
|
||||
}
|
||||
|
||||
RemoveFromIdList(df)
|
||||
register struct def *df;
|
||||
{
|
||||
/* Remove definition "df" from the definition list
|
||||
*/
|
||||
register struct idf *id = df->df_idf;
|
||||
register struct def *df1;
|
||||
|
||||
if ((df1 = id->id_def) == df) id->id_def = df->next;
|
||||
else {
|
||||
while (df1->next != df) {
|
||||
assert(df1->next != 0);
|
||||
df1 = df1->next;
|
||||
}
|
||||
df1->next = df->next;
|
||||
}
|
||||
}
|
||||
|
||||
struct def *
|
||||
DeclProc(type, id)
|
||||
register struct idf *id;
|
||||
{
|
||||
/* A procedure is declared, either in a definition or a program
|
||||
module. Create a def structure for it (if neccessary).
|
||||
Also create a name for it.
|
||||
*/
|
||||
register struct def *df;
|
||||
register struct scope *scope;
|
||||
extern char *sprint();
|
||||
static int nmcount;
|
||||
char buf[256];
|
||||
|
||||
assert(type & (D_PROCEDURE | D_PROCHEAD));
|
||||
|
||||
if (type == D_PROCHEAD) {
|
||||
/* In a definition module
|
||||
*/
|
||||
df = define(id, CurrentScope, type);
|
||||
df->for_node = MkLeaf(Name, &dot);
|
||||
sprint(buf,"%s_%s",CurrentScope->sc_name,id->id_text);
|
||||
df->for_name = Salloc(buf, (unsigned) (strlen(buf)+1));
|
||||
if (CurrVis == Defined->mod_vis) {
|
||||
/* The current module will define this routine.
|
||||
make sure the name is exported.
|
||||
*/
|
||||
C_exp(df->for_name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *name;
|
||||
|
||||
df = lookup(id, CurrentScope, 1);
|
||||
if (df && df->df_kind == D_PROCHEAD) {
|
||||
/* C_exp already generated when we saw the definition
|
||||
in the definition module
|
||||
*/
|
||||
df->df_kind = D_PROCEDURE;
|
||||
name = df->for_name;
|
||||
DefInFront(df);
|
||||
}
|
||||
else {
|
||||
df = define(id, CurrentScope, type);
|
||||
sprint(buf,"_%d_%s",++nmcount,id->id_text);
|
||||
name = Salloc(buf, (unsigned)(strlen(buf)+1));
|
||||
(*c_inp)(buf);
|
||||
}
|
||||
open_scope(OPENSCOPE);
|
||||
scope = CurrentScope;
|
||||
scope->sc_name = name;
|
||||
scope->sc_definedby = df;
|
||||
df->prc_vis = CurrVis;
|
||||
}
|
||||
|
||||
return df;
|
||||
}
|
||||
|
||||
EndProc(df, id)
|
||||
register struct def *df;
|
||||
struct idf *id;
|
||||
{
|
||||
/* The end of a procedure declaration.
|
||||
Check that the closing identifier matches the name of the
|
||||
procedure, close the scope, and check that a function
|
||||
procedure has at least one RETURN statement.
|
||||
*/
|
||||
extern int return_occurred;
|
||||
|
||||
match_id(id, df->df_idf);
|
||||
close_scope(SC_CHKFORW|SC_REVERSE);
|
||||
if (! return_occurred && ResultType(df->df_type)) {
|
||||
error("function procedure %s does not return a value",
|
||||
df->df_idf->id_text);
|
||||
}
|
||||
}
|
||||
|
||||
struct def *
|
||||
DefineLocalModule(id)
|
||||
struct idf *id;
|
||||
{
|
||||
/* Create a definition for a local module. Also give it
|
||||
a name to be used for code generation.
|
||||
*/
|
||||
register struct def *df = define(id, CurrentScope, D_MODULE);
|
||||
register struct scope *sc;
|
||||
static int modulecount = 0;
|
||||
char buf[256];
|
||||
extern char *sprint();
|
||||
extern int proclevel;
|
||||
|
||||
sprint(buf, "_%d%s", ++modulecount, id->id_text);
|
||||
|
||||
if (!df->mod_vis) {
|
||||
/* We never saw the name of this module before. Create a
|
||||
scope for it.
|
||||
*/
|
||||
open_scope(CLOSEDSCOPE);
|
||||
df->mod_vis = CurrVis;
|
||||
}
|
||||
|
||||
CurrVis = df->mod_vis;
|
||||
|
||||
sc = CurrentScope;
|
||||
sc->sc_level = proclevel;
|
||||
sc->sc_definedby = df;
|
||||
sc->sc_name = Salloc(buf, (unsigned) (strlen(buf) + 1));
|
||||
|
||||
/* Create a type for it
|
||||
*/
|
||||
df->df_type = standard_type(T_RECORD, 1, (arith) 0);
|
||||
df->df_type->rec_scope = sc;
|
||||
|
||||
/* Generate code that indicates that the initialization procedure
|
||||
for this module is local.
|
||||
*/
|
||||
(*c_inp)(buf);
|
||||
|
||||
return df;
|
||||
}
|
||||
|
||||
CheckWithDef(df, tp)
|
||||
register struct def *df;
|
||||
struct type *tp;
|
||||
{
|
||||
/* Check the header of a procedure declaration against a
|
||||
possible earlier definition in the definition module.
|
||||
*/
|
||||
|
||||
if (df->df_type) {
|
||||
/* We already saw a definition of this type
|
||||
in the definition module.
|
||||
*/
|
||||
if (!TstProcEquiv(tp, df->df_type)) {
|
||||
error("inconsistent procedure declaration for \"%s\"",
|
||||
df->df_idf->id_text);
|
||||
}
|
||||
FreeType(df->df_type);
|
||||
}
|
||||
df->df_type = tp;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PrDef(df)
|
||||
register struct def *df;
|
||||
{
|
||||
print("n: %s, k: %d\n", df->df_idf->id_text, df->df_kind);
|
||||
}
|
||||
#endif DEBUG
|
|
@ -1,22 +0,0 @@
|
|||
/* D E F A U L T S I Z E S A N D A L I G N M E N T S */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#define MAXSIZE 8 /* the maximum of the SZ_* constants */
|
||||
/* target machine sizes */
|
||||
#define SZ_CHAR (arith)1
|
||||
#define SZ_WORD (arith)4
|
||||
#define SZ_INT (arith)4
|
||||
#define SZ_LONG (arith)4
|
||||
#define SZ_FLOAT (arith)4
|
||||
#define SZ_DOUBLE (arith)8
|
||||
#define SZ_POINTER (arith)4
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_WORD (int) SZ_WORD
|
||||
#define AL_INT (int) SZ_WORD
|
||||
#define AL_LONG (int) SZ_WORD
|
||||
#define AL_FLOAT (int) SZ_WORD
|
||||
#define AL_DOUBLE (int) SZ_WORD
|
||||
#define AL_POINTER (int) SZ_WORD
|
||||
#define AL_STRUCT 1
|
|
@ -1,115 +0,0 @@
|
|||
/* D E F I N I T I O N M O D U L E S */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
|
||||
#include "idf.h"
|
||||
#include "input.h"
|
||||
#include "scope.h"
|
||||
#include "def.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
#include "f_info.h"
|
||||
#include "main.h"
|
||||
#include "node.h"
|
||||
#include "type.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
long sys_filesize();
|
||||
#endif
|
||||
|
||||
struct idf *DefId;
|
||||
|
||||
STATIC
|
||||
GetFile(name)
|
||||
char *name;
|
||||
{
|
||||
/* Try to find a file with basename "name" and extension ".def",
|
||||
in the directories mentioned in "DEFPATH".
|
||||
*/
|
||||
char buf[15];
|
||||
char *strcpy(), *strcat();
|
||||
|
||||
strncpy(buf, name, 10);
|
||||
buf[10] = '\0'; /* maximum length */
|
||||
strcat(buf, ".def");
|
||||
if (! InsertFile(buf, DEFPATH, &(FileName))) {
|
||||
error("could not find a DEFINITION MODULE for \"%s\"", name);
|
||||
return 0;
|
||||
}
|
||||
LineNumber = 1;
|
||||
DO_DEBUG(options['F'], debug("File %s : %ld characters", FileName, sys_filesize(FileName)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct def *
|
||||
GetDefinitionModule(id, incr)
|
||||
register struct idf *id;
|
||||
{
|
||||
/* Return a pointer to the "def" structure of the definition
|
||||
module indicated by "id".
|
||||
We may have to read the definition module itself.
|
||||
Also increment level by "incr".
|
||||
*/
|
||||
register struct def *df;
|
||||
static int level;
|
||||
struct scopelist *vis;
|
||||
|
||||
level += incr;
|
||||
df = lookup(id, GlobalScope, 1);
|
||||
if (!df) {
|
||||
/* Read definition module. Make an exception for SYSTEM.
|
||||
*/
|
||||
if (!strcmp(id->id_text, "SYSTEM")) {
|
||||
do_SYSTEM();
|
||||
}
|
||||
else {
|
||||
open_scope(CLOSEDSCOPE);
|
||||
if (!is_anon_idf(id) && GetFile(id->id_text)) {
|
||||
DefId = id;
|
||||
DefModule();
|
||||
if (level == 1) {
|
||||
/* The module is directly imported by
|
||||
the currently defined module, so we
|
||||
have to remember its name because
|
||||
we have to call its initialization
|
||||
routine
|
||||
*/
|
||||
static struct node *nd_end;
|
||||
register struct node *n;
|
||||
extern struct node *Modules;
|
||||
|
||||
n = MkLeaf(Name, &dot);
|
||||
n->nd_IDF = id;
|
||||
n->nd_symb = IDENT;
|
||||
if (nd_end) nd_end->next = n;
|
||||
else Modules = n;
|
||||
nd_end = n;
|
||||
}
|
||||
}
|
||||
vis = CurrVis;
|
||||
close_scope(SC_CHKFORW);
|
||||
}
|
||||
df = lookup(id, GlobalScope, 1);
|
||||
if (! df) {
|
||||
df = MkDef(id, GlobalScope, D_ERROR);
|
||||
df->df_type = error_type;
|
||||
df->mod_vis = vis;
|
||||
}
|
||||
}
|
||||
else if (df->df_flags & D_BUSY) {
|
||||
error("definition module \"%s\" depends on itself",
|
||||
id->id_text);
|
||||
}
|
||||
else if (df == Defined && level == 1) {
|
||||
error("cannot import from currently defined module");
|
||||
df->df_kind = D_ERROR;
|
||||
}
|
||||
assert(df);
|
||||
level -= incr;
|
||||
return df;
|
||||
}
|
|
@ -1,572 +0,0 @@
|
|||
/* D E S I G N A T O R E V A L U A T I O N */
|
||||
|
||||
/* Code generation for designators.
|
||||
This file contains some routines that generate code common to address
|
||||
as well as value computations, and leave a description in a "desig"
|
||||
structure. It also contains routines to load an address, load a value
|
||||
or perform a store.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "type.h"
|
||||
#include "def.h"
|
||||
#include "scope.h"
|
||||
#include "desig.h"
|
||||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
|
||||
extern int proclevel;
|
||||
struct desig InitDesig = {DSG_INIT, 0, 0};
|
||||
|
||||
STATIC int
|
||||
properly(ds, size, al)
|
||||
register struct desig *ds;
|
||||
arith size;
|
||||
{
|
||||
/* Check if it is allowed to load or store the value indicated
|
||||
by "ds" with LOI/STI.
|
||||
- if the size is not either a multiple or a dividor of the
|
||||
wordsize, then not.
|
||||
- if the alignment is at least "word" then OK.
|
||||
- if size is dividor of word_size and alignment >= size then OK.
|
||||
- otherwise check alignment of address. This can only be done
|
||||
with DSG_FIXED.
|
||||
*/
|
||||
|
||||
arith szmodword = size % word_size; /* 0 if multiple of wordsize */
|
||||
arith wordmodsz = word_size % size; /* 0 if dividor of wordsize */
|
||||
|
||||
if (szmodword && wordmodsz) return 0;
|
||||
if (al >= word_size) return 1;
|
||||
if (szmodword && al >= szmodword) return 1;
|
||||
|
||||
return ds->dsg_kind == DSG_FIXED &&
|
||||
((! szmodword && ds->dsg_offset % word_size == 0) ||
|
||||
(! wordmodsz && ds->dsg_offset % size == 0));
|
||||
}
|
||||
|
||||
CodeValue(ds, size, al)
|
||||
register struct desig *ds;
|
||||
arith size;
|
||||
{
|
||||
/* Generate code to load the value of the designator described
|
||||
in "ds"
|
||||
*/
|
||||
arith tmp = 0;
|
||||
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_LOADED:
|
||||
break;
|
||||
|
||||
case DSG_FIXED:
|
||||
if (ds->dsg_offset % word_size == 0) {
|
||||
if (size == word_size) {
|
||||
if (ds->dsg_name) {
|
||||
C_loe_dnam(ds->dsg_name,ds->dsg_offset);
|
||||
}
|
||||
else C_lol(ds->dsg_offset);
|
||||
break;
|
||||
}
|
||||
|
||||
if (size == dword_size) {
|
||||
if (ds->dsg_name) {
|
||||
C_lde_dnam(ds->dsg_name,ds->dsg_offset);
|
||||
}
|
||||
else C_ldl(ds->dsg_offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Fall through */
|
||||
case DSG_PLOADED:
|
||||
case DSG_PFIXED:
|
||||
if (properly(ds, size, al)) {
|
||||
CodeAddress(ds);
|
||||
C_loi(size);
|
||||
break;
|
||||
}
|
||||
if (ds->dsg_kind == DSG_PLOADED) {
|
||||
tmp = NewPtr();
|
||||
C_stl(tmp);
|
||||
}
|
||||
C_asp(-WA(size));
|
||||
if (!tmp) CodeAddress(ds);
|
||||
else {
|
||||
C_lol(tmp);
|
||||
FreePtr(tmp);
|
||||
}
|
||||
C_loc(size);
|
||||
C_cal("_load");
|
||||
C_asp(2 * word_size);
|
||||
break;
|
||||
|
||||
case DSG_INDEXED:
|
||||
C_lar(word_size);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeValue)");
|
||||
}
|
||||
|
||||
ds->dsg_kind = DSG_LOADED;
|
||||
}
|
||||
|
||||
CodeStore(ds, size, al)
|
||||
register struct desig *ds;
|
||||
arith size;
|
||||
{
|
||||
/* Generate code to store the value on the stack in the designator
|
||||
described in "ds"
|
||||
*/
|
||||
struct desig save;
|
||||
|
||||
save = *ds;
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_FIXED:
|
||||
if (ds->dsg_offset % word_size == 0) {
|
||||
if (size == word_size) {
|
||||
if (ds->dsg_name) {
|
||||
C_ste_dnam(ds->dsg_name,ds->dsg_offset);
|
||||
}
|
||||
else C_stl(ds->dsg_offset);
|
||||
break;
|
||||
}
|
||||
|
||||
if (size == dword_size) {
|
||||
if (ds->dsg_name) {
|
||||
C_sde_dnam(ds->dsg_name,ds->dsg_offset);
|
||||
}
|
||||
else C_sdl(ds->dsg_offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Fall through */
|
||||
case DSG_PLOADED:
|
||||
case DSG_PFIXED:
|
||||
CodeAddress(&save);
|
||||
if (properly(ds, size, al)) {
|
||||
C_sti(size);
|
||||
break;
|
||||
}
|
||||
C_loc(size);
|
||||
C_cal("_store");
|
||||
C_asp(2 * word_size + WA(size));
|
||||
break;
|
||||
|
||||
case DSG_INDEXED:
|
||||
C_sar(word_size);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeStore)");
|
||||
}
|
||||
|
||||
ds->dsg_kind = DSG_INIT;
|
||||
}
|
||||
|
||||
CodeCopy(lhs, rhs, sz, psize)
|
||||
register struct desig *lhs, *rhs;
|
||||
arith sz, *psize;
|
||||
{
|
||||
struct desig l, r;
|
||||
|
||||
l = *lhs; r = *rhs;
|
||||
*psize -= sz;
|
||||
lhs->dsg_offset += sz;
|
||||
rhs->dsg_offset += sz;
|
||||
CodeAddress(&r);
|
||||
C_loi(sz);
|
||||
CodeAddress(&l);
|
||||
C_sti(sz);
|
||||
}
|
||||
|
||||
CodeMove(rhs, left, rtp)
|
||||
register struct desig *rhs;
|
||||
register struct node *left;
|
||||
struct type *rtp;
|
||||
{
|
||||
struct desig dsl;
|
||||
register struct desig *lhs = &dsl;
|
||||
register struct type *tp = left->nd_type;
|
||||
int loadedflag = 0;
|
||||
|
||||
dsl = InitDesig;
|
||||
|
||||
/* Generate code for an assignment. Testing of type
|
||||
compatibility and the like is already done.
|
||||
Go through some (considerable) trouble to see if a BLM can be
|
||||
generated.
|
||||
*/
|
||||
|
||||
switch(rhs->dsg_kind) {
|
||||
case DSG_LOADED:
|
||||
CodeDesig(left, lhs);
|
||||
CodeAddress(lhs);
|
||||
if (rtp->tp_fund == T_STRING) {
|
||||
C_loc(rtp->tp_size);
|
||||
C_loc(tp->tp_size);
|
||||
C_cal("_StringAssign");
|
||||
C_asp(word_size << 2);
|
||||
return;
|
||||
}
|
||||
CodeStore(lhs, tp->tp_size, tp->tp_align);
|
||||
return;
|
||||
case DSG_PLOADED:
|
||||
case DSG_PFIXED:
|
||||
CodeAddress(rhs);
|
||||
if (tp->tp_size % word_size == 0 && tp->tp_align >= word_size) {
|
||||
CodeDesig(left, lhs);
|
||||
CodeAddress(lhs);
|
||||
C_blm(tp->tp_size);
|
||||
return;
|
||||
}
|
||||
CodeValue(rhs, tp->tp_size, tp->tp_align);
|
||||
CodeDStore(left);
|
||||
return;
|
||||
case DSG_FIXED:
|
||||
CodeDesig(left, lhs);
|
||||
if (lhs->dsg_kind == DSG_FIXED &&
|
||||
lhs->dsg_offset % word_size ==
|
||||
rhs->dsg_offset % word_size) {
|
||||
register arith sz;
|
||||
arith size = tp->tp_size;
|
||||
|
||||
while (size && (sz = (lhs->dsg_offset % word_size))) {
|
||||
/* First copy up to word-aligned
|
||||
boundaries
|
||||
*/
|
||||
if (sz < 0) sz = -sz; /* bloody '%' */
|
||||
while (word_size % sz) sz--;
|
||||
CodeCopy(lhs, rhs, sz, &size);
|
||||
}
|
||||
if (size > 3*dword_size) {
|
||||
/* Do a block move
|
||||
*/
|
||||
struct desig l, r;
|
||||
|
||||
sz = (size / word_size) * word_size;
|
||||
l = *lhs; r = *rhs;
|
||||
CodeAddress(&r);
|
||||
CodeAddress(&l);
|
||||
C_blm(sz);
|
||||
rhs->dsg_offset += sz;
|
||||
lhs->dsg_offset += sz;
|
||||
size -= sz;
|
||||
}
|
||||
else for (sz = dword_size; sz; sz -= word_size) {
|
||||
while (size >= sz) {
|
||||
/* Then copy dwords, words.
|
||||
Depend on peephole optimizer
|
||||
*/
|
||||
CodeCopy(lhs, rhs, sz, &size);
|
||||
}
|
||||
}
|
||||
sz = word_size;
|
||||
while (size && --sz) {
|
||||
/* And then copy remaining parts
|
||||
*/
|
||||
while (word_size % sz) sz--;
|
||||
while (size >= sz) {
|
||||
CodeCopy(lhs, rhs, sz, &size);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (lhs->dsg_kind == DSG_PLOADED ||
|
||||
lhs->dsg_kind == DSG_INDEXED) {
|
||||
CodeAddress(lhs);
|
||||
loadedflag = 1;
|
||||
}
|
||||
if (tp->tp_size % word_size == 0 && tp->tp_align >= word_size) {
|
||||
CodeAddress(rhs);
|
||||
if (loadedflag) C_exg(pointer_size);
|
||||
else CodeAddress(lhs);
|
||||
C_blm(tp->tp_size);
|
||||
return;
|
||||
}
|
||||
{
|
||||
arith tmp;
|
||||
|
||||
if (loadedflag) {
|
||||
tmp = NewPtr();
|
||||
lhs->dsg_offset = tmp;
|
||||
lhs->dsg_name = 0;
|
||||
lhs->dsg_kind = DSG_PFIXED;
|
||||
C_stl(tmp); /* address of lhs */
|
||||
}
|
||||
CodeValue(rhs, tp->tp_size, tp->tp_align);
|
||||
CodeStore(lhs, tp->tp_size, tp->tp_align);
|
||||
if (loadedflag) FreePtr(tmp);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
crash("CodeMove");
|
||||
}
|
||||
}
|
||||
|
||||
CodeAddress(ds)
|
||||
register struct desig *ds;
|
||||
{
|
||||
/* Generate code to load the address of the designator described
|
||||
in "ds"
|
||||
*/
|
||||
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_PLOADED:
|
||||
if (ds->dsg_offset) {
|
||||
C_adp(ds->dsg_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case DSG_FIXED:
|
||||
if (ds->dsg_name) {
|
||||
C_lae_dnam(ds->dsg_name, ds->dsg_offset);
|
||||
break;
|
||||
}
|
||||
C_lal(ds->dsg_offset);
|
||||
break;
|
||||
|
||||
case DSG_PFIXED:
|
||||
if (ds->dsg_name) {
|
||||
C_loe_dnam(ds->dsg_name,ds->dsg_offset);
|
||||
break;
|
||||
}
|
||||
C_lol(ds->dsg_offset);
|
||||
break;
|
||||
|
||||
case DSG_INDEXED:
|
||||
C_aar(word_size);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeAddress)");
|
||||
}
|
||||
|
||||
ds->dsg_offset = 0;
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
}
|
||||
|
||||
CodeFieldDesig(df, ds)
|
||||
register struct def *df;
|
||||
register struct desig *ds;
|
||||
{
|
||||
/* Generate code for a field designator. Only the code common for
|
||||
address as well as value computation is generated, and the
|
||||
resulting information on where to find the designator is placed
|
||||
in "ds". "df" indicates the definition of the field.
|
||||
*/
|
||||
|
||||
if (ds->dsg_kind == DSG_INIT) {
|
||||
/* In a WITH statement. We must find the designator in the
|
||||
WITH statement, and act as if the field is a selection
|
||||
of this designator.
|
||||
So, first find the right WITH statement, which is the
|
||||
first one of the proper record type, which is
|
||||
recognized by its scope indication.
|
||||
*/
|
||||
register struct withdesig *wds = WithDesigs;
|
||||
|
||||
assert(wds != 0);
|
||||
|
||||
while (wds->w_scope != df->df_scope) {
|
||||
wds = wds->w_next;
|
||||
assert(wds != 0);
|
||||
}
|
||||
|
||||
/* Found it. Now, act like it was a selection.
|
||||
*/
|
||||
*ds = wds->w_desig;
|
||||
assert(ds->dsg_kind == DSG_PFIXED);
|
||||
}
|
||||
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_PLOADED:
|
||||
case DSG_FIXED:
|
||||
ds->dsg_offset += df->fld_off;
|
||||
break;
|
||||
|
||||
case DSG_PFIXED:
|
||||
case DSG_INDEXED:
|
||||
CodeAddress(ds);
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
ds->dsg_offset = df->fld_off;
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeFieldDesig)");
|
||||
}
|
||||
}
|
||||
|
||||
CodeVarDesig(df, ds)
|
||||
register struct def *df;
|
||||
register struct desig *ds;
|
||||
{
|
||||
/* Generate code for a variable represented by a "def" structure.
|
||||
Of course, there are numerous cases: the variable is local,
|
||||
it is a value parameter, it is a var parameter, it is one of
|
||||
those of an enclosing procedure, or it is global.
|
||||
*/
|
||||
register struct scope *sc = df->df_scope;
|
||||
|
||||
/* Selections from a module are handled earlier, when identifying
|
||||
the variable, so ...
|
||||
*/
|
||||
assert(ds->dsg_kind == DSG_INIT);
|
||||
|
||||
if (df->var_addrgiven) {
|
||||
/* the programmer specified an address in the declaration of
|
||||
the variable. Generate code to push the address.
|
||||
*/
|
||||
CodeConst(df->var_off, pointer_size);
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
ds->dsg_offset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (df->var_name) {
|
||||
/* this variable has been given a name, so it is global.
|
||||
It is directly accessible.
|
||||
*/
|
||||
ds->dsg_name = df->var_name;
|
||||
ds->dsg_offset = 0;
|
||||
ds->dsg_kind = DSG_FIXED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sc->sc_level != proclevel) {
|
||||
/* the variable is local to a statically enclosing procedure.
|
||||
*/
|
||||
assert(proclevel > sc->sc_level);
|
||||
|
||||
df->df_flags |= D_NOREG;
|
||||
if (df->df_flags & (D_VARPAR|D_VALPAR)) {
|
||||
/* value or var parameter
|
||||
*/
|
||||
C_lxa((arith) (proclevel - sc->sc_level));
|
||||
if ((df->df_flags & D_VARPAR) ||
|
||||
IsConformantArray(df->df_type)) {
|
||||
/* var parameter or conformant array.
|
||||
For conformant array's, the address is
|
||||
passed.
|
||||
*/
|
||||
C_adp(df->var_off);
|
||||
C_loi(pointer_size);
|
||||
ds->dsg_offset = 0;
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else C_lxl((arith) (proclevel - sc->sc_level));
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
ds->dsg_offset = df->var_off;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now, finally, we have a local variable or a local parameter
|
||||
*/
|
||||
if ((df->df_flags & D_VARPAR) || IsConformantArray(df->df_type)) {
|
||||
/* a var parameter; address directly accessible.
|
||||
*/
|
||||
ds->dsg_kind = DSG_PFIXED;
|
||||
}
|
||||
else ds->dsg_kind = DSG_FIXED;
|
||||
ds->dsg_offset =df->var_off;
|
||||
}
|
||||
|
||||
CodeDesig(nd, ds)
|
||||
register struct node *nd;
|
||||
register struct desig *ds;
|
||||
{
|
||||
/* Generate code for a designator. Use divide and conquer
|
||||
principle
|
||||
*/
|
||||
register struct def *df;
|
||||
|
||||
switch(nd->nd_class) { /* Divide */
|
||||
case Def:
|
||||
df = nd->nd_def;
|
||||
|
||||
switch(df->df_kind) {
|
||||
case D_FIELD:
|
||||
CodeFieldDesig(df, ds);
|
||||
break;
|
||||
|
||||
case D_VARIABLE:
|
||||
CodeVarDesig(df, ds);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeDesig) Def");
|
||||
}
|
||||
break;
|
||||
|
||||
case LinkDef:
|
||||
assert(nd->nd_symb == '.');
|
||||
|
||||
CodeDesig(nd->nd_left, ds);
|
||||
CodeFieldDesig(nd->nd_def, ds);
|
||||
break;
|
||||
|
||||
case Arrsel:
|
||||
assert(nd->nd_symb == '[');
|
||||
|
||||
CodeDesig(nd->nd_left, ds);
|
||||
CodeAddress(ds);
|
||||
CodePExpr(nd->nd_right);
|
||||
if (nd->nd_right->nd_type->tp_size > word_size) {
|
||||
CodeCoercion(nd->nd_right->nd_type, int_type);
|
||||
}
|
||||
|
||||
/* Now load address of descriptor
|
||||
*/
|
||||
if (IsConformantArray(nd->nd_left->nd_type)) {
|
||||
assert(nd->nd_left->nd_class == Def);
|
||||
|
||||
df = nd->nd_left->nd_def;
|
||||
if (proclevel > df->df_scope->sc_level) {
|
||||
C_lxa((arith) (proclevel - df->df_scope->sc_level));
|
||||
C_adp(df->var_off + pointer_size);
|
||||
}
|
||||
else C_lal(df->var_off + pointer_size);
|
||||
}
|
||||
else {
|
||||
C_lae_dlb(nd->nd_left->nd_type->arr_descr, (arith) 0);
|
||||
}
|
||||
ds->dsg_kind = DSG_INDEXED;
|
||||
break;
|
||||
|
||||
case Arrow:
|
||||
assert(nd->nd_symb == '^');
|
||||
|
||||
CodeDesig(nd->nd_right, ds);
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_LOADED:
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
break;
|
||||
|
||||
case DSG_INDEXED:
|
||||
case DSG_PLOADED:
|
||||
case DSG_PFIXED:
|
||||
CodeValue(ds, pointer_size, pointer_align);
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
ds->dsg_offset = 0;
|
||||
break;
|
||||
|
||||
case DSG_FIXED:
|
||||
ds->dsg_kind = DSG_PFIXED;
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeDesig) Uoper");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeDesig) class");
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/* D E S I G N A T O R D E S C R I P T I O N S */
|
||||
|
||||
/* Generating code for designators is not particularly easy, especially if
|
||||
you don't know wether you want the address or the value.
|
||||
The next structure is used to generate code for designators.
|
||||
It contains information on how to find the designator, after generation
|
||||
of the code that is common to both address and value computations.
|
||||
*/
|
||||
|
||||
struct desig {
|
||||
int dsg_kind;
|
||||
#define DSG_INIT 0 /* don't know anything yet */
|
||||
#define DSG_LOADED 1 /* designator loaded on top of the stack */
|
||||
#define DSG_PLOADED 2 /* designator accessible through pointer on
|
||||
stack, possibly with an offset
|
||||
*/
|
||||
#define DSG_FIXED 3 /* designator directly accessible */
|
||||
#define DSG_PFIXED 4 /* designator accessible through directly
|
||||
accessible pointer
|
||||
*/
|
||||
#define DSG_INDEXED 5 /* designator accessible through array
|
||||
operation. Address of array descriptor on
|
||||
top of the stack, index beneath that, and
|
||||
base address beneath that
|
||||
*/
|
||||
arith dsg_offset; /* contains an offset for PLOADED,
|
||||
or for FIXED or PFIXED it contains an
|
||||
offset from dsg_name, if it exists,
|
||||
or from the current Local Base
|
||||
*/
|
||||
char *dsg_name; /* name of global variable, used for
|
||||
FIXED and PFIXED
|
||||
*/
|
||||
};
|
||||
|
||||
/* The next structure describes the designator in a with-statement.
|
||||
We have a linked list of them, as with-statements may be nested.
|
||||
*/
|
||||
|
||||
struct withdesig {
|
||||
struct withdesig *w_next;
|
||||
struct scope *w_scope; /* scope in which fields of this record
|
||||
reside
|
||||
*/
|
||||
struct desig w_desig; /* a desig structure for this particular
|
||||
designator
|
||||
*/
|
||||
};
|
||||
|
||||
extern struct withdesig *WithDesigs;
|
||||
extern struct desig InitDesig;
|
||||
|
||||
#define NO_LABEL ((label) 0)
|
|
@ -1,451 +0,0 @@
|
|||
/* H I G H L E V E L S Y M B O L E N T R Y */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "idf.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "scope.h"
|
||||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
#include "main.h"
|
||||
#include "misc.h"
|
||||
|
||||
struct def *
|
||||
Enter(name, kind, type, pnam)
|
||||
char *name;
|
||||
struct type *type;
|
||||
{
|
||||
/* Enter a definition for "name" with kind "kind" and type
|
||||
"type" in the Current Scope. If it is a standard name, also
|
||||
put its number in the definition structure.
|
||||
*/
|
||||
register struct def *df;
|
||||
|
||||
df = define(str2idf(name, 0), CurrentScope, kind);
|
||||
df->df_type = type;
|
||||
if (pnam) df->df_value.df_stdname = pnam;
|
||||
return df;
|
||||
}
|
||||
|
||||
EnterEnumList(Idlist, type)
|
||||
struct node *Idlist;
|
||||
register struct type *type;
|
||||
{
|
||||
/* Put a list of enumeration literals in the symbol table.
|
||||
They all have type "type".
|
||||
Also assign numbers to them, and link them together.
|
||||
We must link them together because an enumeration type may
|
||||
be exported, in which case its literals must also be exported.
|
||||
Thus, we need an easy way to get to them.
|
||||
*/
|
||||
register struct def *df;
|
||||
register struct node *idlist = Idlist;
|
||||
|
||||
type->enm_ncst = 0;
|
||||
for (; idlist; idlist = idlist->next) {
|
||||
df = define(idlist->nd_IDF, CurrentScope, D_ENUM);
|
||||
df->df_type = type;
|
||||
df->enm_val = (type->enm_ncst)++;
|
||||
df->enm_next = type->enm_enums;
|
||||
type->enm_enums = df;
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
EnterFieldList(Idlist, type, scope, addr)
|
||||
struct node *Idlist;
|
||||
register struct type *type;
|
||||
struct scope *scope;
|
||||
arith *addr;
|
||||
{
|
||||
/* Put a list of fields in the symbol table.
|
||||
They all have type "type", and are put in scope "scope".
|
||||
Mark them as QUALIFIED EXPORT, because that's exactly what
|
||||
fields are, you can get to them by qualifying them.
|
||||
*/
|
||||
register struct def *df;
|
||||
register struct node *idlist = Idlist;
|
||||
|
||||
for (; idlist; idlist = idlist->next) {
|
||||
df = define(idlist->nd_IDF, scope, D_FIELD);
|
||||
df->df_type = type;
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
df->fld_off = align(*addr, type->tp_align);
|
||||
*addr = df->fld_off + type->tp_size;
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
EnterVarList(Idlist, type, local)
|
||||
struct node *Idlist;
|
||||
struct type *type;
|
||||
{
|
||||
/* Enter a list of identifiers representing variables into the
|
||||
name list. "type" represents the type of the variables.
|
||||
"local" is set if the variables are declared local to a
|
||||
procedure.
|
||||
*/
|
||||
register struct def *df;
|
||||
register struct node *idlist = Idlist;
|
||||
register struct scopelist *sc;
|
||||
char buf[256];
|
||||
extern char *sprint();
|
||||
|
||||
sc = CurrVis;
|
||||
|
||||
if (local) {
|
||||
/* Find the closest enclosing open scope. This
|
||||
is the procedure that we are dealing with
|
||||
*/
|
||||
while (sc->sc_scope->sc_scopeclosed) sc = enclosing(sc);
|
||||
}
|
||||
|
||||
for (; idlist; idlist = idlist->nd_right) {
|
||||
df = define(idlist->nd_IDF, CurrentScope, D_VARIABLE);
|
||||
df->df_type = type;
|
||||
if (idlist->nd_left) {
|
||||
/* An address was supplied
|
||||
*/
|
||||
register struct type *tp = idlist->nd_left->nd_type;
|
||||
|
||||
df->var_addrgiven = 1;
|
||||
df->df_flags |= D_NOREG;
|
||||
if (tp != error_type && !(tp->tp_fund & T_CARDINAL)){
|
||||
node_error(idlist->nd_left,
|
||||
"illegal type for address");
|
||||
}
|
||||
df->var_off = idlist->nd_left->nd_INT;
|
||||
}
|
||||
else if (local) {
|
||||
/* subtract aligned size of variable to the offset,
|
||||
as the variable list exists only local to a
|
||||
procedure
|
||||
*/
|
||||
sc->sc_scope->sc_off =
|
||||
-WA(align(type->tp_size - sc->sc_scope->sc_off,
|
||||
type->tp_align));
|
||||
df->var_off = sc->sc_scope->sc_off;
|
||||
}
|
||||
else {
|
||||
/* Global name, possibly external
|
||||
*/
|
||||
sprint(buf,"%s_%s", sc->sc_scope->sc_name,
|
||||
df->df_idf->id_text);
|
||||
df->var_name = Salloc(buf, (unsigned)(strlen(buf)+1));
|
||||
df->df_flags |= D_NOREG;
|
||||
|
||||
if (DefinitionModule) {
|
||||
if (sc == Defined->mod_vis) {
|
||||
C_exa_dnam(df->var_name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
C_ina_dnam(df->var_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
EnterParamList(ppr, Idlist, type, VARp, off)
|
||||
struct paramlist **ppr;
|
||||
struct node *Idlist;
|
||||
struct type *type;
|
||||
int VARp;
|
||||
arith *off;
|
||||
{
|
||||
/* Create (part of) a parameterlist of a procedure.
|
||||
"ids" indicates the list of identifiers, "tp" their type, and
|
||||
"VARp" indicates D_VARPAR or D_VALPAR.
|
||||
*/
|
||||
register struct paramlist *pr;
|
||||
register struct def *df;
|
||||
register struct node *idlist = Idlist;
|
||||
struct node *dummy = 0;
|
||||
static struct paramlist *last;
|
||||
|
||||
if (! idlist) {
|
||||
/* Can only happen when a procedure type is defined */
|
||||
dummy = Idlist = idlist = MkLeaf(Name, &dot);
|
||||
}
|
||||
for ( ; idlist; idlist = idlist->next) {
|
||||
pr = new_paramlist();
|
||||
pr->next = 0;
|
||||
if (!*ppr) *ppr = pr;
|
||||
else last->next = pr;
|
||||
last = pr;
|
||||
if (!DefinitionModule && idlist != dummy) {
|
||||
df = define(idlist->nd_IDF, CurrentScope, D_VARIABLE);
|
||||
df->var_off = *off;
|
||||
}
|
||||
else df = new_def();
|
||||
pr->par_def = df;
|
||||
df->df_type = type;
|
||||
df->df_flags = VARp;
|
||||
|
||||
if (IsConformantArray(type)) {
|
||||
/* we need room for the base address and a descriptor
|
||||
*/
|
||||
*off += pointer_size + 3 * word_size;
|
||||
}
|
||||
else if (VARp == D_VARPAR) {
|
||||
*off += pointer_size;
|
||||
}
|
||||
else {
|
||||
*off += WA(type->tp_size);
|
||||
}
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
STATIC
|
||||
DoImport(df, scope)
|
||||
register struct def *df;
|
||||
struct scope *scope;
|
||||
{
|
||||
/* Definition "df" is imported to scope "scope".
|
||||
Handle the case that it is an enumeration type or a module.
|
||||
*/
|
||||
|
||||
define(df->df_idf, scope, D_IMPORT)->imp_def = df;
|
||||
|
||||
if (df->df_kind == D_TYPE && df->df_type->tp_fund == T_ENUMERATION) {
|
||||
/* Also import all enumeration literals
|
||||
*/
|
||||
for (df = df->df_type->enm_enums; df; df = df->enm_next) {
|
||||
define(df->df_idf, scope, D_IMPORT)->imp_def = df;
|
||||
}
|
||||
}
|
||||
else if (df->df_kind == D_MODULE) {
|
||||
/* Also import all definitions that are exported from this
|
||||
module
|
||||
*/
|
||||
if (df->mod_vis == CurrVis) {
|
||||
error("cannot import current module \"%s\"",
|
||||
df->df_idf->id_text);
|
||||
return;
|
||||
}
|
||||
for (df = df->mod_vis->sc_scope->sc_def;
|
||||
df;
|
||||
df = df->df_nextinscope) {
|
||||
if (df->df_flags & D_EXPORTED) {
|
||||
define(df->df_idf,scope,D_IMPORT)->imp_def = df;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC struct scopelist *
|
||||
ForwModule(df, nd)
|
||||
register struct def *df;
|
||||
struct node *nd;
|
||||
{
|
||||
/* An import is done from a not yet defined module "df".
|
||||
We could also end up here for not found DEFINITION MODULES.
|
||||
Create a declaration and a scope for this module.
|
||||
*/
|
||||
struct scopelist *vis;
|
||||
|
||||
if (df->df_scope != GlobalScope) {
|
||||
df->df_scope = enclosing(CurrVis)->sc_scope;
|
||||
df->df_kind = D_FORWMODULE;
|
||||
}
|
||||
open_scope(CLOSEDSCOPE);
|
||||
vis = CurrVis; /* The new scope, but watch out, it's "sc_encl"
|
||||
field is not set right. It must indicate the
|
||||
enclosing scope, but this must be done AFTER
|
||||
closing this one
|
||||
*/
|
||||
close_scope(0);
|
||||
vis->sc_encl = enclosing(CurrVis);
|
||||
/* Here ! */
|
||||
df->for_vis = vis;
|
||||
df->for_node = nd;
|
||||
return vis;
|
||||
}
|
||||
|
||||
STATIC struct def *
|
||||
ForwDef(ids, scope)
|
||||
register struct node *ids;
|
||||
struct scope *scope;
|
||||
{
|
||||
/* Enter a forward definition of "ids" in scope "scope",
|
||||
if it is not already defined.
|
||||
*/
|
||||
register struct def *df;
|
||||
|
||||
if (!(df = lookup(ids->nd_IDF, scope, 1))) {
|
||||
df = define(ids->nd_IDF, scope, D_FORWARD);
|
||||
df->for_node = MkLeaf(Name, &(ids->nd_token));
|
||||
}
|
||||
return df;
|
||||
}
|
||||
|
||||
EnterExportList(Idlist, qualified)
|
||||
struct node *Idlist;
|
||||
{
|
||||
/* From the current scope, the list of identifiers "ids" is
|
||||
exported. Note this fact. If the export is not qualified, make
|
||||
all the "ids" visible in the enclosing scope by defining them
|
||||
in this scope as "imported".
|
||||
*/
|
||||
register struct node *idlist = Idlist;
|
||||
register struct def *df, *df1;
|
||||
|
||||
for (;idlist; idlist = idlist->next) {
|
||||
df = lookup(idlist->nd_IDF, CurrentScope, 0);
|
||||
|
||||
if (!df) {
|
||||
/* undefined item in export list
|
||||
*/
|
||||
node_error(idlist,
|
||||
"identifier \"%s\" not defined",
|
||||
idlist->nd_IDF->id_text);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (df->df_flags & (D_EXPORTED|D_QEXPORTED)) {
|
||||
node_error(idlist,
|
||||
"multiple occurrences of \"%s\" in export list",
|
||||
idlist->nd_IDF->id_text);
|
||||
}
|
||||
|
||||
if (df->df_kind == D_IMPORT) df = df->imp_def;
|
||||
|
||||
df->df_flags |= qualified;
|
||||
if (qualified == D_EXPORTED) {
|
||||
/* Export, but not qualified.
|
||||
Find all imports of the module in which this export
|
||||
occurs, and export the current definition to it
|
||||
*/
|
||||
df1 = CurrentScope->sc_definedby->df_idf->id_def;
|
||||
while (df1) {
|
||||
if (df1->df_kind == D_IMPORT &&
|
||||
df1->imp_def == CurrentScope->sc_definedby) {
|
||||
DoImport(df, df1->df_scope);
|
||||
}
|
||||
df1 = df1->next;
|
||||
}
|
||||
|
||||
/* Also handle the definition as if the enclosing
|
||||
scope imports it.
|
||||
*/
|
||||
df1 = lookup(idlist->nd_IDF,
|
||||
enclosing(CurrVis)->sc_scope, 1);
|
||||
if (df1) {
|
||||
/* It was already defined in the enclosing
|
||||
scope. There are two legal possibilities,
|
||||
which are examined below.
|
||||
*/
|
||||
if (df1->df_kind == D_PROCHEAD &&
|
||||
df->df_kind == D_PROCEDURE) {
|
||||
df1->df_kind = D_IMPORT;
|
||||
df1->imp_def = df;
|
||||
continue;
|
||||
}
|
||||
if (df1->df_kind == D_HIDDEN &&
|
||||
df->df_kind == D_TYPE) {
|
||||
DeclareType(idlist, df1, df->df_type);
|
||||
df1->df_kind = D_TYPE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
DoImport(df, enclosing(CurrVis)->sc_scope);
|
||||
}
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
EnterFromImportList(Idlist, FromDef, FromId)
|
||||
struct node *Idlist;
|
||||
register struct def *FromDef;
|
||||
struct node *FromId;
|
||||
{
|
||||
/* Import the list Idlist from the module indicated by Fromdef.
|
||||
*/
|
||||
register struct node *idlist = Idlist;
|
||||
register struct scopelist *vis;
|
||||
register struct def *df;
|
||||
char *module_name = FromDef->df_idf->id_text;
|
||||
int forwflag = 0;
|
||||
|
||||
switch(FromDef->df_kind) {
|
||||
case D_ERROR:
|
||||
/* The module from which the import was done
|
||||
is not yet declared. I'm not sure if I must
|
||||
accept this, but for the time being I will.
|
||||
We also end up here if some definition module could not
|
||||
be found.
|
||||
???
|
||||
*/
|
||||
vis = ForwModule(FromDef, FromId);
|
||||
forwflag = 1;
|
||||
break;
|
||||
case D_FORWMODULE:
|
||||
vis = FromDef->for_vis;
|
||||
break;
|
||||
case D_MODULE:
|
||||
vis = FromDef->mod_vis;
|
||||
if (vis == CurrVis) {
|
||||
node_error(FromId, "cannot import from current module \"%s\"", module_name);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
node_error(FromId,"identifier \"%s\" does not represent a module",module_name);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; idlist; idlist = idlist->next) {
|
||||
if (forwflag) df = ForwDef(idlist, vis->sc_scope);
|
||||
else if (! (df = lookup(idlist->nd_IDF, vis->sc_scope, 1))) {
|
||||
if (! is_anon_idf(idlist->nd_IDF)) {
|
||||
node_error(idlist,
|
||||
"identifier \"%s\" not declared in module \"%s\"",
|
||||
idlist->nd_IDF->id_text,
|
||||
module_name);
|
||||
}
|
||||
df = define(idlist->nd_IDF,vis->sc_scope,D_ERROR);
|
||||
}
|
||||
else if (! (df->df_flags & (D_EXPORTED|D_QEXPORTED))) {
|
||||
node_error(idlist,
|
||||
"identifier \"%s\" not exported from module \"%s\"",
|
||||
idlist->nd_IDF->id_text,
|
||||
module_name);
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
}
|
||||
DoImport(df, CurrentScope);
|
||||
}
|
||||
|
||||
if (!forwflag) FreeNode(FromId);
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
EnterImportList(Idlist, local)
|
||||
struct node *Idlist;
|
||||
{
|
||||
/* Import "Idlist" from the enclosing scope.
|
||||
An exception must be made for imports of the compilation unit.
|
||||
In this case, definition modules must be read for "Idlist".
|
||||
This case is indicated by the value 0 of the "local" flag.
|
||||
*/
|
||||
register struct node *idlist = Idlist;
|
||||
struct scope *sc = enclosing(CurrVis)->sc_scope;
|
||||
extern struct def *GetDefinitionModule();
|
||||
|
||||
for (; idlist; idlist = idlist->next) {
|
||||
DoImport(local ?
|
||||
ForwDef(idlist, sc) :
|
||||
GetDefinitionModule(idlist->nd_IDF, 1) ,
|
||||
CurrentScope);
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
/* E R R O R A N D D I A G N O S T I C R O U T I N E S */
|
||||
|
||||
/* This file contains the (non-portable) error-message and diagnostic
|
||||
giving functions. Be aware that they are called with a variable
|
||||
number of arguments!
|
||||
*/
|
||||
|
||||
#include "errout.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <system.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "f_info.h"
|
||||
#include "LLlex.h"
|
||||
#include "main.h"
|
||||
#include "node.h"
|
||||
#include "warning.h"
|
||||
|
||||
/* error classes */
|
||||
#define ERROR 1
|
||||
#define WARNING 2
|
||||
#define LEXERROR 3
|
||||
#define LEXWARNING 4
|
||||
#define CRASH 5
|
||||
#define FATAL 6
|
||||
#ifdef DEBUG
|
||||
#define VDEBUG 7
|
||||
#endif
|
||||
|
||||
int err_occurred;
|
||||
static int warn_class;
|
||||
|
||||
extern char *symbol2str();
|
||||
|
||||
/* There are three general error-message functions:
|
||||
lexerror() lexical and pre-processor error messages
|
||||
error() syntactic and semantic error messages
|
||||
node_error() errors in nodes
|
||||
The difference lies in the place where the file name and line
|
||||
number come from.
|
||||
Lexical errors report from the global variables LineNumber and
|
||||
FileName, node errors get their information from the
|
||||
node, whereas other errors use the information in the token.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
/*VARARGS1*/
|
||||
debug(fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
_error(VDEBUG, NULLNODE, fmt, &args);
|
||||
}
|
||||
#endif DEBUG
|
||||
|
||||
/*VARARGS1*/
|
||||
error(fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
_error(ERROR, NULLNODE, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS2*/
|
||||
node_error(node, fmt, args)
|
||||
struct node *node;
|
||||
char *fmt;
|
||||
{
|
||||
_error(ERROR, node, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
warning(class, fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
warn_class = class;
|
||||
if (class & warning_classes) _error(WARNING, NULLNODE, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS2*/
|
||||
node_warning(node, class, fmt, args)
|
||||
struct node *node;
|
||||
char *fmt;
|
||||
{
|
||||
warn_class = class;
|
||||
if (class & warning_classes) _error(WARNING, node, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
lexerror(fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
_error(LEXERROR, NULLNODE, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
lexwarning(class, fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
warn_class = class;
|
||||
if (class & warning_classes) _error(LEXWARNING, NULLNODE, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
fatal(fmt, args)
|
||||
char *fmt;
|
||||
int args;
|
||||
{
|
||||
|
||||
_error(FATAL, NULLNODE, fmt, &args);
|
||||
sys_stop(S_EXIT);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
crash(fmt, args)
|
||||
char *fmt;
|
||||
int args;
|
||||
{
|
||||
|
||||
_error(CRASH, NULLNODE, fmt, &args);
|
||||
#ifdef DEBUG
|
||||
sys_stop(S_ABORT);
|
||||
#else
|
||||
sys_stop(S_EXIT);
|
||||
#endif
|
||||
}
|
||||
|
||||
_error(class, node, fmt, argv)
|
||||
int class;
|
||||
struct node *node;
|
||||
char *fmt;
|
||||
int argv[];
|
||||
{
|
||||
/* _error attempts to limit the number of error messages
|
||||
for a given line to MAXERR_LINE.
|
||||
*/
|
||||
static unsigned int last_ln = 0;
|
||||
unsigned int ln = 0;
|
||||
static char * last_fn = 0;
|
||||
static int e_seen = 0;
|
||||
register char *remark = 0;
|
||||
|
||||
/* Since name and number are gathered from different places
|
||||
depending on the class, we first collect the relevant
|
||||
values and then decide what to print.
|
||||
*/
|
||||
/* preliminaries */
|
||||
switch (class) {
|
||||
case ERROR:
|
||||
case LEXERROR:
|
||||
case CRASH:
|
||||
case FATAL:
|
||||
if (C_busy()) C_ms_err();
|
||||
err_occurred = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* the remark */
|
||||
switch (class) {
|
||||
case WARNING:
|
||||
case LEXWARNING:
|
||||
switch(warn_class) {
|
||||
case W_OLDFASHIONED:
|
||||
remark = "(old-fashioned use)";
|
||||
break;
|
||||
case W_STRICT:
|
||||
remark = "(strict)";
|
||||
break;
|
||||
default:
|
||||
remark = "(warning)";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CRASH:
|
||||
remark = "CRASH\007";
|
||||
break;
|
||||
case FATAL:
|
||||
remark = "fatal error --";
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
case VDEBUG:
|
||||
remark = "(debug)";
|
||||
break;
|
||||
#endif DEBUG
|
||||
}
|
||||
|
||||
/* the place */
|
||||
switch (class) {
|
||||
case WARNING:
|
||||
case ERROR:
|
||||
ln = node ? node->nd_lineno : dot.tk_lineno;
|
||||
break;
|
||||
case LEXWARNING:
|
||||
case LEXERROR:
|
||||
case CRASH:
|
||||
case FATAL:
|
||||
#ifdef DEBUG
|
||||
case VDEBUG:
|
||||
#endif DEBUG
|
||||
ln = LineNumber;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (class != VDEBUG) {
|
||||
#endif
|
||||
if (FileName == last_fn && ln == last_ln) {
|
||||
/* we've seen this place before */
|
||||
e_seen++;
|
||||
if (e_seen == MAXERR_LINE) fmt = "etc ...";
|
||||
else
|
||||
if (e_seen > MAXERR_LINE)
|
||||
/* and too often, I'd say ! */
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* brand new place */
|
||||
last_ln = ln;
|
||||
last_fn = FileName;
|
||||
e_seen = 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
}
|
||||
#endif DEBUG
|
||||
|
||||
if (FileName) fprint(ERROUT, "\"%s\", line %u: ", FileName, ln);
|
||||
|
||||
if (remark) fprint(ERROUT, "%s ", remark);
|
||||
|
||||
doprnt(ERROUT, fmt, argv); /* contents of error */
|
||||
fprint(ERROUT, "\n");
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
/* E X P R E S S I O N S */
|
||||
|
||||
{
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "LLlex.h"
|
||||
#include "idf.h"
|
||||
#include "def.h"
|
||||
#include "node.h"
|
||||
#include "const.h"
|
||||
#include "type.h"
|
||||
#include "chk_expr.h"
|
||||
#include "warning.h"
|
||||
|
||||
extern char options[];
|
||||
}
|
||||
|
||||
number(struct node **p;) :
|
||||
[
|
||||
%default
|
||||
INTEGER
|
||||
|
|
||||
REAL
|
||||
] { *p = MkLeaf(Value, &dot);
|
||||
(*p)->nd_type = toktype;
|
||||
}
|
||||
;
|
||||
|
||||
qualident(struct node **p;)
|
||||
{
|
||||
} :
|
||||
IDENT { *p = MkLeaf(Name, &dot); }
|
||||
[
|
||||
selector(p)
|
||||
]*
|
||||
;
|
||||
|
||||
selector(struct node **pnd;):
|
||||
'.' { *pnd = MkNode(Link,*pnd,NULLNODE,&dot); }
|
||||
IDENT { (*pnd)->nd_IDF = dot.TOK_IDF; }
|
||||
;
|
||||
|
||||
ExpList(struct node **pnd;)
|
||||
{
|
||||
register struct node *nd;
|
||||
} :
|
||||
expression(pnd) { *pnd = nd = MkNode(Link,*pnd,NULLNODE,&dot);
|
||||
nd->nd_symb = ',';
|
||||
}
|
||||
[
|
||||
',' { nd->nd_right = MkLeaf(Link, &dot);
|
||||
nd = nd->nd_right;
|
||||
}
|
||||
expression(&(nd->nd_left))
|
||||
]*
|
||||
;
|
||||
|
||||
ConstExpression(struct node **pnd;)
|
||||
{
|
||||
register struct node *nd;
|
||||
}:
|
||||
expression(pnd)
|
||||
/*
|
||||
* Changed rule in new Modula-2.
|
||||
* Check that the expression is a constant expression and evaluate!
|
||||
*/
|
||||
{ nd = *pnd;
|
||||
DO_DEBUG(options['X'], print("CONSTANT EXPRESSION\n"));
|
||||
DO_DEBUG(options['X'], PrNode(nd, 0));
|
||||
|
||||
if (ChkExpression(nd) &&
|
||||
((nd)->nd_class != Set && (nd)->nd_class != Value)) {
|
||||
error("constant expression expected");
|
||||
}
|
||||
|
||||
DO_DEBUG(options['X'], print("RESULTS IN\n"));
|
||||
DO_DEBUG(options['X'], PrNode(nd, 0));
|
||||
}
|
||||
;
|
||||
|
||||
expression(struct node **pnd;)
|
||||
{
|
||||
} :
|
||||
SimpleExpression(pnd)
|
||||
[
|
||||
/* relation */
|
||||
[ '=' | '#' | '<' | LESSEQUAL | '>' | GREATEREQUAL | IN ]
|
||||
{ *pnd = MkNode(Oper, *pnd, NULLNODE, &dot); }
|
||||
SimpleExpression(&((*pnd)->nd_right))
|
||||
]?
|
||||
;
|
||||
|
||||
/* Inline in expression
|
||||
relation:
|
||||
'=' | '#' | '<' | LESSEQUAL | '>' | GREATEREQUAL | IN
|
||||
;
|
||||
*/
|
||||
|
||||
SimpleExpression(struct node **pnd;)
|
||||
{
|
||||
} :
|
||||
[
|
||||
[ '+' | '-' ]
|
||||
{ *pnd = MkLeaf(Uoper, &dot);
|
||||
pnd = &((*pnd)->nd_right);
|
||||
/* priority of unary operator ??? */
|
||||
}
|
||||
]?
|
||||
term(pnd)
|
||||
[
|
||||
/* AddOperator */
|
||||
[ '+' | '-' | OR ]
|
||||
{ *pnd = MkNode(Oper, *pnd, NULLNODE, &dot); }
|
||||
term(&((*pnd)->nd_right))
|
||||
]*
|
||||
;
|
||||
|
||||
/* Inline in "SimpleExpression"
|
||||
AddOperator:
|
||||
'+' | '-' | OR
|
||||
;
|
||||
*/
|
||||
|
||||
term(struct node **pnd;)
|
||||
{
|
||||
}:
|
||||
factor(pnd)
|
||||
[
|
||||
/* MulOperator */
|
||||
[ '*' | '/' | DIV | MOD | AND | '&' ]
|
||||
{ *pnd = MkNode(Oper, *pnd, NULLNODE, &dot); }
|
||||
factor(&((*pnd)->nd_right))
|
||||
]*
|
||||
;
|
||||
|
||||
/* inline in "term"
|
||||
MulOperator:
|
||||
'*' | '/' | DIV | MOD | AND | '&'
|
||||
;
|
||||
*/
|
||||
|
||||
factor(register struct node **p;)
|
||||
{
|
||||
struct node *nd;
|
||||
} :
|
||||
qualident(p)
|
||||
[
|
||||
designator_tail(p)?
|
||||
[
|
||||
{ *p = MkNode(Call, *p, NULLNODE, &dot); }
|
||||
ActualParameters(&((*p)->nd_right))
|
||||
]?
|
||||
|
|
||||
bare_set(&nd)
|
||||
{ nd->nd_left = *p; *p = nd; }
|
||||
]
|
||||
|
|
||||
bare_set(p)
|
||||
| %default
|
||||
number(p)
|
||||
|
|
||||
STRING { *p = MkLeaf(Value, &dot);
|
||||
(*p)->nd_type = toktype;
|
||||
}
|
||||
|
|
||||
'(' expression(p) ')'
|
||||
|
|
||||
NOT { *p = MkLeaf(Uoper, &dot); }
|
||||
factor(&((*p)->nd_right))
|
||||
;
|
||||
|
||||
bare_set(struct node **pnd;)
|
||||
{
|
||||
register struct node *nd;
|
||||
} :
|
||||
'{' { dot.tk_symb = SET;
|
||||
*pnd = nd = MkLeaf(Xset, &dot);
|
||||
nd->nd_type = bitset_type;
|
||||
}
|
||||
[
|
||||
element(nd)
|
||||
[ { nd = nd->nd_right; }
|
||||
',' element(nd)
|
||||
]*
|
||||
]?
|
||||
'}'
|
||||
;
|
||||
|
||||
ActualParameters(struct node **pnd;):
|
||||
'(' ExpList(pnd)? ')'
|
||||
;
|
||||
|
||||
element(struct node *nd;)
|
||||
{
|
||||
struct node *nd1;
|
||||
} :
|
||||
expression(&nd1)
|
||||
[
|
||||
UPTO
|
||||
{ nd1 = MkNode(Link, nd1, NULLNODE, &dot);}
|
||||
expression(&(nd1->nd_right))
|
||||
]?
|
||||
{ nd->nd_right = MkNode(Link, nd1, NULLNODE, &dot);
|
||||
nd->nd_right->nd_symb = ',';
|
||||
}
|
||||
;
|
||||
|
||||
designator(struct node **pnd;)
|
||||
:
|
||||
qualident(pnd)
|
||||
designator_tail(pnd)?
|
||||
;
|
||||
|
||||
designator_tail(struct node **pnd;):
|
||||
visible_designator_tail(pnd)
|
||||
[ %persistent
|
||||
%default
|
||||
selector(pnd)
|
||||
|
|
||||
visible_designator_tail(pnd)
|
||||
]*
|
||||
;
|
||||
|
||||
visible_designator_tail(register struct node **pnd;):
|
||||
'[' { *pnd = MkNode(Arrsel, *pnd, NULLNODE, &dot); }
|
||||
expression(&((*pnd)->nd_right))
|
||||
[
|
||||
','
|
||||
{ *pnd = MkNode(Arrsel, *pnd, NULLNODE, &dot);
|
||||
(*pnd)->nd_symb = '[';
|
||||
}
|
||||
expression(&((*pnd)->nd_right))
|
||||
]*
|
||||
']'
|
||||
|
|
||||
'^' { *pnd = MkNode(Arrow, NULLNODE, *pnd, &dot); }
|
||||
;
|
|
@ -1,11 +0,0 @@
|
|||
/* F I L E D E S C R I P T O R S T R U C T U R E */
|
||||
|
||||
struct f_info {
|
||||
unsigned short f_lineno;
|
||||
char *f_filename;
|
||||
char *f_workingdir;
|
||||
};
|
||||
|
||||
extern struct f_info file_info;
|
||||
#define LineNumber file_info.f_lineno
|
||||
#define FileName file_info.f_filename
|
|
@ -1,4 +0,0 @@
|
|||
/* I N S T A N T I A T I O N O F I D F P A C K A G E */
|
||||
|
||||
#include "idf.h"
|
||||
#include <idf_pkg.body>
|
|
@ -1,12 +0,0 @@
|
|||
/* U S E R D E C L A R E D P A R T O F I D F */
|
||||
|
||||
struct id_u {
|
||||
int id_res;
|
||||
struct def *id_df;
|
||||
};
|
||||
|
||||
#define IDF_TYPE struct id_u
|
||||
#define id_reserved id_user.id_res
|
||||
#define id_def id_user.id_df
|
||||
|
||||
#include <idf_pkg.spec>
|
|
@ -1,12 +0,0 @@
|
|||
/* $Header$ */
|
||||
|
||||
#include <alloc.h>
|
||||
|
||||
/* Structure to link idf structures together
|
||||
*/
|
||||
struct id_list {
|
||||
struct id_list *next;
|
||||
struct idf *id_ptr;
|
||||
};
|
||||
|
||||
/* ALLOCDEF "id_list" */
|
|
@ -1,20 +0,0 @@
|
|||
static char *RcsId = "$Header$";
|
||||
|
||||
#include "idf.h"
|
||||
#include "idlist.h"
|
||||
|
||||
struct id_list *h_id_list; /* Header of free list */
|
||||
|
||||
/* FreeIdList: take a list of id_list structures and put them
|
||||
on the free list of id_list structures
|
||||
*/
|
||||
FreeIdList(p)
|
||||
struct id_list *p;
|
||||
{
|
||||
register struct id_list *q;
|
||||
|
||||
while (q = p) {
|
||||
p = p->next;
|
||||
free_id_list(q);
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/* I N S T A N T I A T I O N O F I N P U T P A C K A G E */
|
||||
|
||||
#include "f_info.h"
|
||||
struct f_info file_info;
|
||||
#include "input.h"
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include "def.h"
|
||||
#include "idf.h"
|
||||
#include "scope.h"
|
||||
#include <inp_pkg.body>
|
||||
|
||||
|
||||
AtEoIF()
|
||||
{
|
||||
/* Make the unstacking of input streams noticable to the
|
||||
lexical analyzer
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
AtEoIT()
|
||||
{
|
||||
/* Make the end of the text noticable
|
||||
*/
|
||||
return 1;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
/* I N S T A N T I A T I O N O F I N P U T M O D U L E */
|
||||
|
||||
#include "inputtype.h"
|
||||
|
||||
#define INP_NPUSHBACK 2
|
||||
#define INP_TYPE struct f_info
|
||||
#define INP_VAR file_info
|
||||
|
||||
#include <inp_pkg.spec>
|
|
@ -1,77 +0,0 @@
|
|||
/* L O O K U P R O U T I N E S */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "def.h"
|
||||
#include "idf.h"
|
||||
#include "scope.h"
|
||||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
#include "type.h"
|
||||
#include "misc.h"
|
||||
|
||||
struct def *
|
||||
lookup(id, scope, import)
|
||||
register struct idf *id;
|
||||
struct scope *scope;
|
||||
{
|
||||
/* Look up a definition of an identifier in scope "scope".
|
||||
Make the "def" list self-organizing.
|
||||
Return a pointer to its "def" structure if it exists,
|
||||
otherwise return 0.
|
||||
*/
|
||||
register struct def *df, *df1;
|
||||
|
||||
/* Look in the chain of definitions of this "id" for one with scope
|
||||
"scope".
|
||||
*/
|
||||
for (df = id->id_def, df1 = 0;
|
||||
df && df->df_scope != scope;
|
||||
df1 = df, df = df->next) { /* nothing */ }
|
||||
|
||||
if (df) {
|
||||
/* Found it
|
||||
*/
|
||||
if (df1) {
|
||||
/* Put the definition in front
|
||||
*/
|
||||
df1->next = df->next;
|
||||
df->next = id->id_def;
|
||||
id->id_def = df;
|
||||
}
|
||||
if (import && df->df_kind == D_IMPORT) {
|
||||
assert(df->imp_def != 0);
|
||||
return df->imp_def;
|
||||
}
|
||||
}
|
||||
return df;
|
||||
}
|
||||
|
||||
struct def *
|
||||
lookfor(id, vis, give_error)
|
||||
register struct node *id;
|
||||
struct scopelist *vis;
|
||||
{
|
||||
/* Look for an identifier in the visibility range started by "vis".
|
||||
If it is not defined create a dummy definition and,
|
||||
if "give_error" is set, give an error message.
|
||||
*/
|
||||
register struct def *df;
|
||||
register struct scopelist *sc = vis;
|
||||
|
||||
while (sc) {
|
||||
df = lookup(id->nd_IDF, sc->sc_scope, 1);
|
||||
if (df) return df;
|
||||
sc = nextvisible(sc);
|
||||
}
|
||||
|
||||
if (give_error) id_not_declared(id);
|
||||
|
||||
df = MkDef(id->nd_IDF, vis->sc_scope, D_ERROR);
|
||||
df->df_type = error_type;
|
||||
return df;
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
/* M A I N P R O G R A M */
|
||||
|
||||
#include "debug.h"
|
||||
#include "ndir.h"
|
||||
|
||||
#include <system.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "f_info.h"
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
#include "type.h"
|
||||
#include "def.h"
|
||||
#include "scope.h"
|
||||
#include "standards.h"
|
||||
#include "tokenname.h"
|
||||
#include "node.h"
|
||||
#include "warning.h"
|
||||
|
||||
int state; /* either IMPLEMENTATION or PROGRAM */
|
||||
char options[128];
|
||||
int DefinitionModule;
|
||||
char *ProgName;
|
||||
char *DEFPATH[NDIRS+1];
|
||||
struct def *Defined;
|
||||
extern int err_occurred;
|
||||
extern int fp_used; /* set if floating point used */
|
||||
|
||||
extern C_inp(), C_exp();
|
||||
int (*c_inp)() = C_inp;
|
||||
|
||||
main(argc, argv)
|
||||
register char **argv;
|
||||
{
|
||||
register int Nargc = 1;
|
||||
register char **Nargv = &argv[0];
|
||||
|
||||
ProgName = *argv++;
|
||||
warning_classes = W_INITIAL;
|
||||
|
||||
while (--argc > 0) {
|
||||
if (**argv == '-')
|
||||
DoOption((*argv++) + 1);
|
||||
else
|
||||
Nargv[Nargc++] = *argv++;
|
||||
}
|
||||
Nargv[Nargc] = 0; /* terminate the arg vector */
|
||||
if (Nargc < 2) {
|
||||
fprint(STDERR, "%s: Use a file argument\n", ProgName);
|
||||
return 1;
|
||||
}
|
||||
if (options['x']) c_inp = C_exp;
|
||||
return !Compile(Nargv[1], Nargv[2]);
|
||||
}
|
||||
|
||||
Compile(src, dst)
|
||||
char *src, *dst;
|
||||
{
|
||||
extern struct tokenname tkidf[];
|
||||
|
||||
if (! InsertFile(src, (char **) 0, &src)) {
|
||||
fprint(STDERR,"%s: cannot open %s\n", ProgName, src);
|
||||
return 0;
|
||||
}
|
||||
LineNumber = 1;
|
||||
FileName = src;
|
||||
DEFPATH[0] = ".";
|
||||
DEFPATH[NDIRS] = 0;
|
||||
init_idf();
|
||||
InitCst();
|
||||
reserve(tkidf);
|
||||
InitScope();
|
||||
InitTypes();
|
||||
AddStandards();
|
||||
#ifdef DEBUG
|
||||
if (options['l']) {
|
||||
LexScan();
|
||||
return 1;
|
||||
}
|
||||
#endif DEBUG
|
||||
open_scope(OPENSCOPE);
|
||||
GlobalVis = CurrVis;
|
||||
close_scope(0);
|
||||
C_init(word_size, pointer_size);
|
||||
if (! C_open(dst)) fatal("could not open output file");
|
||||
C_magic();
|
||||
C_ms_emx(word_size, pointer_size);
|
||||
CompUnit();
|
||||
C_ms_src((arith) (LineNumber - 1), FileName);
|
||||
if (!err_occurred) {
|
||||
C_exp(Defined->mod_vis->sc_scope->sc_name);
|
||||
WalkModule(Defined);
|
||||
if (fp_used) C_ms_flt();
|
||||
}
|
||||
C_close();
|
||||
#ifdef DEBUG
|
||||
if (options['i']) Info();
|
||||
#endif
|
||||
return ! err_occurred;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
LexScan()
|
||||
{
|
||||
register struct token *tkp = ˙
|
||||
extern char *symbol2str();
|
||||
|
||||
while (LLlex() > 0) {
|
||||
print(">>> %s ", symbol2str(tkp->tk_symb));
|
||||
switch(tkp->tk_symb) {
|
||||
|
||||
case IDENT:
|
||||
print("%s\n", tkp->TOK_IDF->id_text);
|
||||
break;
|
||||
|
||||
case INTEGER:
|
||||
print("%ld\n", tkp->TOK_INT);
|
||||
break;
|
||||
|
||||
case REAL:
|
||||
print("%s\n", tkp->TOK_REL);
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
print("\"%s\"\n", tkp->TOK_STR);
|
||||
break;
|
||||
|
||||
default:
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
AddStandards()
|
||||
{
|
||||
register struct def *df;
|
||||
extern struct def *Enter();
|
||||
static struct node nilnode = { 0, 0, Value, 0, { INTEGER, 0}};
|
||||
|
||||
(void) Enter("ABS", D_PROCEDURE, std_type, S_ABS);
|
||||
(void) Enter("CAP", D_PROCEDURE, std_type, S_CAP);
|
||||
(void) Enter("CHR", D_PROCEDURE, std_type, S_CHR);
|
||||
(void) Enter("FLOAT", D_PROCEDURE, std_type, S_FLOAT);
|
||||
(void) Enter("HIGH", D_PROCEDURE, std_type, S_HIGH);
|
||||
(void) Enter("HALT", D_PROCEDURE, std_type, S_HALT);
|
||||
(void) Enter("EXCL", D_PROCEDURE, std_type, S_EXCL);
|
||||
(void) Enter("DEC", D_PROCEDURE, std_type, S_DEC);
|
||||
(void) Enter("INC", D_PROCEDURE, std_type, S_INC);
|
||||
(void) Enter("VAL", D_PROCEDURE, std_type, S_VAL);
|
||||
(void) Enter("NEW", D_PROCEDURE, std_type, S_NEW);
|
||||
(void) Enter("DISPOSE", D_PROCEDURE, std_type, S_DISPOSE);
|
||||
(void) Enter("TRUNC", D_PROCEDURE, std_type, S_TRUNC);
|
||||
(void) Enter("SIZE", D_PROCEDURE, std_type, S_SIZE);
|
||||
(void) Enter("ORD", D_PROCEDURE, std_type, S_ORD);
|
||||
(void) Enter("ODD", D_PROCEDURE, std_type, S_ODD);
|
||||
(void) Enter("MAX", D_PROCEDURE, std_type, S_MAX);
|
||||
(void) Enter("MIN", D_PROCEDURE, std_type, S_MIN);
|
||||
(void) Enter("INCL", D_PROCEDURE, std_type, S_INCL);
|
||||
|
||||
(void) Enter("CHAR", D_TYPE, char_type, 0);
|
||||
(void) Enter("INTEGER", D_TYPE, int_type, 0);
|
||||
(void) Enter("LONGINT", D_TYPE, longint_type, 0);
|
||||
(void) Enter("REAL", D_TYPE, real_type, 0);
|
||||
(void) Enter("LONGREAL", D_TYPE, longreal_type, 0);
|
||||
(void) Enter("BOOLEAN", D_TYPE, bool_type, 0);
|
||||
(void) Enter("CARDINAL", D_TYPE, card_type, 0);
|
||||
df = Enter("NIL", D_CONST, address_type, 0);
|
||||
df->con_const = &nilnode;
|
||||
nilnode.nd_INT = 0;
|
||||
nilnode.nd_type = address_type;
|
||||
|
||||
(void) Enter("PROC",
|
||||
D_TYPE,
|
||||
construct_type(T_PROCEDURE, NULLTYPE),
|
||||
0);
|
||||
df = Enter("BITSET", D_TYPE, bitset_type, 0);
|
||||
df = Enter("TRUE", D_ENUM, bool_type, 0);
|
||||
df->enm_val = 1;
|
||||
df->enm_next = Enter("FALSE", D_ENUM, bool_type, 0);
|
||||
df = df->enm_next;
|
||||
df->enm_val = 0;
|
||||
df->enm_next = 0;
|
||||
}
|
||||
|
||||
/* How do you like that! Modula-2 in a C-program.
|
||||
*/
|
||||
char SYSTEM[] = "\
|
||||
DEFINITION MODULE SYSTEM;\n\
|
||||
TYPE PROCESS = ADDRESS;\n\
|
||||
PROCEDURE NEWPROCESS(P:PROC; A:ADDRESS; n:CARDINAL; VAR p1:ADDRESS);\n\
|
||||
PROCEDURE TRANSFER(VAR p1,p2:ADDRESS);\n\
|
||||
END SYSTEM.\n";
|
||||
|
||||
do_SYSTEM()
|
||||
{
|
||||
/* Simulate the reading of the SYSTEM definition module
|
||||
*/
|
||||
open_scope(CLOSEDSCOPE);
|
||||
(void) Enter("WORD", D_TYPE, word_type, 0);
|
||||
(void) Enter("BYTE", D_TYPE, byte_type, 0);
|
||||
(void) Enter("ADDRESS", D_TYPE, address_type, 0);
|
||||
(void) Enter("ADR", D_PROCEDURE, std_type, S_ADR);
|
||||
(void) Enter("TSIZE", D_PROCEDURE, std_type, S_TSIZE);
|
||||
if (!InsertText(SYSTEM, sizeof(SYSTEM) - 1)) {
|
||||
fatal("could not insert text");
|
||||
}
|
||||
DefModule();
|
||||
close_scope(SC_CHKFORW);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
int cntlines;
|
||||
|
||||
Info()
|
||||
{
|
||||
extern int cnt_def, cnt_node, cnt_paramlist, cnt_type,
|
||||
cnt_switch_hdr, cnt_case_entry,
|
||||
cnt_scope, cnt_scopelist, cnt_tmpvar;
|
||||
|
||||
print("\
|
||||
%6d def\n%6d node\n%6d paramlist\n%6d type\n%6d switch_hdr\n\
|
||||
%6d case_entry\n%6d scope\n%6d scopelist\n%6d tmpvar\n",
|
||||
cnt_def, cnt_node, cnt_paramlist, cnt_type,
|
||||
cnt_switch_hdr, cnt_case_entry,
|
||||
cnt_scope, cnt_scopelist, cnt_tmpvar);
|
||||
print("\nNumber of lines read: %d\n", cntlines);
|
||||
}
|
||||
#endif
|
|
@ -1,15 +0,0 @@
|
|||
/* S O M E G L O B A L V A R I A B L E S */
|
||||
|
||||
extern char options[]; /* indicating which options were given */
|
||||
|
||||
extern int DefinitionModule;
|
||||
/* flag indicating that we are reading a definition
|
||||
module
|
||||
*/
|
||||
|
||||
extern struct def *Defined;
|
||||
/* definition structure of module defined in this
|
||||
compilation
|
||||
*/
|
||||
extern char *DEFPATH[]; /* search path for DEFINITION MODULE's */
|
||||
extern int state; /* either IMPLEMENTATION or PROGRAM */
|
|
@ -1,26 +0,0 @@
|
|||
sed -e '
|
||||
s:^.*[ ]ALLOCDEF[ ].*"\(.*\)"[ ]*\([0-9][0-9]*\).*$:\
|
||||
/* allocation definitions of struct \1 */\
|
||||
extern char *st_alloc();\
|
||||
extern struct \1 *h_\1;\
|
||||
#ifdef DEBUG\
|
||||
extern int cnt_\1;\
|
||||
extern char *std_alloc();\
|
||||
#define new_\1() ((struct \1 *) std_alloc((char **)\&h_\1, sizeof(struct \1), \2, \&cnt_\1))\
|
||||
#else\
|
||||
#define new_\1() ((struct \1 *) st_alloc((char **)\&h_\1, sizeof(struct \1), \2))\
|
||||
#endif\
|
||||
#define free_\1(p) st_free(p, h_\1, sizeof(struct \1))\
|
||||
:' -e '
|
||||
s:^.*[ ]STATICALLOCDEF[ ].*"\(.*\)"[ ]*\([0-9][0-9]*\).*$:\
|
||||
/* allocation definitions of struct \1 */\
|
||||
extern char *st_alloc();\
|
||||
struct \1 *h_\1;\
|
||||
#ifdef DEBUG\
|
||||
int cnt_\1;\
|
||||
#define new_\1() ((struct \1 *) std_alloc((char **)\&h_\1, sizeof(struct \1), \2, \&cnt_\1))\
|
||||
#else\
|
||||
#define new_\1() ((struct \1 *) st_alloc((char **)\&h_\1, sizeof(struct \1), \2))\
|
||||
#endif\
|
||||
#define free_\1(p) st_free(p, h_\1, sizeof(struct \1))\
|
||||
:'
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue