Initial commit from latest tar.gz file
This commit is contained in:
commit
dfbf66ea39
3
INSTALL
Normal file
3
INSTALL
Normal file
@ -0,0 +1,3 @@
|
||||
Quick install: type "./configure && make -j && sudo make install".
|
||||
|
||||
More information is available in "doc/building.html".
|
||||
37
Makefile
Normal file
37
Makefile
Normal file
@ -0,0 +1,37 @@
|
||||
SUBSYSTEMS = tools bin h pch gtc ti68k
|
||||
INSTALLABLE_SUBSYSTEMS = h pch gtc
|
||||
all: $(addprefix all-,$(SUBSYSTEMS))
|
||||
@echo 1>&2
|
||||
@echo 1>&2 '-- Compilation successful!'
|
||||
@echo 1>&2 ' You may use the calculator binaries now (e.g. for the TI-89 in ti68k/bin-89).'
|
||||
@echo 1>&2 ' Or if you want to go ahead and install the cross-compiler, just type "make install".'
|
||||
@echo 1>&2
|
||||
install: $(addprefix all-,$(SUBSYSTEMS)) $(addprefix install-,$(INSTALLABLE_SUBSYSTEMS))
|
||||
@echo 1>&2
|
||||
@echo 1>&2 '-- Cross-compiler install successful!'
|
||||
@echo 1>&2 ' You should now be able to compile by typing "gtc myprogram.c".'
|
||||
@echo 1>&2 ' Remember that the calculator binaries are available, e.g. for the TI-89 in ti68k/bin-89.'
|
||||
@echo 1>&2
|
||||
clean: $(addprefix clean-,$(SUBSYSTEMS))
|
||||
distclean: $(addprefix distclean-,$(SUBSYSTEMS))
|
||||
scratchclean: $(addprefix scratchclean-,$(SUBSYSTEMS))
|
||||
distclean scratchclean:
|
||||
$(RM) config.mk
|
||||
|
||||
all-bin: all-tools
|
||||
all-h: all-bin
|
||||
all-pch: all-bin
|
||||
all-gtc: all-bin
|
||||
all-ti68k: all-bin all-h all-pch
|
||||
$(addprefix install-,$(INSTALLABLE_SUBSYSTEMS)): $(addprefix all-,$(INSTALLABLE_SUBSYSTEMS))
|
||||
|
||||
all-%:
|
||||
$(MAKE) -C $(patsubst all-%,%,$@) all
|
||||
install-%:
|
||||
$(MAKE) -C $(patsubst install-%,%,$@) install
|
||||
clean-%:
|
||||
$(MAKE) -C $(patsubst clean-%,%,$@) clean
|
||||
distclean-%:
|
||||
$(MAKE) -C $(patsubst distclean-%,%,$@) distclean
|
||||
scratchclean-%:
|
||||
$(MAKE) -C $(patsubst scratchclean-%,%,$@) scratchclean
|
||||
20
bin/Makefile
Normal file
20
bin/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
include ../platform.mk
|
||||
vpath ../tools
|
||||
|
||||
PROGRAMS = obj2ti$(BIN_SUFFIX) pchmaker$(BIN_SUFFIX) txt89t$(BIN_SUFFIX) dat89y$(BIN_SUFFIX)
|
||||
|
||||
all: $(PROGRAMS)
|
||||
|
||||
clean:
|
||||
distclean:
|
||||
$(RM) $(PROGRAMS)
|
||||
scratchclean: distclean
|
||||
|
||||
obj2ti$(BIN_SUFFIX): ../tools/obj2ti/obj2ti$(BIN_SUFFIX)
|
||||
cp $< $@
|
||||
pchmaker$(BIN_SUFFIX): ../tools/pchmaker/pchmaker$(BIN_SUFFIX)
|
||||
cp $< $@
|
||||
txt89t$(BIN_SUFFIX): ../tools/txt89t/txt89t$(BIN_SUFFIX)
|
||||
cp $< $@
|
||||
dat89y$(BIN_SUFFIX): ../tools/dat89y/dat89y$(BIN_SUFFIX)
|
||||
cp $< $@
|
||||
13
common-gtc.mk
Normal file
13
common-gtc.mk
Normal file
@ -0,0 +1,13 @@
|
||||
# This Makefile is used for source codes that depend on the GTC code tree.
|
||||
# It is expected that the current working directory is of the form src/xxx/yyy.
|
||||
#
|
||||
# Note that GTC itself may need more C defines to be compiled, but they will
|
||||
# only be required in .c files, not .h files, so they are not defined here.
|
||||
|
||||
include ../../common.mk
|
||||
include ../../config.mk
|
||||
|
||||
GTC_SOURCE = ../../gtc/src
|
||||
GTC_HEADERS = $(GTC_SOURCE)/*.h
|
||||
|
||||
CFLAGS = $(DEFAULT_CFLAGS) -I$(GTC_SOURCE) $(GTC_ARCH_DEFINES)
|
||||
11
common.mk
Normal file
11
common.mk
Normal file
@ -0,0 +1,11 @@
|
||||
# This Makefile is used for all source codes that must build binaries.
|
||||
|
||||
DEFAULT_CFLAGS = -O2 -s
|
||||
|
||||
ifndef CC
|
||||
ifeq (,$(shell which gcc 2>&1 >/dev/null))
|
||||
CC=gcc
|
||||
else
|
||||
CC=cc
|
||||
endif
|
||||
endif
|
||||
20
configure
vendored
Executable file
20
configure
vendored
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
rm -f config.mk
|
||||
touch config.mk
|
||||
if [ "x$1" = "x--prefix" ]; then
|
||||
if test -z "$2"; then
|
||||
echo "missing argument to $1" 1>&2; exit 1
|
||||
fi
|
||||
echo "using prefix $2..."
|
||||
echo "prefix=$2" >> config.mk
|
||||
shift 2
|
||||
else
|
||||
deflt_prefix=/usr/local
|
||||
echo "using default prefix $deflt_prefix..."
|
||||
echo "prefix=$deflt_prefix" >> config.mk
|
||||
fi
|
||||
if test "$1"; then
|
||||
echo "error: too many arguments" 1>&2; exit 1
|
||||
fi
|
||||
echo "GTC_ARCH_DEFINES = -DNDEBUG -DMC68000 -DCPU_DEFINED -DPC -DUNIXOID -DAS -DASM -DPCH -DREGPARM -DBCDFLT -DNOFLOAT -DVCG" >> config.mk
|
||||
echo configuration OK ! 1>&2
|
||||
55
doc/building.html
Normal file
55
doc/building.html
Normal file
@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>Building GTC - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>Building GTC</h1>
|
||||
<p>If you use Windows or TI calculators you don't need to build GTC yourself as
|
||||
there are already precompiled versions available.</p>
|
||||
<p>If you use Unix-like operating systems (Linux, Mac OS X...) you will have to
|
||||
follow these instructions to build GTC yourself.</p>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#Building.the.binaries'>Building the binaries</a></li>
|
||||
<li><a href='#Rebuilding.a.modified.GTC'>Rebuilding a modified GTC</a></li>
|
||||
<li><a href='#Notes.for.developers'>Notes for developers</a></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Building.the.binaries'></a>Building the binaries</h1><div class='c1in'><hr class='hr1in' />
|
||||
<p>You should need no special package apart from GNU make and a C/C++ compiler to
|
||||
build GTC. On Windows you will need Cygwin.</p>
|
||||
<p>Just type</p>
|
||||
<p><code>./configure && make && sudo make install</code></p>
|
||||
<p>(replace<span class='widespace'> </span><code>make</code><span class='widespace'> </span>with<span class='widespace'> </span><code>make -j</code><span class='widespace'> </span>to take advantage of multiprocessor systems).</p>
|
||||
<p>By default GTC will be installed in<span class='widespace'> </span><code>/usr/local</code>. If you want to install it in
|
||||
a different directory (for example if you don't have administrator rights), use
|
||||
the following command:</p>
|
||||
<p><code>./configure --prefix $HOME/my_directory && make install</code></p>
|
||||
</div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Rebuilding.a.modified.GTC'></a>Rebuilding a modified GTC</h1><div class='c1in'><hr class='hr1in' />
|
||||
<p>The above instructions are designed to only recompile platform-dependent files
|
||||
and as such have minimal dependencies.</p>
|
||||
<p>If you want to modify precompiled data such as the precompiled headers you will
|
||||
need extra packages like Perl and possibly Ruby.</p>
|
||||
</div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Notes.for.developers'></a>Notes for developers</h1><div class='c1in'><hr class='hr1in' />
|
||||
<p>The Makefiles follow these conventions:</p>
|
||||
<ul><li><span class='widespace'> </span><code>make clean</code><span class='widespace'> </span>cleans up intermediary files, but not final files.
|
||||
</li><li><span class='widespace'> </span><code>make distclean</code><span class='widespace'> </span>cleans up intermediary files and any platform-dependent
|
||||
files.
|
||||
</li><li><span class='widespace'> </span><code>make scratchclean</code><span class='widespace'> </span>cleans up everything that can be rebuilt. Note: use
|
||||
with care, as if you don't have the right tools installed you are not going
|
||||
to be able to rebuild GTC.
|
||||
</li></ul>
|
||||
<p>All Makefiles are designed to be safely used with parallel compilation.
|
||||
</div></div></p></div>
|
||||
</body>
|
||||
</html>
|
||||
118
doc/cmdline.html
Normal file
118
doc/cmdline.html
Normal file
@ -0,0 +1,118 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>GTC Command-line options - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>GTC Command-line options</h1>
|
||||
<p>The computer version of GTC has a number of options available on the command-line. They are all listed here.</p>
|
||||
<p>Please note that currently, these options are not available for the FlashApp version.</p>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#Basic.usage'>Basic usage</a>
|
||||
<ul>
|
||||
<li><a href='#Invocation'>Invocation</a></li>
|
||||
<li><a href='#Adding.options'>Adding options</a></li>
|
||||
</ul></li>
|
||||
<li><a href='#List.of.all.options'>List of all options</a>
|
||||
<ul>
|
||||
<li><a href='#Options.affecting.output'>Options affecting output</a>
|
||||
<ul>
|
||||
<li><a href='#-o.switch'>-o switch</a></li>
|
||||
<li><a href='#--folder.switch'>--folder switch</a></li>
|
||||
<li><a href='#--output.switch'>--output switch</a></li>
|
||||
</ul></li>
|
||||
<li><a href='#Preprocessor.options'>Preprocessor options</a>
|
||||
<ul>
|
||||
<li><a href='#-I.switch'>-I switch</a></li>
|
||||
<li><a href='#-D.switch'>-D switch</a></li>
|
||||
</ul></li>
|
||||
<li><a href='#Optimization.options'>Optimization options</a>
|
||||
<ul>
|
||||
<li><a href='#-exe.switch'>-exe switch</a></li>
|
||||
<li><a href='#-mno-bss.switch'>-mno-bss switch</a></li>
|
||||
</ul></li>
|
||||
<li><a href='#Other.options'>Other options</a>
|
||||
<ul>
|
||||
<li><a href='#--.separator'>-- separator</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Basic.usage'></a>Basic usage</h1><div class='c1in'><hr class='hr1in' /><div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Invocation'></a>Invocation</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>To compile a file named<span class='widespace'> </span><code>hello.c</code>, open a command-line prompt in the folder where<span class='widespace'> </span><code>hello.c</code><span class='widespace'> </span>is stored, and type:</p>
|
||||
<pre>
|
||||
gtc hello.c
|
||||
</pre>
|
||||
<p>This will create files named<span class='widespace'> </span><code>hello.89z</code>,<span class='widespace'> </span><code>hello.9xz</code><span class='widespace'> </span>and<span class='widespace'> </span><code>hello.v2z</code><span class='widespace'> </span>(or only some of those, if your program is specific to a calculator model). You can now run them after sending them to your calculator or to an emulator.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Adding.options'></a>Adding options</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>You can modify the behaviour of GTC with command-line options (or command-line <em>switches</em>). Their position on the command-line does not matter. For example, if you want to use the<span class='widespace'> </span><a href='cmdline.html#-o.switch'><code>-o</code><span class='widespace'> </span>switch</a> to create files named<span class='widespace'> </span><code>somename.89z</code>,<span class='widespace'> </span><code>somename.9xz</code><span class='widespace'> </span>and<span class='widespace'> </span><code>somename.v2z</code>, you can type:</p>
|
||||
<pre>
|
||||
gtc hello.c -o somename
|
||||
</pre>
|
||||
<p>Or, equivalently:</p>
|
||||
<pre>
|
||||
gtc -o somename hello.c
|
||||
</pre>
|
||||
<p>See below for a complete list of options.</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='List.of.all.options'></a>List of all options</h1><div class='c1in'><hr class='hr1in' /><div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Options.affecting.output'></a>Options affecting output</h2><div class='c2in'><hr class='hr2in' /><div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='-o.switch'></a><code>-o</code><span class='widespace'> </span>switch</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>By default,<span class='widespace'> </span><code>gtc hello.c foo.c bar.c</code><span class='widespace'> </span>results in an executable named<span class='widespace'> </span><code>hello.89z</code><span class='widespace'> </span>or<span class='widespace'> </span><code>hello.v2z</code>. You can specify other names with this switch, for example<span class='widespace'> </span><code>gtc hello.c foo.c bar.c -o somename</code><span class='widespace'> </span>will instead create an executable named<span class='widespace'> </span><code>somename.89z</code><span class='widespace'> </span>or<span class='widespace'> </span><code>somename.v2z</code>.</p>
|
||||
</div></div>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='--folder.switch'></a><code>--folder</code><span class='widespace'> </span>switch</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>By default, calculator executables are stored in the<span class='widespace'> </span><code>main</code><span class='widespace'> </span>folder. You can store them in the folder<span class='widespace'> </span><code>somefold</code><span class='widespace'> </span>with the switch<span class='widespace'> </span><code>--folder=somefold</code>.</p>
|
||||
</div></div>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='--output.switch'></a><code>--output</code><span class='widespace'> </span>switch</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>By default,<span class='widespace'> </span><code>gtc hello.c -o somename</code><span class='widespace'> </span>results in an executable named<span class='widespace'> </span><code>somename.89z</code>; the name of the program on the calculator will thus be<span class='widespace'> </span><code>somename()</code>. You can change this with the switch<span class='widespace'> </span><code>--output=myprog</code>:<span class='widespace'> </span><code>gtc hello.c -o somename --output=myprog</code><span class='widespace'> </span>creates an executable named<span class='widespace'> </span><code>somename.89z</code><span class='widespace'> </span>containing a program whose name on the calculator will be<span class='widespace'> </span><code>myprog()</code>.</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Preprocessor.options'></a>Preprocessor options</h2><div class='c2in'><hr class='hr2in' /><div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='-I.switch'></a><code>-I</code><span class='widespace'> </span>switch</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>The<span class='widespace'> </span><code>-I folder</code><span class='widespace'> </span>(or<span class='widespace'> </span><code>-Ifolder</code>) switch tells GTC to look for include files not only in the current directory, but also in the folder<span class='widespace'> </span><code>folder</code>.
|
||||
You can use this switch several times to include several folders.</p>
|
||||
</div></div>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='-D.switch'></a><code>-D</code><span class='widespace'> </span>switch</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>The<span class='widespace'> </span><code>-D SYMBOL</code><span class='widespace'> </span>(or<span class='widespace'> </span><code>-DSYMBOL</code>) switch tells GTC to<span class='widespace'> </span><a href='preprocessor.html#.23define'><code>#define</code></a><span class='widespace'> </span>the symbol<span class='widespace'> </span><code>SYMBOL</code>, with no specific value.
|
||||
The<span class='widespace'> </span><code>-D SYMBOL=value</code><span class='widespace'> </span>(or<span class='widespace'> </span><code>-DSYMBOL=value</code>) switch tells GTC to<span class='widespace'> </span><a href='preprocessor.html#.23define'><code>#define</code></a><span class='widespace'> </span>the symbol<span class='widespace'> </span><code>SYMBOL</code>, with the value<span class='widespace'> </span><code>value</code>.
|
||||
You can use this switch several times to define several symbols.</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Optimization.options'></a>Optimization options</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>It is in the philosophy of GTC to have default options as sensible as possible, so optimization options are kept to a bare minimum. Furthermore, optimizations are <em>always</em> enabled.</p>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='-exe.switch'></a><code>-exe</code><span class='widespace'> </span>switch</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>This switch will make your program much smaller and very slightly faster, at the expense of a short loading time (usually less than half a second). However note that because it adds an unpacker to your program, it will make very small programs (less than 3-4 kilobytes) larger, so it should not be used in this case. It has the same effect as defining the<span class='widespace'> </span><a href='missing.html' class='invalidlink'><code>EXE_OUT</code></a><span class='widespace'> </span>preprocessor symbol.</p>
|
||||
<p>It can be an interesting way to work around <a href='glossary.html#AMS'>AMS</a>'s <a href='missing.html' class='invalidlink'>program size limit</a> for <a href='glossary.html#AMS'>AMS</a> version 2.0x, because a program that exceeds the size limit when uncompressed can be compressed to a size below the limit.</p>
|
||||
</div></div>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='-mno-bss.switch'></a><code>-mno-bss</code><span class='widespace'> </span>switch</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>This switch disables the creation of BSS sections. In some cases it has absolutely no effect, in other cases it will either make the program faster and smaller, or make it much larger (if you are using large global arrays).</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Other.options'></a>Other options</h2><div class='c2in'><hr class='hr2in' /><div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='--.separator'></a><code>--</code><span class='widespace'> </span>separator</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>Not an option <em>per se</em>, but a way to indicate that all arguments after<span class='widespace'> </span><code>--</code><span class='widespace'> </span>are really filenames and not command-line switches.
|
||||
For example<span class='widespace'> </span><code>gtc -DHELLO hello.c -- foo.c -file-with-dashes-.c</code><span class='widespace'> </span>will compile the 3 files<span class='widespace'> </span><code>hello.c</code>,<span class='widespace'> </span><code>foo.c</code><span class='widespace'> </span>and<span class='widespace'> </span><code>-file-with-dashes-.c</code>, with the single option<span class='widespace'> </span><code>-DHELLO</code>. Without<span class='widespace'> </span><code>--</code><span class='widespace'> </span>the file<span class='widespace'> </span><code>-file-with-dashes-.c</code><span class='widespace'> </span>would have been understood as an (invalid) command-line option.
|
||||
</div></div>
|
||||
</div></div>
|
||||
</div></div></p></div>
|
||||
</body>
|
||||
</html>
|
||||
83
doc/credits.html
Normal file
83
doc/credits.html
Normal file
@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>Information - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>Information</h1>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#Credits.and.licensing'>Credits and licensing</a>
|
||||
<ul>
|
||||
<li><a href='#Standard.library'>Standard library</a></li>
|
||||
<li><a href='#Compiler.core'>Compiler core</a></li>
|
||||
<li><a href='#Compression.routines'>Compression routines</a></li>
|
||||
<li><a href='#Object.file.import'>Object file import</a></li>
|
||||
<li><a href='#Thanks'>Thanks</a></li>
|
||||
</ul></li>
|
||||
<li><a href='#Contact'>Contact</a></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Credits.and.licensing'></a>Credits and licensing</h1><div class='c1in'><hr class='hr1in' />
|
||||
<p>GTC is composed of three separate parts: the GTC compiler, the GTC IDE and the
|
||||
GTC standard library. You are free to use these parts separately or in
|
||||
combination.</p>
|
||||
<p>You can redistribute or modify GTC freely for non-commercial use, as long as
|
||||
you also redistribute the modified source and comply with the licenses of the
|
||||
components you choose to distribute: you cannot redistribute the GTC standard
|
||||
library if you fail to comply with the terms of the <a href='license-gpl2.html#GNU.General.Public.License'>GNU General Public
|
||||
License</a>, version 2 (GPL). In addition you may redistribute the GTC standard
|
||||
library under the terms of the GPL license, without restriction on commercial
|
||||
use.</p>
|
||||
<p>Excluding the standard library, the main author of GTC is Paul Froissart,
|
||||
however GTC would not have been possible without building upon the work of
|
||||
the following contributors.</p>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Standard.library'></a>Standard library</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>The GTC standard library is a simple recompilation of old versions of the TIGCC
|
||||
library, adapted for usage of a different calling convention. As such it is
|
||||
licensed under the terms of the <a href='license-gpl2.html#GNU.General.Public.License'>GNU General Public License</a>, with an
|
||||
exception allowing linking of the library with external programs, and
|
||||
redistribution of the linked programs notwithstanding the provisions of the
|
||||
GPL.</p>
|
||||
<p>The TIGCC library was written by Zeljko Juric, Thomas Nussbaumer, Sebastian
|
||||
Reichelt, Kevin Kofler and other contributors to the
|
||||
<a href='http://tigcc.ticalc.org/'> TIGCC project</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Compiler.core'></a>Compiler core</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>The GTC compiler is based on the 68000 and i386 C compiler III.1 by Christoph
|
||||
van Wuellen (1989-1991), itself based on the 68000 compiler by Matthew Brandt
|
||||
(1984-1986).</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Compression.routines'></a>Compression routines</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>The<span class='widespace'> </span><code>-exe</code><span class='widespace'> </span>mode is based on the PuCrunch algorithm written by Pasi <em>Albert</em> Ojala, and adapted for use on TI calculators by Thomas Nussbaumer.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Object.file.import'></a>Object file import</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>The code to import<span class='widespace'> </span><code>.o</code><span class='widespace'> </span>files is based on<span class='widespace'> </span><code>obj2ti</code><span class='widespace'> </span>written by Julien Muchembled and further modified by Sebastian Reichelt and Kevin Kofler.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Thanks'></a>Thanks</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>Some people provided significant help without contributing code to the project.</p>
|
||||
<p>Thanks to Olivier Armand for his FlashAppy patch: since TI has stopped signing
|
||||
Flash applications this is absolutely vital to GTC.</p>
|
||||
<p>Thanks to vince from the Ti-Fr team for his generous hosting.</p>
|
||||
<p>Thanks to all the testers who helped uncover bugs.</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Contact'></a>Contact</h1><div class='c1in'><hr class='hr1in' />
|
||||
<p>You will find the latest versions and online documentation on the GTC website:</p>
|
||||
<p><a href='http://gtc.ti-fr.com/'> http://gtc.ti-fr.com/</a></p>
|
||||
<p>Please use the <a href='http://gtc.ti-fr.com/feedback/'> feedback form</a> to submit bugs or
|
||||
comments.
|
||||
</div></div></p></div>
|
||||
</body>
|
||||
</html>
|
||||
14
doc/examples.html
Normal file
14
doc/examples.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>GTC examples - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>GTC examples</h1>
|
||||
<p>You will find</p></div>
|
||||
</body>
|
||||
</html>
|
||||
352
doc/extensions.html
Normal file
352
doc/extensions.html
Normal file
@ -0,0 +1,352 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>GTC Extensions - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>GTC Extensions</h1>
|
||||
<p>GTC supports a number of extensions, designed to take advantage of the TI platform, or simply to maintain compatibility with existing programs.</p>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#GNU.extensions'>GNU extensions</a>
|
||||
<ul>
|
||||
<li><a href='#Statements.and.Declarations.in.Expressions'>Statements and Declarations in Expressions</a></li>
|
||||
<li><a href='#Referring.to.a.Type.with.typeof'>Referring to a Type with typeof</a></li>
|
||||
<li><a href='#Generalized.Lvalues'>Generalized Lvalues</a></li>
|
||||
<li><a href='#Conditionals.with.Omitted.Operands'>Conditionals with Omitted Operands</a></li>
|
||||
<li><a href='#Binary.Numbers'>Binary Numbers</a></li>
|
||||
<li><a href='#Structures.With.No.Members'>Structures With No Members</a></li>
|
||||
<li><a href='#Arrays.of.Length.Zero'>Arrays of Length Zero</a></li>
|
||||
<li><a href='#Macros.with.a.Variable.Number.of.Arguments'>Macros with a Variable Number of Arguments</a></li>
|
||||
<li><a href='#Arithmetic.on.void.and.Function.Pointers'>Arithmetic on void and Function Pointers</a></li>
|
||||
<li><a href='#Non-Constant.Initializers'>Non-Constant Initializers</a></li>
|
||||
<li><a href='#Compound.Literals..28Cast.Constructors.29'>Compound Literals (Cast Constructors)</a></li>
|
||||
<li><a href='#Designated.Initializers'>Designated Initializers</a></li>
|
||||
<li><a href='#Case.Ranges'>Case Ranges</a></li>
|
||||
<li><a href='#Specifying.Attributes.of.Functions'>Specifying Attributes of Functions</a></li>
|
||||
<li><a href='#C.2b.2b.Style.Comments'>C++ Style Comments</a></li>
|
||||
<li><a href='#Dollar.Signs.in.Identifier.Names'>Dollar Signs in Identifier Names</a></li>
|
||||
<li><a href='#Escape.Character.in.Constants'>Escape Character in Constants</a></li>
|
||||
<li><a href='#Alternate.Keywords'>Alternate Keywords</a></li>
|
||||
<li><a href='#__builtin_constant_p'>__builtin_constant_p</a></li>
|
||||
<li><a href='#Mixed.Declarations.and.Code'>Mixed Declarations and Code</a></li>
|
||||
<li><a href='#Unnamed.struct.2funion.Fields.within.structs.2funions'>Unnamed struct/union Fields within structs/unions</a></li>
|
||||
</ul></li>
|
||||
<li><a href='#GTC-specific.extensions'>GTC-specific extensions</a>
|
||||
<ul>
|
||||
<li><a href='#incbin.directive'>incbin directive</a>
|
||||
<ul>
|
||||
<li><a href='#Using.incbin.to.declare.a.C.array'>Using incbin to declare a C array</a></li>
|
||||
<li><a href='#Using.incbin.within.an.asm.7b.7d.statement'>Using incbin within an asm{} statement</a></li>
|
||||
</ul></li>
|
||||
<li><a href='#asm.7b.7d.statement'>asm{} statement</a>
|
||||
<ul>
|
||||
<li><a href='#Inserting.an.asm.7b.7d.statement.in.the.code'>Inserting an asm{} statement in the code</a>
|
||||
<ul>
|
||||
<li><a href='#Global.asm.7b.7d.statements'>Global asm{} statements</a></li>
|
||||
<li><a href='#Inline.asm.7b.7d.statements'>Inline asm{} statements</a></li>
|
||||
</ul></li>
|
||||
<li><a href='#Structure.of.an.asm.7b.7d.statement'>Structure of an asm{} statement</a></li>
|
||||
<li><a href='#asm.7b.7d.interpretation.rules'>asm{} interpretation rules</a></li>
|
||||
<li><a href='#Extra.features.of.asm.7b.7d.statements'>Extra features of asm{} statements</a></li>
|
||||
<li><a href='#asm.7b.7d.special.operator.3a.__c__'>asm{} special operator: __c__</a></li>
|
||||
</ul></li>
|
||||
<li><a href='#.40.40.prefix'>@@ prefix</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='GNU.extensions'></a>GNU extensions</h1><div class='c1in'><hr class='hr1in' /><div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Statements.and.Declarations.in.Expressions'></a>Statements and Declarations in Expressions</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC63'> Statements and Declarations in Expressions</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Referring.to.a.Type.with.typeof'></a>Referring to a Type with <em>typeof</em></h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC69'> Referring to a Type with <em>typeof</em></a></p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Generalized.Lvalues'></a>Generalized Lvalues</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC70'> Generalized Lvalues</a>.</p>
|
||||
<p>Note however that weird constructs like<span class='widespace'> </span><code>(a,b)+=5</code><span class='widespace'> </span>are rejected by GTC -- commas are not considered legal lvalues.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Conditionals.with.Omitted.Operands'></a>Conditionals with Omitted Operands</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC71'> Conditionals with Omitted Operands</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Binary.Numbers'></a>Binary Numbers</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC110'> Binary Numbers</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Structures.With.No.Members'></a>Structures With No Members</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC111'> Structures With No Members</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Arrays.of.Length.Zero'></a>Arrays of Length Zero</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC75'> Arrays of Length Zero</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Macros.with.a.Variable.Number.of.Arguments'></a>Macros with a Variable Number of Arguments</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC77'> Macros with a Variable Number of Arguments</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Arithmetic.on.void.and.Function.Pointers'></a>Arithmetic on void and Function Pointers</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC79'> Arithmetic on void and Function Pointers</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Non-Constant.Initializers'></a>Non-Constant Initializers</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC80'> Non-Constant Initializers</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Compound.Literals..28Cast.Constructors.29'></a>Compound Literals (Cast Constructors)</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC81'> Compound Literals (Cast Constructors)</a>. There is some difference in the handling of static storage duration though, see <a href='faq.html#Differences.between.GTC.and.TIGCC'>Differences between GTC and TIGCC</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Designated.Initializers'></a>Designated Initializers</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC82'> Designated Initializers</a>, but in GTC this only works for array types.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Case.Ranges'></a>Case Ranges</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC83'> Case Ranges</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Specifying.Attributes.of.Functions'></a>Specifying Attributes of Functions</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC85'> Specifying Attributes of Functions</a>, however not all of the specifiers are meaningful in GTC.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='C.2b.2b.Style.Comments'></a>C++ Style Comments</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC87'> C++ Style Comments</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Dollar.Signs.in.Identifier.Names'></a>Dollar Signs in Identifier Names</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC88'> Dollar Signs in Identifier Names</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Escape.Character.in.Constants'></a>Escape Character in Constants</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC89'> Escape Character in Constants</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Alternate.Keywords'></a>Alternate Keywords</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC100'> Alternate Keywords</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='__builtin_constant_p'></a><a href='extensions.html#__builtin_constant_p'><code>__builtin_constant_p</code></a></h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC104___builtin_constant_p'> __builtin_constant_p</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Mixed.Declarations.and.Code'></a>Mixed Declarations and Code</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC107'> Mixed Declarations and Code</a>.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Unnamed.struct.2funion.Fields.within.structs.2funions'></a>Unnamed struct/union Fields within structs/unions</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>See <a href='http://tigcc.ticalc.org/doc/gnuexts.html#SEC108'> Unnamed struct/union Fields within structs/unions</a>.</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='GTC-specific.extensions'></a>GTC-specific extensions</h1><div class='c1in'><hr class='hr1in' /><div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='incbin.directive'></a><a href='extensions.html#incbin.directive'><code>incbin</code></a><span class='widespace'> </span>directive</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>It is sometimes convenient to include binary files directly into your program, for example when using sprites. The<span class='widespace'> </span><a href='extensions.html#incbin.directive'><code>incbin</code></a><span class='widespace'> </span>directives allows you to do just that, without having to convert your data to a decimal or hexadecimal header (which can be memory-consuming on a TI).</p>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='Using.incbin.to.declare.a.C.array'></a>Using<span class='widespace'> </span><a href='extensions.html#incbin.directive'><code>incbin</code></a><span class='widespace'> </span>to declare a C array</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>You can use<span class='widespace'> </span><a href='extensions.html#incbin.directive'><code>incbin</code></a><span class='widespace'> </span>to initialize the contents of a C array:</p>
|
||||
<pre>
|
||||
// The following declares a sprite using normal C initializers
|
||||
short sprite1[] = {
|
||||
0xFFFF, 0x8008, 0x8008, 0xFFFF,
|
||||
0xFF00, 0x8800, 0x8800, 0x8800,
|
||||
0x00FF, 0x0088, 0x0088, 0x0088,
|
||||
0xFFFF, 0x8008, 0x8008, 0xFFFF,
|
||||
};
|
||||
|
||||
// The following declares a sprite using <a href='extensions.html#incbin.directive'><code>incbin</code></a>,
|
||||
// reading the contents from the file <em>sprite.bin</em>
|
||||
short sprite2[] = incbin "sprite.bin";
|
||||
</pre>
|
||||
<p>The first declaration creates an array of 16 shorts containing the hexadecimal numbers provided.
|
||||
The second declaration creates an array of 16 shorts whose representation in memory will be the same as<span class='widespace'> </span><code>sprite.bin</code>.</p>
|
||||
<p>Note that for the sake of portability,<span class='widespace'> </span><a href='http://tigcc.ticalc.org/doc/default.html#import_binary'><code>import_binary</code></a><span class='widespace'> </span>can be a useful
|
||||
alternative, although there are several caveats: you will have to manually
|
||||
declare the size of the array if<span class='widespace'> </span><code>sizeof</code><span class='widespace'> </span>is to be used, and you cannot use it
|
||||
to declare a static array inside a function.</p>
|
||||
</div></div>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='Using.incbin.within.an.asm.7b.7d.statement'></a>Using<span class='widespace'> </span><a href='extensions.html#incbin.directive'><code>incbin</code></a><span class='widespace'> </span>within an<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statement</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>Like in <a href='glossary.html#a68k'>a68k</a>, you can also use<span class='widespace'> </span><a href='extensions.html#incbin.directive'><code>incbin</code></a><span class='widespace'> </span>inside an<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statement to insert binary data.</p>
|
||||
<pre>
|
||||
asm {
|
||||
// Insert the values 1,2,3,4 after <code>label1</code>
|
||||
label1:
|
||||
dc.w 1,2
|
||||
dc.w 3,4
|
||||
// Insert the content of <code>sprite.bin</code> after <code>label2</code>
|
||||
label2:
|
||||
incbin "sprite.bin"
|
||||
};
|
||||
</pre></div></div>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='asm.7b.7d.statement'></a><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statement</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>GTC allows you to program in <a href='glossary.html#Assembly'>assembly</a>, with a syntax very close to that of <a href='glossary.html#a68k'>a68k</a>. In fact, it is powerful enough to write full assembly programs using only GTC!</p>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='Inserting.an.asm.7b.7d.statement.in.the.code'></a>Inserting an<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statement in the code</h3><div class='c3in'><hr class='hr3in' /><div class='c4'>
|
||||
<hr class='hr4' /><h4 class='heading'><a name='Global.asm.7b.7d.statements'></a>Global<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statements</h4><div class='c4in'><hr class='hr4in' />
|
||||
<p>You can insert assembly code at the global level, for example:</p>
|
||||
<pre>
|
||||
asm {
|
||||
add_3_and_multiply_by_5:
|
||||
add.w #3,d0
|
||||
mulu #5,d0
|
||||
rts
|
||||
};
|
||||
</pre>
|
||||
<p>This creates an assembly function named<span class='widespace'> </span><code>add_3_and_multiply_by_5</code><span class='widespace'> </span>that takes an input argument in<span class='widespace'> </span><code>d0</code>, adds 3 to it, multiplies it by 5, and returns the result in<span class='widespace'> </span><code>d0</code>.</p>
|
||||
<p>To use such a function in C code, you need to <a href='missing.html' class='invalidlink'>prototype</a> it:</p>
|
||||
<pre>
|
||||
short add_3_and_multiply_by_5(short x);
|
||||
</pre>
|
||||
<p>This tells GTC that your function takes a<span class='widespace'> </span><code>short</code><span class='widespace'> </span>named<span class='widespace'> </span><code>x</code><span class='widespace'> </span>as an input, and outputs a<span class='widespace'> </span><code>short</code>. Because of the <a href='specificities.html#Calling.convention'>calling convention</a>,<span class='widespace'> </span><code>x</code><span class='widespace'> </span>will be placed in<span class='widespace'> </span><code>d0</code>: see <a href='specificities.html#Default.calling.convention..28regparm.29'>default calling convention</a> for more information on where input arguments to assembly functions will be located.</p>
|
||||
</div></div>
|
||||
<div class='c4'>
|
||||
<hr class='hr4' /><h4 class='heading'><a name='Inline.asm.7b.7d.statements'></a>Inline<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statements</h4><div class='c4in'><hr class='hr4in' />
|
||||
<p>You can also insert assembly code within a function. This has the advantage over global assembly functions to eliminate the overhead associated with a function call.</p>
|
||||
<pre>
|
||||
void do_something(char *command) {
|
||||
if (!strcmp(command,"off"))
|
||||
asm { trap #4 };
|
||||
else
|
||||
printf("unknown command!\n");
|
||||
}
|
||||
</pre>
|
||||
<p>This functions turns off the calculator when<span class='widespace'> </span><code>command</code><span class='widespace'> </span>is<span class='widespace'> </span><code>"off"</code>, by calling<span class='widespace'> </span><code>trap #4</code>.</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='Structure.of.an.asm.7b.7d.statement'></a>Structure of an<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statement</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>An<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statement is comprised of a set of declarations between the outer<span class='widespace'> </span><code>{</code><span class='widespace'> </span>and<span class='widespace'> </span><code>}</code><span class='widespace'> </span>braces.
|
||||
A declaration can be:</p>
|
||||
<ul><li> a <a href='glossary.html#68000'>68000</a> instruction, e.g.<span class='widespace'> </span><code>moveq #123,d0</code><span class='widespace'> </span></li><li> a label definition, e.g.<span class='widespace'> </span><code>my_function:</code><span class='widespace'> </span></li><li> a data declaration, e.g.<span class='widespace'> </span><code>dc.w 123,456,789</code><span class='widespace'> </span>or<span class='widespace'> </span><code>incbin "data.bin"</code><span class='widespace'> </span></li></ul>
|
||||
<p>You must separate different declarations either:</p>
|
||||
<ul><li> by putting them on separate lines
|
||||
</li><li> by simply concatenating them if the first is a label
|
||||
</li><li> by separating them with a semicolon (<code>;</code>) -- however you should absolutely avoid doing this outside<span class='widespace'> </span><a href='preprocessor.html#.23define'><code>#define</code></a>, as the behaviour may change some day
|
||||
</li></ul></div></div>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='asm.7b.7d.interpretation.rules'></a><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>interpretation rules</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>The behaviour of GTC is indeed very close to that of<span class='widespace'> </span><a href='glossary.html#a68k'><code>a68k</code></a>. Like<span class='widespace'> </span><a href='glossary.html#a68k'><code>a68k</code></a>, GTC tries to optimize instructions when it is possible, for example<span class='widespace'> </span><code>add.w #3,d0</code><span class='widespace'> </span>will be optimized to<span class='widespace'> </span><code>addq.w #3,d0</code>. Like<span class='widespace'> </span><a href='glossary.html#a68k'><code>a68k</code></a>, you don't need to add a<span class='widespace'> </span><code>:</code><span class='widespace'> </span>after label names: however, while with<span class='widespace'> </span><a href='glossary.html#a68k'><code>a68k</code></a><span class='widespace'> </span>you can only do so if the label is placed on the first char of the line, with GTC you can do so any time as long as the label does not correspond to an assembly instruction.</p>
|
||||
<p>The most notable difference is perhaps that, where<span class='widespace'> </span><a href='glossary.html#a68k'><code>a68k</code></a><span class='widespace'> </span>uses specific commands like<span class='widespace'> </span><code>equ</code><span class='widespace'> </span>and<span class='widespace'> </span><code>equr</code><span class='widespace'> </span>to define macros, GTC simply uses the C preprocessor. This is very powerful, as it allows you to define constants just once and reuse them in C code. You can also use normal C conditionals like<span class='widespace'> </span><code>#if</code><span class='widespace'> </span>or<span class='widespace'> </span><code>#ifdef</code>, making conditional compilation easier.
|
||||
You can also interface your code with C much more easily, for example you have access to the<span class='widespace'> </span><code>sizeof</code><span class='widespace'> </span>operator:</p>
|
||||
<pre>
|
||||
int table[] = { 1,2,3,4 };
|
||||
|
||||
asm {
|
||||
negate_table:
|
||||
lea table,a0
|
||||
moveq #sizeof(table)/2-1,d0
|
||||
\loop
|
||||
neg.w (a0)+
|
||||
dbra d0,\loop
|
||||
rts
|
||||
};
|
||||
</pre>
|
||||
<p>After execution of<span class='widespace'> </span><code>negate_table</code>,<span class='widespace'> </span><code>table</code><span class='widespace'> </span>will be equal to<span class='widespace'> </span><code>{ -1,-2,-3,-4 }</code>.</p>
|
||||
<p>Note the<span class='widespace'> </span><code>\</code><span class='widespace'> </span>in<span class='widespace'> </span><code>\loop</code>: this means that the label is local. However, this notion differs slightly from that of<span class='widespace'> </span><a href='glossary.html#a68k'><code>a68k</code></a>: while the label is only valid between the surrounding two global labels in<span class='widespace'> </span><a href='glossary.html#a68k'><code>a68k</code></a>, the label is valid throughout the<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statement in GTC. It is often more convenient, as this example shows:</p>
|
||||
<pre>
|
||||
asm {
|
||||
\return_with_error
|
||||
moveq #-1,d0
|
||||
rts
|
||||
my_function:
|
||||
addq.w #5,d0
|
||||
bmi.s \return_with_error
|
||||
tst.w d1
|
||||
bmi.s \return_with_error
|
||||
... very long code (longer than 128 bytes) ...
|
||||
rts
|
||||
};
|
||||
</pre>
|
||||
<p>In this example,<span class='widespace'> </span><code>\return_with_error</code><span class='widespace'> </span>is placed <em>before</em><span class='widespace'> </span><code>my_function</code><span class='widespace'> </span>because it allows the branches to<span class='widespace'> </span><code>\return_with_error</code><span class='widespace'> </span>to be short branches (<code>bmi.s</code>, 2 bytes) rather than long branches (<code>bmi.w</code>, 4 bytes). If GTC followed the rules of<span class='widespace'> </span><a href='glossary.html#a68k'><code>a68k</code></a>, then it would require<span class='widespace'> </span><code>\return_with_error</code><span class='widespace'> </span>to be a global, which can be inconvenient if you have lots of these. Instead, it allows you to structurally divide your program in logical<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>blocks.</p>
|
||||
</div></div>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='Extra.features.of.asm.7b.7d.statements'></a>Extra features of<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statements</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>Because<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statements rely on the C compiler architecture of GTC, there are lots of nice features, for example:</p>
|
||||
<pre>
|
||||
#define USE_KERNEL
|
||||
#include <std.h>
|
||||
asm {
|
||||
_main:
|
||||
pea "Hello, world!"(pc)
|
||||
jsr ST_helpMsg
|
||||
addq.l #4,a7
|
||||
rts
|
||||
};
|
||||
</pre>
|
||||
<p>What's most interesting in all this is that the C library required <b>no modification whatsoever</b> to allow using ROM calls in such a way: ROM calls are not defined twice, and there isn't even a conditional statement acting differently inside<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>code and inside C code!
|
||||
This is possible because the assembler was able to interpret the C construct corresponding to<span class='widespace'> </span><code>ST_helpMsg</code>.</p>
|
||||
</div></div>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='asm.7b.7d.special.operator.3a.__c__'></a><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>special operator:<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.special.operator.3a.__c__'><code>__c__</code></a></h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>This is an operator reserved to operands of instructions in<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statements.</p>
|
||||
<p>The reason why this operator exists is simple: assembly and C each have different arithmetic rules. For example, if you have the following code:</p>
|
||||
<pre>
|
||||
int table[] = { 1,2,3,4 };
|
||||
</pre>
|
||||
<p>then, while in C<span class='widespace'> </span><code>table+2</code><span class='widespace'> </span>will designate the address of<span class='widespace'> </span><code>table[2]</code><span class='widespace'> </span>(the number<span class='widespace'> </span><code>3</code>), in assembly<span class='widespace'> </span><code>table+2</code><span class='widespace'> </span>will designate the address of<span class='widespace'> </span><code>table[0]</code><span class='widespace'> </span>plus 2 bytes, which happens to be the address of<span class='widespace'> </span><code>table[1]</code>.</p>
|
||||
<p>So when you write:</p>
|
||||
<pre>
|
||||
asm {
|
||||
load_address:
|
||||
lea table+2(pc),a0
|
||||
rts
|
||||
};
|
||||
</pre>
|
||||
<p>then, as you would expect from assembly code,<span class='widespace'> </span><code>table+2</code><span class='widespace'> </span>corresponds to the address given by assembly arithmetic rules.</p>
|
||||
<p>This works with<span class='widespace'> </span><a href='preprocessor.html#.23define'><code>#define</code></a><span class='widespace'> </span>statements too:</p>
|
||||
<pre>
|
||||
asm {
|
||||
load_address:
|
||||
#define my_item table+2
|
||||
lea my_item(pc),a0
|
||||
rts
|
||||
};
|
||||
</pre>
|
||||
<p>But GTC allows you to do much more: you may want to access information that requires access to the full typing system of C, not just the addresses of different objects.
|
||||
The way you can access this typing system is by the<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.special.operator.3a.__c__'><code>__c__</code></a><span class='widespace'> </span>operator: if you write</p>
|
||||
<pre>
|
||||
asm {
|
||||
load_address:
|
||||
lea __c__(table+2)(pc),a0
|
||||
rts
|
||||
};
|
||||
</pre>
|
||||
<p>then<span class='widespace'> </span><code>table+2</code><span class='widespace'> </span>will not be interpreted according to assembly rules, but according to C rules: that is,<span class='widespace'> </span><code>__c__(table+2)</code><span class='widespace'> </span>is the adress of<span class='widespace'> </span><code>table[2]</code>.</p>
|
||||
<p>GTC goes one step further, by automatically enclosing<span class='widespace'> </span><a href='preprocessor.html#.23define'><code>#define</code>s</a> written as part of C code in the<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.special.operator.3a.__c__'><code>__c__</code></a><span class='widespace'> </span>operator:</p>
|
||||
<pre>
|
||||
int table[] = { 1,2,3,4 };
|
||||
#define third_item &table[2] // note: <em>table+2</em> would give the same results
|
||||
|
||||
int *c_load_address() {
|
||||
return third_item;
|
||||
}
|
||||
|
||||
asm {
|
||||
load_address:
|
||||
lea third_item(pc),a0
|
||||
rts
|
||||
};
|
||||
</pre>
|
||||
<p>Here both<span class='widespace'> </span><code>c_load_address()</code><span class='widespace'> </span>and<span class='widespace'> </span><code>load_address()</code><span class='widespace'> </span>do the same thing, without ever having to define<span class='widespace'> </span><code>third_item</code><span class='widespace'> </span>twice!</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='.40.40.prefix'></a><a href='extensions.html#.40.40.prefix'><code>@@</code></a><span class='widespace'> </span>prefix</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>The prefix<span class='widespace'> </span><a href='extensions.html#.40.40.prefix'><code>@@</code></a><span class='widespace'> </span>can be prepended to any identifier to prevent it from being <a href='missing.html' class='invalidlink'>expanded</a> by the <a href='missing.html' class='invalidlink'>preprocessor</a>.
|
||||
For example,<span class='widespace'> </span><code>@@MY_SYMBOL</code><span class='widespace'> </span>will expand to<span class='widespace'> </span><code>MY_SYMBOL</code><span class='widespace'> </span>even if<span class='widespace'> </span><code>MY_SYMBOL</code><span class='widespace'> </span>has been<span class='widespace'> </span><a href='preprocessor.html#.23define'><code>#define</code>d</a> to expand to<span class='widespace'> </span><code>0x1234</code>.</p>
|
||||
<p>This is not very useful in normal C code, but it can be useful in conjunction with other GTC extensions, mainly<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a><span class='widespace'> </span>statements and <a href='missing.html' class='invalidlink'>pre-compiled headers</a>.</p>
|
||||
</div></div>
|
||||
</div></div></div>
|
||||
</body>
|
||||
</html>
|
||||
112
doc/faq.html
Normal file
112
doc/faq.html
Normal file
@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>Frequently Asked Questions - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>Frequently Asked Questions</h1>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#Common.issues'>Common issues</a>
|
||||
<ul>
|
||||
<li><a href='#.28on-calc.29.I.keep.getting.errors.such.as..22not.enough.memory.to.compile.function.abc.22'>(on-calc) I keep getting errors such as "not enough memory to compile function abc"</a></li>
|
||||
</ul></li>
|
||||
<li><a href='#Differences.between.GTC.and.TIGCC'>Differences between GTC and TIGCC</a>
|
||||
<ul>
|
||||
<li><a href='#How.can.I.port.my.program.from.TIGCC.to.GTC.3f'>How can I port my program from TIGCC to GTC?</a></li>
|
||||
<li><a href='#How.can.I.make.sure.my.GTC.program.can.be.compiled.with.TIGCC.too.3f'>How can I make sure my GTC program can be compiled with TIGCC too?</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Common.issues'></a>Common issues</h1><div class='c1in'><hr class='hr1in' /><div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='.28on-calc.29.I.keep.getting.errors.such.as..22not.enough.memory.to.compile.function.abc.22'></a>(on-calc) I keep getting errors such as "<code>not enough memory to compile function <em>abc</em></code>"</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>This could be because you do not have enough free RAM (more than 100kb is recommended), but if you have enough RAM it is probably because the function <em>abc</em> is too large to fit in the memory of the calculator. You will need to split into smaller functions to avoid the error.</p>
|
||||
<p>Another reason could be that you have a<span class='widespace'> </span><a href='preprocessor.html#.23define'><code>#define</code></a><span class='widespace'> </span>with a large body, or a very
|
||||
large number of global declarations. This shouldn't be a problem for most
|
||||
programs, but if you think you are in this case, you can try to solve it with<span class='widespace'> </span><code>#undef</code><span class='widespace'> </span>or by creating a <a href='missing.html' class='invalidlink'>precompiled header</a>.</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Differences.between.GTC.and.TIGCC'></a>Differences between GTC and TIGCC</h1><div class='c1in'><hr class='hr1in' /><div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='How.can.I.port.my.program.from.TIGCC.to.GTC.3f'></a>How can I port my program from TIGCC to GTC?</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>It all depends on what features your program uses. Here is a list of porting issues:</p>
|
||||
<ul><li> <b><code>long long</code><span class='widespace'> </span>support</b>: GTC does not support them, if you use them you will have to rewrite your code to use two<span class='widespace'> </span><code>long</code>s instead. In many cases it's very easy to port.
|
||||
</li><li> <b><code>asm()</code><span class='widespace'> </span>vs<span class='widespace'> </span><a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a></b>: the assembly syntax is different between GTC and TIGCC. However if you are familiar with <a href='glossary.html#a68k'>a68k</a> you will be able to use GTC's syntax in no time.
|
||||
</li><li> <b><code>float</code>/<code>double</code><span class='widespace'> </span>support</b>: currently, GTC does not support floats. If your program uses floats, then unless you think you can get rid of them (e.g. if you are only using them for sines and cosines, you can use a pre-computed table instead), you're basically stuck and should definitely continue using TIGCC (unless you're willing to go down to the assembly level). Sorry.
|
||||
</li></ul>
|
||||
<p>Additionally, you may run into these little behaviour differences:</p>
|
||||
<ul><li> <b>Cast constructors</b>: currently, the following code
|
||||
<pre>
|
||||
int *f(int *dest,int x) {
|
||||
memcpy(dest,(int[4]){x,x+1,x+2},8);
|
||||
return dest;
|
||||
}
|
||||
</pre>
|
||||
is not accepted by GTC because the array constructed is not constant (<code>x</code><span class='widespace'> </span>is not known at compile time). But you can rewrite it to use a temporary array instead:
|
||||
<pre>
|
||||
int *f(int *dest,int x) {
|
||||
int temp[4] = {x,x+1,x+2};
|
||||
memcpy(dest,temp,8);
|
||||
return dest;
|
||||
}
|
||||
</pre>
|
||||
</li><li> <b>Calling convention</b>: by default, GTC uses the<span class='widespace'> </span><code><a href='specificities.html#Default.calling.convention..28regparm.29'>regparm</a>(2,1)</code><span class='widespace'> </span>convention, while TIGCC uses the<span class='widespace'> </span><a href='specificities.html#AMS.calling.convention..28stkparm.29'><code>stkparm</code></a><span class='widespace'> </span>convention. This is only a problem if you have written assembly functions yourself; in this case, you have to specify the calling convention you use in the prototype, e.g.:
|
||||
<pre>
|
||||
asm {
|
||||
upper_8_bits:
|
||||
move.b 4(a7),d0
|
||||
rts
|
||||
};
|
||||
char upper_8_bits(long x);
|
||||
</pre>
|
||||
would become
|
||||
<pre>
|
||||
asm {
|
||||
upper_8_bits:
|
||||
move.b 4(a7),d0
|
||||
rts
|
||||
};
|
||||
char upper_8_bits(long x) __attribute__((stkparm));
|
||||
</pre>
|
||||
</li></ul>
|
||||
<p>This list may not be exhaustive, but I will be happy to hear about any problems you might have that are not mentioned in this list.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='How.can.I.make.sure.my.GTC.program.can.be.compiled.with.TIGCC.too.3f'></a>How can I make sure my GTC program can be compiled with TIGCC too?</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>You should not have much trouble compiling GTC programs with TIGCC as GTC was designed to introduce as few incompatibilities as possible. However, if you use low-level features like assembly you might run into some problems:</p>
|
||||
<ul><li> See if your program uses <a href='extensions.html#GTC-specific.extensions'>GTC-specific extensions</a>. For example, if you really need to use a short bit of assembly you can use conditional compilation to turn a GTC-only program like this one:
|
||||
<pre>
|
||||
asm {
|
||||
turn_calculator_off:
|
||||
trap #4
|
||||
rts
|
||||
};
|
||||
</pre>
|
||||
into this more portable program:
|
||||
<pre>
|
||||
#ifdef __GTC__
|
||||
/* assembly code using GTC's <a href='extensions.html#asm.7b.7d.statement'><code>asm{}</code></a> syntax */
|
||||
asm {
|
||||
turn_calculator_off:
|
||||
trap #4
|
||||
rts
|
||||
};
|
||||
#else
|
||||
/* assembly code using TIGCC's <code>asm()</code> syntax */
|
||||
asm("
|
||||
turn_calculator_off:
|
||||
trap #4
|
||||
rts
|
||||
");
|
||||
#endif
|
||||
</pre>
|
||||
</li><li> The default calling convention is different, so if you define your own assembly functions and call them from C code make sure their prototypes are properly specified with<span class='widespace'> </span><a href='specificities.html#Default.calling.convention..28regparm.29'><code>regparm</code></a>.
|
||||
</li></ul></div></div>
|
||||
</div></div></div>
|
||||
</body>
|
||||
</html>
|
||||
51
doc/glossary.html
Normal file
51
doc/glossary.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>Glossary - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>Glossary</h1>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#68000'>68000</a></li>
|
||||
<li><a href='#a68k'>a68k</a></li>
|
||||
<li><a href='#AMS'>AMS</a></li>
|
||||
<li><a href='#Assembly'>Assembly</a></li>
|
||||
<li><a href='#TIGCC'>TIGCC</a></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<div class='c2'>
|
||||
<div class='c3'>
|
||||
<div class='c4'>
|
||||
<hr class='hr4' /><h4 class='heading'><a name='68000'></a>68000</h4><div class='c4in'><hr class='hr4in' />
|
||||
<p>The type of processor included in TI-89 and above calculators.</p>
|
||||
</div></div>
|
||||
<div class='c4'>
|
||||
<hr class='hr4' /><h4 class='heading'><a name='a68k'></a><a href='glossary.html#a68k'><code>a68k</code></a></h4><div class='c4in'><hr class='hr4in' />
|
||||
<p>The traditional (and popular) assembler for TI calculators. It is currently
|
||||
distributed as part of TIGCC.</p>
|
||||
</div></div>
|
||||
<div class='c4'>
|
||||
<hr class='hr4' /><h4 class='heading'><a name='AMS'></a>AMS</h4><div class='c4in'><hr class='hr4in' />
|
||||
<p>AMS (Advanced Mathematics Software) is the operating system of TI calculators.
|
||||
It is stored in the Flash ROM.</p>
|
||||
</div></div>
|
||||
<div class='c4'>
|
||||
<hr class='hr4' /><h4 class='heading'><a name='Assembly'></a>Assembly</h4><div class='c4in'><hr class='hr4in' />
|
||||
<p>The native language of the 68000 processor.</p>
|
||||
</div></div>
|
||||
<div class='c4'>
|
||||
<hr class='hr4' /><h4 class='heading'><a name='TIGCC'></a>TIGCC</h4><div class='c4in'><hr class='hr4in' />
|
||||
<p>The largest C compiler available for TI calculators. It's a patched GCC
|
||||
compiler and for this reason is only available for PC platforms.
|
||||
</div></div>
|
||||
</div></div>
|
||||
</div></div>
|
||||
</div></div></p></div>
|
||||
</body>
|
||||
</html>
|
||||
51
doc/index.html
Normal file
51
doc/index.html
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>GTC 0.90.2 - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<div class='c0'>
|
||||
<h1>GTC 0.90.2</h1>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#About.GTC'>About GTC</a></li>
|
||||
<li><a href='#Documentation.summary'>Documentation summary</a></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='About.GTC'></a>About GTC</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>GTC is a C compiler to create programs for the TI-89/TI-92+/V200 calculators. You can choose to run the compiler either on a computer (<em>cross-compilation</em>) or directly on a TI calculator (<em>on-calc</em> compilation).
|
||||
You can <a href='http://gtc.ti-fr.com/'> download GTC here</a>.</p>
|
||||
<p><b>Warning</b>: the Windows version does not have a graphical interface yet, so
|
||||
you should only use it if you know how to run programs from the command line.</p>
|
||||
<p>Please note this is preliminary documentation. Some important topics are
|
||||
missing, and you may find broken links.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Documentation.summary'></a>Documentation summary</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>General information:</p>
|
||||
<ul><li> <a href='credits.html#Credits.and.licensing'>Credits and licensing</a>
|
||||
</li><li> <a href='version.html#Version.history'>Version history</a>
|
||||
</li><li> <a href='credits.html#Contact'>Contact</a>
|
||||
</li></ul>
|
||||
<p>Getting started:</p>
|
||||
<ul><li> <a href='oncalc.html#On-calc.IDE'>Getting started with the calculator compiler</a>
|
||||
</li><li> <a href='windows.html#Getting.started.with.the.Windows.compiler'>Getting started with the Windows compiler</a>
|
||||
</li><li> <a href='building.html#Building.GTC'>Getting started with the Unix compiler</a>
|
||||
</li><li> <a href='http://gtc.ti-fr.com/gtc-examples.zip'> Download some examples</a>
|
||||
</li></ul>
|
||||
<p>General TI programming documentation:</p>
|
||||
<ul><li> <a href='http://tigcc.ticalc.org/doc/hdrindex.html'>TIGCCLIB headers</a>: list of TI functions, grouped by category
|
||||
</li><li> <a href='http://tigcc.ticalc.org/doc/catalog.html'>TIGCCLIB index</a>: list of TI functions, sorted alphabetically (quick access: <a href='http://tigcc.ticalc.org/doc/catalog.html#A'> A</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#B'> B</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#C'> C</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#D'> D</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#E'> E</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#F'> F</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#G'> G</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#H'> H</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#I'> I</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#J'> J</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#K'> K</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#L'> L</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#M'> M</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#N'> N</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#O'> O</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#P'> P</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#Q'> Q</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#R'> R</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#S'> S</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#T'> T</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#U'> U</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#V'> V</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#W'> W</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#X'> X</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#Y'> Y</a> <a href='http://tigcc.ticalc.org/doc/catalog.html#Z'> Z</a>)
|
||||
</li></ul>
|
||||
<p>GTC-specific documentation:</p>
|
||||
<ul><li> <a href='cmdline.html#GTC.Command-line.options'>GTC Command-line options</a>
|
||||
</li><li> <a href='extensions.html#GTC.Extensions'>GTC Extensions</a>
|
||||
</li><li> <a href='faq.html#Frequently.Asked.Questions'>Frequently Asked Questions</a>
|
||||
</li></ul></div></div>
|
||||
</div></div></div>
|
||||
</body>
|
||||
</html>
|
||||
1
doc/layout/default.css
Normal file
1
doc/layout/default.css
Normal file
@ -0,0 +1 @@
|
||||
@import url(simple.css);
|
||||
89
doc/layout/simple.css
Normal file
89
doc/layout/simple.css
Normal file
@ -0,0 +1,89 @@
|
||||
body {
|
||||
background-color: white;
|
||||
color: black;
|
||||
font-family: georgia, verdana, sans-serif;
|
||||
padding-bottom: 2em;
|
||||
font-size-adjust: 0.5;
|
||||
}
|
||||
p {
|
||||
text-align: justify;
|
||||
line-height: 130%;
|
||||
}
|
||||
pre {
|
||||
margin-left: 2em;
|
||||
}
|
||||
/*.widespace {
|
||||
margin: 0.1em;
|
||||
}*/
|
||||
a {
|
||||
color:#0000b0;
|
||||
text-decoration:none;
|
||||
}
|
||||
a:hover {
|
||||
color:#6060ff;
|
||||
text-decoration:underline;
|
||||
}
|
||||
h1,h2,h3,h4,h5,h6,
|
||||
h1 a,h2 a,h3 a,h4 a,h5 a,h6 a {
|
||||
color:#25b;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
h2 {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
.hr1in {
|
||||
height: 1px;
|
||||
background-color: #999; /* used by FF */
|
||||
color: #999; /* used by IE */
|
||||
border: 0;
|
||||
}
|
||||
.hr1,.hr2,.hr3,.hr4,.hr5,.hr6 {
|
||||
display: none;
|
||||
}
|
||||
.hr0in {
|
||||
height: 1px;
|
||||
background-color: #7a7;
|
||||
border: 0;
|
||||
}
|
||||
.hr0in,.hr2in,.hr3in,.hr4in,.hr5in,.hr6in {
|
||||
display: none;
|
||||
}
|
||||
.c0 {
|
||||
width: 700px;
|
||||
}
|
||||
/*
|
||||
.c0 {
|
||||
width: 700px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
text-align: center;
|
||||
}
|
||||
*/
|
||||
.c1 {
|
||||
text-align: left;
|
||||
}
|
||||
.toc {
|
||||
font-size: 95%;
|
||||
margin-top: 1em;
|
||||
margin-left: 2em;
|
||||
padding: 0.2em;
|
||||
border: 1px dotted black;
|
||||
}
|
||||
.toc ul {
|
||||
/*list-style-type: circle;*/
|
||||
}
|
||||
.toc ul ul ul {
|
||||
/*list-style-type: ;*/
|
||||
}
|
||||
.toc ul ul ul ul {
|
||||
display: none;
|
||||
}
|
||||
code a {
|
||||
font-weight: bold;
|
||||
}
|
||||
a.invalidlink {
|
||||
color: #900000;
|
||||
}
|
||||
354
doc/license-gpl2.html
Normal file
354
doc/license-gpl2.html
Normal file
@ -0,0 +1,354 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>GNU General Public License - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>GNU General Public License</h1>
|
||||
<pre>
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type <code>show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type </code>show c' for details.
|
||||
|
||||
The hypothetical commands <code>show w' and </code>show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than <code>show w' and </code>show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
</pre></div>
|
||||
</body>
|
||||
</html>
|
||||
14
doc/missing.html
Normal file
14
doc/missing.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>Missing entry - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>Missing entry</h1>
|
||||
<p>Sorry, this entry has not been written yet!</p></div>
|
||||
</body>
|
||||
</html>
|
||||
93
doc/oncalc.html
Normal file
93
doc/oncalc.html
Normal file
@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>On-calc usage - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>On-calc usage</h1>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#On-calc.IDE'>On-calc IDE</a>
|
||||
<ul>
|
||||
<li><a href='#Installation'>Installation</a></li>
|
||||
<li><a href='#Key.commands'>Key commands</a></li>
|
||||
<li><a href='#Tips.and.tricks'>Tips and tricks</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='On-calc.IDE'></a>On-calc IDE</h1><div class='c1in'><hr class='hr1in' /><div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Installation'></a>Installation</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>You must first install FlashAppy on your calculator. Note that like all ROM
|
||||
patches, you will not be able to send your modified calculator ROM image to
|
||||
other calculators. Neither the authors of GTC nor the author of FlashAppy can
|
||||
be held responsible for any damage that could occur during or after this
|
||||
process. However, we are not aware of any case where a calculator was damaged
|
||||
by FlashAppy.</p>
|
||||
<p>You only need to install FlashAppy once: you won't need to reinstall it after a
|
||||
reset or after upgrading to a newer version of GTC. On the other hand if you
|
||||
install an <a href='glossary.html#AMS'>AMS</a> update you will need to reinstall FlashAppy afterwards.</p>
|
||||
<p><em>Legal notice: the<span class='widespace'> </span><code>.89t/.9xt/.v2t</code><span class='widespace'> </span>and<span class='widespace'> </span><code>.89y/.9xy/.v2y</code><span class='widespace'> </span>files in the<span class='widespace'> </span><code>bin-89/92p/v200</code><span class='widespace'> </span>directories are subject to the <a href='license-gpl2.html#GNU.General.Public.License'>GNU General Public License</a>, which grants you a number of rights. You may choose not to install them, but this will prevent you from using the TIGCC Library.</em></p>
|
||||
<p>Once FlashAppy is installed, send all the files in the<span class='widespace'> </span><code>bin-89</code>,<span class='widespace'> </span><code>bin-92p</code><span class='widespace'> </span>or<span class='widespace'> </span><code>bin-v200</code><span class='widespace'> </span>directory (depending on the model) to your calculator, and archive
|
||||
them all.</p>
|
||||
<p>Check that the GTC flashapp was properly transferred by entering the Var-Link
|
||||
screen and pressing F7: you should see GTC appear in the list. Otherwise, the
|
||||
transfer failed: make sure that FlashAppy is installed and that you have enough
|
||||
Archive memory.</p>
|
||||
<p>To create a test source file, create a directory named<span class='widespace'> </span><code>source</code>, create an
|
||||
empty text file inside that directory named<span class='widespace'> </span><code>hello</code><span class='widespace'> </span>with the TI text editor,
|
||||
and archive it with the Var-Link screen.</p>
|
||||
<p>Now you can run the IDE by typing<span class='widespace'> </span><code>gtc\gtc_ide()</code><span class='widespace'> </span>and open the file named<span class='widespace'> </span><code>hello</code>.</p>
|
||||
<p>Type in the following code:</p>
|
||||
<pre>
|
||||
#include <tigcclib.h>
|
||||
|
||||
void _main() {
|
||||
ST_helpMsg("Hello world!");
|
||||
}
|
||||
</pre>
|
||||
<p>Now press the F5 key. This should bring up a compilation dialog, which should
|
||||
close after a few seconds (if not, you may not have installed GTC properly:
|
||||
make sure FlashAppy is correctly installed, that everything is archived, and
|
||||
that you have enough RAM).</p>
|
||||
<p>Once the compilation is over you can exit the IDE and run your program by
|
||||
typing</p>
|
||||
<pre>
|
||||
outbin()
|
||||
</pre>
|
||||
<p>It should display the text<span class='widespace'> </span><code>Hello world!</code><span class='widespace'> </span>in the status line. If it worked,
|
||||
congratulations! You now have a working C compiler on your calculator.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Key.commands'></a>Key commands</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>Here is a small subset of the key commands supported by GTC IDE:</p>
|
||||
<ul><li> <b>CLEAR</b>: indent the cursor by two columns (equivalent to the TAB key on a
|
||||
PC)
|
||||
</li><li> <b>Catalog</b>: lists all functions available in the standard library
|
||||
</li><li> <b>F5</b>: compile the current file
|
||||
</li><li> <b>2nd-F3</b>: search for a string in the current file
|
||||
</li><li> <b>Diamond-F3</b>: replace a string in the current file
|
||||
</li><li> <b>F3</b>: search for the next occurrence of the string
|
||||
</li></ul>
|
||||
<p>Also, GTC IDE supports keyboard shortcuts that the standard text editor
|
||||
doesn't: for example, you can press <b>Shift-2nd-Right</b> (press Shift and 2nd,
|
||||
then press Right while still holding Shift and 2nd) to highlight the text from
|
||||
the cursor to the end of the line. Likewise you can press <b>Shift-2nd-Down</b> to
|
||||
highlight a whole screen of text, or <b>Shift-Diamond-Down</b> to select until the
|
||||
end of the file. These shortcuts come in particularly handy when selecting
|
||||
large amounts of text.</p>
|
||||
</div></div>
|
||||
<div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Tips.and.tricks'></a>Tips and tricks</h2><div class='c2in'><hr class='hr2in' /><ul><li> You should map<span class='widespace'> </span><code>main\outbin()</code><span class='widespace'> </span>to a<span class='widespace'> </span><code>kbdprgm</code><span class='widespace'> </span>like<span class='widespace'> </span><code>kbdprgm9</code><span class='widespace'> </span>so that you can
|
||||
quickly run a freshly compiled program by typing <b>Diamond-9</b> in the Home
|
||||
screen.
|
||||
</li><li> You can save memory by deleting header files you don't use in the folder<span class='widespace'> </span><code>zheader</code>. You should not delete<span class='widespace'> </span><code>stdhead</code><span class='widespace'> </span>or<span class='widespace'> </span><code>keywords</code><span class='widespace'> </span>if you want to
|
||||
compile programs designed for the TIGCC library.
|
||||
</li></ul></div></div>
|
||||
</div></div></div>
|
||||
</body>
|
||||
</html>
|
||||
27
doc/preprocessor.html
Normal file
27
doc/preprocessor.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>The C preprocessor - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>The C preprocessor</h1>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#Preprocessor.directives'>Preprocessor directives</a>
|
||||
<ul>
|
||||
<li><a href='#.23define'>#define</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Preprocessor.directives'></a>Preprocessor directives</h1><div class='c1in'><hr class='hr1in' /><div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='.23define'></a><a href='preprocessor.html#.23define'><code>#define</code></a></h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>...
|
||||
</div></div>
|
||||
</div></div></p></div>
|
||||
</body>
|
||||
</html>
|
||||
78
doc/specificities.html
Normal file
78
doc/specificities.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>Specificities of GTC - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>Specificities of GTC</h1>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#Application.binary.interface..28ABI.29'>Application binary interface (ABI)</a>
|
||||
<ul>
|
||||
<li><a href='#Calling.convention'>Calling convention</a>
|
||||
<ul>
|
||||
<li><a href='#Default.calling.convention..28regparm.29'>Default calling convention (regparm)</a></li>
|
||||
<li><a href='#AMS.calling.convention..28stkparm.29'>AMS calling convention (stkparm)</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Application.binary.interface..28ABI.29'></a>Application binary interface (<b>ABI</b>)</h1><div class='c1in'><hr class='hr1in' /><div class='c2'>
|
||||
<hr class='hr2' /><h2 class='heading'><a name='Calling.convention'></a>Calling convention</h2><div class='c2in'><hr class='hr2in' />
|
||||
<p>A calling convention specifies where arguments to a function are placed, and where the function places its return value.
|
||||
You shouldn't worry about it, unless you are an <a href='glossary.html#Assembly'>assembly</a> programmer trying to call assembly functions from C code or vice-versa.</p>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='Default.calling.convention..28regparm.29'></a>Default calling convention (<a href='specificities.html#Default.calling.convention..28regparm.29'><code>regparm</code></a>)</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>Unless otherwise specified, GTC uses the most efficient calling convention,<span class='widespace'> </span><a href='specificities.html#Default.calling.convention..28regparm.29'><code>regparm</code></a>.
|
||||
Basically, it consists of placing as many arguments as possible into a small set of <a href='missing.html' class='invalidlink'>registers</a> for maximum efficiency, and when they are all used, place the remaining arguments on the <a href='missing.html' class='invalidlink'>stack</a>, which is less efficient.</p>
|
||||
<p>More precisely, here is the specific algorithm for placing arguments:</p>
|
||||
<ul><li> for each argument<span class='widespace'> </span><code>a</code>, from left to right
|
||||
</li><ul><li> if all registers {<code>d0</code>,<code>d1</code>,<code>d2</code>,<code>a0</code>,<code>a1</code>} are already used by other arguments
|
||||
</li><ul><li> place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>on the stack
|
||||
</li></ul><li> else
|
||||
</li><ul><li> if there is at least one of {<code>d0</code>,<code>d1</code>,<code>d2</code>} unused <b>and</b> one of {<code>a0</code>,<code>a1</code>} unused
|
||||
</li><ul><li> if<span class='widespace'> </span><code>a</code>'s type is a pointer
|
||||
</li><ul><li> place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in the next free address register
|
||||
</li></ul><li> else
|
||||
</li><ul><li> place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in the next free data register
|
||||
</li></ul></ul><li> else
|
||||
</li><ul><li> if one of {<code>a0</code>,<code>a1</code>} is unused
|
||||
</li><ul><li> place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in the next free address register
|
||||
</li></ul><li> else
|
||||
</li><ul><li> place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in the next free data register
|
||||
</li></ul></ul></ul></ul></ul>
|
||||
<p>Here is how the placement of an argument is done:</p>
|
||||
<ul><li> how to place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in the next free data register:
|
||||
</li><ul><li> place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in<span class='widespace'> </span><code>d0</code><span class='widespace'> </span>if it is unused
|
||||
</li><li> or if it is used
|
||||
</li><ul><li> place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in<span class='widespace'> </span><code>d1</code><span class='widespace'> </span>if it is unused
|
||||
</li><li> or if it is used place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in<span class='widespace'> </span><code>d2</code><span class='widespace'> </span></li></ul></ul><li> how to place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in the next free address register:
|
||||
</li><ul><li> place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in<span class='widespace'> </span><code>a0</code><span class='widespace'> </span>if it is unused
|
||||
</li><li> or if it is used place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>in<span class='widespace'> </span><code>a1</code><span class='widespace'> </span></li></ul><li> how to place<span class='widespace'> </span><code>a</code><span class='widespace'> </span>on the stack:
|
||||
</li><ul><li> see<span class='widespace'> </span><a href='specificities.html#AMS.calling.convention..28stkparm.29'><code>stkparm</code></a><span class='widespace'> </span></li></ul></ul>
|
||||
<p>Here is the algorithm for placing the return value:</p>
|
||||
<ul><li> if the return value's type is a pointer
|
||||
</li><ul><li> the function should return the value in<span class='widespace'> </span><code>a0</code><span class='widespace'> </span></li></ul><li> if the return value's type is an integer
|
||||
</li><ul><li> the function should return the value in<span class='widespace'> </span><code>d0</code><span class='widespace'> </span></li></ul><li> if the return value's type is a<span class='widespace'> </span><code>struct</code><span class='widespace'> </span>or a<span class='widespace'> </span><code>union</code><span class='widespace'> </span></li><ul><li> if the structure is 4 bytes long or shorter
|
||||
</li><ul><li> the function should return the <em>contents</em> of the structure in<span class='widespace'> </span><code>d0</code><span class='widespace'> </span>(not the address!)
|
||||
</li></ul><li> else
|
||||
</li><ul><li> the ABI is not specified in this case, you should avoid it
|
||||
</li></ul></ul></ul>
|
||||
<p>Note that<span class='widespace'> </span><a href='specificities.html#Default.calling.convention..28regparm.29'><code>regparm</code></a><span class='widespace'> </span>requires the function to have a fixed number of arguments: otherwise, for <a href='missing.html' class='invalidlink'>variable-argument functions</a>, <b>no</b> arguments are placed in registers, and the<span class='widespace'> </span><a href='specificities.html#AMS.calling.convention..28stkparm.29'><code>stkparm</code></a><span class='widespace'> </span>convention is used instead.</p>
|
||||
<p>Note that TIGCC uses the same algorithm, as long as you specify the <a href='missing.html' class='invalidlink'>function attribute</a><span class='widespace'> </span><code>__attribute__((regparm(2,1)))</code>.</p>
|
||||
<p>You can also use a different set of variables than<span class='widespace'> </span><code>d0</code>-<code>d2</code>/<code>a0</code>-<code>a1</code><span class='widespace'> </span>thanks to the<span class='widespace'> </span><a href='missing.html' class='invalidlink'><code>regparm</code><span class='widespace'> </span>function attribute</a>, but it is not recommended.</p>
|
||||
</div></div>
|
||||
<div class='c3'>
|
||||
<hr class='hr3' /><h3 class='heading'><a name='AMS.calling.convention..28stkparm.29'></a>AMS calling convention (<a href='specificities.html#AMS.calling.convention..28stkparm.29'><code>stkparm</code></a>)</h3><div class='c3in'><hr class='hr3in' />
|
||||
<p>The<span class='widespace'> </span><a href='specificities.html#AMS.calling.convention..28stkparm.29'><code>stkparm</code></a><span class='widespace'> </span>convention is less efficient, but is useful because it is the one used internally by <a href='glossary.html#AMS'>AMS</a>. It is also much simpler to describe.</p>
|
||||
<p>The arguments are pushed one after the other onto the stack, starting from the rightmost argument.<span class='widespace'> </span><code>char</code>s and<span class='widespace'> </span><code>unsigned char</code>s should be widened to an<span class='widespace'> </span><code>int</code><span class='widespace'> </span>before being pushed.
|
||||
</div></div>
|
||||
</div></div>
|
||||
</div></div></p></div>
|
||||
</body>
|
||||
</html>
|
||||
32
doc/version.html
Normal file
32
doc/version.html
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>History - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>History</h1>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#Version.history'>Version history</a></li>
|
||||
<li><a href='#To.do'>To do</a></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Version.history'></a>Version history</h1><div class='c1in'><hr class='hr1in' /><ul><li> 0.90.2:
|
||||
</li><ul><li> fix IDE behaviour when catalog symbol limit is reached
|
||||
</li><li> small compiler fixes:
|
||||
</li><ul><li> proper error message when converting from union type to another type
|
||||
</li><li> reject duplicate member names in struct or union declarations
|
||||
</li></ul></ul><li> 0.90.1: first public release
|
||||
</li></ul></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='To.do'></a>To do</h1><div class='c1in'><hr class='hr1in' /><ul><li> Implement command-line interface in on-calc version.
|
||||
</li><li> Improve the pre-compiled header format to handle the full up-to-date TIGCC library.
|
||||
</li><li> Add a true linker.
|
||||
</li></ul></div></div></div>
|
||||
</body>
|
||||
</html>
|
||||
29
doc/windows.html
Normal file
29
doc/windows.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>Windows-specific features - GTC documentation</title>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<link rel='stylesheet' type='text/css' href='layout/default.css' />
|
||||
</head>
|
||||
<body>
|
||||
<p><a href='index.html'>◄ Back to index</a></p>
|
||||
<div class='c0'>
|
||||
<h1>Windows-specific features</h1>
|
||||
<p><b>Warning</b>: the Windows version does not have a graphical interface yet, so
|
||||
you should only use it if you know how to run programs from the command line.</p>
|
||||
<div class='toc'><div class='toctop'><div class='tocbot'><div class='toc-content'>
|
||||
<b>Contents:</b><ul>
|
||||
<li><a href='#Getting.started.with.the.Windows.compiler'>Getting started with the Windows compiler</a></li>
|
||||
</ul>
|
||||
</div></div></div></div>
|
||||
<div class='c1'>
|
||||
<hr class='hr1' /><h1 class='heading'><a name='Getting.started.with.the.Windows.compiler'></a>Getting started with the Windows compiler</h1><div class='c1in'><hr class='hr1in' />
|
||||
<p><em>Legal notice: the<span class='widespace'> </span><code>Include</code><span class='widespace'> </span>directory is subject to the <a href='license-gpl2.html#GNU.General.Public.License'>GNU General Public License</a>, which grants you a number of rights. You may choose not to install it, but it will prevent you from using the TIGCC Library.</em></p>
|
||||
<p>To install GTC just extract<span class='widespace'> </span><code>gtc.exe</code><span class='widespace'> </span>and the<span class='widespace'> </span><code>Include</code><span class='widespace'> </span>directory to any
|
||||
directory. You should add that directory to your Windows path (Control Panel →
|
||||
System → Advanced → Environment Variables, and modify the PATH variable).</p>
|
||||
<p>Now you can invoke<span class='widespace'> </span><code>gtc</code><span class='widespace'> </span>on the command-line, for more information see <a href='cmdline.html#GTC.Command-line.options'>GTC
|
||||
Command-line options</a>.
|
||||
</div></div></p></div>
|
||||
</body>
|
||||
</html>
|
||||
96
gtc/Makefile
Normal file
96
gtc/Makefile
Normal file
@ -0,0 +1,96 @@
|
||||
VPATH = src
|
||||
|
||||
ifndef DEBUG_FLAG
|
||||
CCBASEFLAGS=-O2 -Wall -Wno-unused-functions
|
||||
LDFLAGS=-s
|
||||
else
|
||||
CCBASEFLAGS=-g -Wall -Wno-switch -DDEBUGGING
|
||||
LDFLAGS=
|
||||
endif
|
||||
ifdef MINGW32
|
||||
ifeq (Cygwin,$(shell uname -o))
|
||||
CCBASEFLAGS += -mno-cygwin
|
||||
LDFLAGS += -mno-cygwin
|
||||
endif
|
||||
endif
|
||||
include ../config.mk
|
||||
include ../platform.mk
|
||||
CDEFINES=$(GTC_ARCH_DEFINES) -DINCL_PATH=\"$(prefix)/share/gtc/include\"
|
||||
CFLAGS=$(CCBASEFLAGS) $(CDEFINES)
|
||||
SOURCEFILES=$(wildcard src/*.c src/*.h src/gtpack/*)
|
||||
HEADERS=$(wildcard src/*.h)
|
||||
OBJFILES=\
|
||||
analyze.o \
|
||||
bin2calc.o \
|
||||
cmain.o \
|
||||
decl.o \
|
||||
expr.o \
|
||||
func.o \
|
||||
gen68k.o \
|
||||
genffp.o \
|
||||
genstmt.o \
|
||||
getasm.o \
|
||||
getsym.o \
|
||||
init.o \
|
||||
intexpr.o \
|
||||
memmgt.o \
|
||||
optimize.o \
|
||||
out68k_as.o \
|
||||
peep68k.o \
|
||||
preproc.o \
|
||||
reg68k.o \
|
||||
searchkw.o \
|
||||
stmt.o \
|
||||
sunpack.o \
|
||||
symbol.o \
|
||||
|
||||
|
||||
.PHONY: all clean install
|
||||
|
||||
all: gtc
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJFILES) src/tags
|
||||
distclean: clean
|
||||
$(RM) gtc$(BIN_SUFFIX)
|
||||
scratchclean: distclean
|
||||
|
||||
install: gtc
|
||||
mkdir -p $(prefix)/bin
|
||||
install gtc $(prefix)/bin/gtc
|
||||
|
||||
splint:
|
||||
splint \
|
||||
-nestcomment -paramuse -nullassign -initallelements -fullinitblock \
|
||||
+charint +boolint -boolops +ptrnegate -shiftnegative \
|
||||
-nullret -retvalint -retvalother \
|
||||
-noeffect \
|
||||
-globstate -mustfreeonly -mustfreefresh -onlytrans -statictrans -observertrans -dependenttrans -temptrans -branchstate \
|
||||
$(CDEFINES) $(OBJFILES:%.o=%.c)
|
||||
# -nestcomment is for '//#define foo bar /* this is a comment */'
|
||||
# -paramuse is for unused func params
|
||||
# -nullassign is for 'int x CGLOB;'
|
||||
# -initallelements is for 'int x[5] CGLOBL;'
|
||||
# -fullinitblock is for 'TI_SHORT x CGLOBL;'
|
||||
# +charint is for 'char c = 2+1;' or 'if (c < 2+1)'
|
||||
# +boolint is for 'int z = (x==y);'
|
||||
# -boolops is for 'ptr && x'
|
||||
# +ptrnegate is for '!ptr'
|
||||
# -shiftnegative is for '1 << my_int' where 'my_int' has no known range
|
||||
# -noeffect is for '(void)0'
|
||||
# -nullret is for 'return NULL;' without '/*@null@*/' annotation
|
||||
# -retvalint is for 'myfunc(x);' without subsequent cast to void
|
||||
# -retvalother is for 'myfunc(x);' without subsequent cast to void
|
||||
|
||||
src/protos.h: src/*.c
|
||||
ruby -e '' && perl -e '' && (grep "^[^/\#*} ].*(.*{" src/*.c | perl -pe 's/ {/;/ or die $$_' | perl -pe '$$m=$$_;s/\/\*.*?\*\// /g;/(\w+)\(/ or die $$_;print "$$1:";$$_=$$m' | perl -pe 's/\bTYP\b/struct typ/g;s/\bSYM\b/struct sym/g;s/\bTABLE\b/struct stab/g;s/\bHTABLE\b/struct hstab/g;s/\bSTACK_IMAGE\b/struct _stackimg/g;s/\bREGS_IMAGE\b/struct _regsimg/g;s/\b_pc_bcd\b/struct _pc_bcd_s/g' | sort | uniq | ruby script/mkprotos.rb > $@) || echo 1>&2 "warning: unable to rebuild 'protos.h'"
|
||||
|
||||
gtc: $(SOURCEFILES)
|
||||
$(MAKE) gtc-rebuild
|
||||
|
||||
#$(OBJFILES): $(HEADERS)
|
||||
gtc-rebuild: $(OBJFILES)
|
||||
$(CC) -o gtc $(LDFLAGS) $(OBJFILES)
|
||||
|
||||
%.o: %.c vcg.c error.c *.h gtpack/*.h Makefile config.mk
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
87
gtc/Makefile.orig
Normal file
87
gtc/Makefile.orig
Normal file
@ -0,0 +1,87 @@
|
||||
VPATH = src
|
||||
|
||||
ifndef DEBUG_FLAG
|
||||
CCBASEFLAGS=-O2 -Wimplicit
|
||||
LDFLAGS=-s
|
||||
else
|
||||
CCBASEFLAGS=-g -Wall
|
||||
LDFLAGS=
|
||||
endif
|
||||
ifdef MINGW32
|
||||
ifeq (Cygwin,$(shell uname -o))
|
||||
CCBASEFLAGS += -mno-cygwin
|
||||
LDFLAGS += -mno-cygwin
|
||||
endif
|
||||
endif
|
||||
include ../config.mk
|
||||
include ../platform.mk
|
||||
CDEFINES=$(GTC_ARCH_DEFINES) -DINCL_PATH=\"$(prefix)/share/gtc/include\"
|
||||
CFLAGS=$(CCBASEFLAGS) $(CDEFINES)
|
||||
OBJFILES=\
|
||||
analyze.o \
|
||||
cmain.o \
|
||||
decl.o \
|
||||
expr.o \
|
||||
func.o \
|
||||
gen68k.o \
|
||||
genffp.o \
|
||||
genstmt.o \
|
||||
getasm.o \
|
||||
getsym.o \
|
||||
init.o \
|
||||
intexpr.o \
|
||||
memmgt.o \
|
||||
optimize.o \
|
||||
out68k_as.o \
|
||||
peep68k.o \
|
||||
preproc.o \
|
||||
reg68k.o \
|
||||
searchkw.o \
|
||||
stmt.o \
|
||||
sunpack.o \
|
||||
symbol.o \
|
||||
ttbin2asm.o \
|
||||
|
||||
|
||||
.PHONY: all clean install
|
||||
|
||||
all: gtc
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJFILES) src/tags
|
||||
distclean: clean
|
||||
$(RM) gtc$(BIN_SUFFIX)
|
||||
scratchclean: distclean
|
||||
|
||||
install: gtc
|
||||
mkdir -p $(prefix)/bin
|
||||
install gtc $(prefix)/bin/gtc
|
||||
|
||||
splint:
|
||||
splint \
|
||||
-nestcomment -paramuse -nullassign -initallelements -fullinitblock \
|
||||
+charint +boolint -boolops +ptrnegate -shiftnegative \
|
||||
-nullret -retvalint -retvalother \
|
||||
-noeffect \
|
||||
-globstate -mustfreeonly -mustfreefresh -onlytrans -statictrans -observertrans -dependenttrans -temptrans -branchstate \
|
||||
$(CDEFINES) $(OBJFILES:%.o=%.c)
|
||||
# -nestcomment is for '//#define foo bar /* this is a comment */'
|
||||
# -paramuse is for unused func params
|
||||
# -nullassign is for 'int x CGLOB;'
|
||||
# -initallelements is for 'int x[5] CGLOBL;'
|
||||
# -fullinitblock is for 'TI_SHORT x CGLOBL;'
|
||||
# +charint is for 'char c = 2+1;' or 'if (c < 2+1)'
|
||||
# +boolint is for 'int z = (x==y);'
|
||||
# -boolops is for 'ptr && x'
|
||||
# +ptrnegate is for '!ptr'
|
||||
# -shiftnegative is for '1 << my_int' where 'my_int' has no known range
|
||||
# -noeffect is for '(void)0'
|
||||
# -nullret is for 'return NULL;' without '/*@null@*/' annotation
|
||||
# -retvalint is for 'myfunc(x);' without subsequent cast to void
|
||||
# -retvalother is for 'myfunc(x);' without subsequent cast to void
|
||||
|
||||
gtc: $(OBJFILES)
|
||||
$(CC) -o gtc $(LDFLAGS) $(OBJFILES)
|
||||
|
||||
%.o: %.c vcg.c error.c *.h gtpack/*.h Makefile config.mk
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
114
gtc/script/mkprotos.rb
Normal file
114
gtc/script/mkprotos.rb
Normal file
@ -0,0 +1,114 @@
|
||||
#!/usr/bin/ruby
|
||||
|
||||
class String
|
||||
def scan_for_structenum(target)
|
||||
scan(/(struct\s+\w+)/) do
|
||||
target[$1] = true
|
||||
end
|
||||
scan(/enum\((\w+)\)/) do
|
||||
target["enum #$1"] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class FuncDef
|
||||
attr_accessor :name,:files,:proto,:referenced
|
||||
def initialize(name,files,proto)
|
||||
@name = name
|
||||
@files = files
|
||||
@proto = proto
|
||||
@referenced = []
|
||||
end
|
||||
def to_s
|
||||
(files.length==1 ? files[0] : "{"+files.join(",")+"}")+":#{name} [[#{proto}]]"
|
||||
end
|
||||
def inspect
|
||||
"{{FuncDef #{to_s}}}"
|
||||
end
|
||||
def compatible?(oth)
|
||||
name==oth.name && proto==oth.proto
|
||||
end
|
||||
def static?
|
||||
proto =~ /^\bstatic\b/
|
||||
end
|
||||
end
|
||||
|
||||
funcs = {}
|
||||
structenum = {}
|
||||
|
||||
while x=gets
|
||||
if x !~ /^(\w+):(.*?):(.*)$/
|
||||
throw x
|
||||
else
|
||||
func = FuncDef.new($1,[$2],$3)
|
||||
if !func.static?
|
||||
func.proto.scan_for_structenum(structenum)
|
||||
name = func.name
|
||||
if funcs[name]
|
||||
if funcs[name].compatible?(func)
|
||||
funcs[name].files += func.files
|
||||
else
|
||||
$stderr.puts "conflict between #{funcs[name]} and #{func}"
|
||||
throw :conflict
|
||||
end
|
||||
else
|
||||
funcs[name] = func
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
banlist = %w(debug isidch isalnum isdigit isspace unary declare nl Compile err_int warn_int error_do AP_app AP_about sUnpack)
|
||||
banlist.each do |name|
|
||||
funcs.delete(name)
|
||||
end
|
||||
|
||||
class Union
|
||||
include Enumerable
|
||||
def initialize(*sets)
|
||||
@sets = sets
|
||||
end
|
||||
def each
|
||||
@sets.each do |set|
|
||||
set.each do |item|
|
||||
yield item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Union.new(Dir['**/*.c']).each do |path|
|
||||
File.open(path) do |f|
|
||||
words = Hash.new 0
|
||||
f.each do |line|
|
||||
line.scan(/\w+/) do |word|
|
||||
if funcs[word]
|
||||
words[word] += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
words.each do |word,count|
|
||||
if funcs[word].files != [path]
|
||||
funcs[word].referenced << path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
puts "// Auto-generated file, do not edit!"
|
||||
puts
|
||||
puts "#ifndef PROTOS_H_"
|
||||
puts "#define PROTOS_H_"
|
||||
puts
|
||||
structenum.keys.sort.each do |decl|
|
||||
puts "#{decl};"
|
||||
end
|
||||
puts
|
||||
funcs.each do |name,func|
|
||||
if !func.referenced.empty? || func.files!=["src/out68k_as.c"]
|
||||
puts func.proto
|
||||
end
|
||||
end
|
||||
puts
|
||||
puts "#endif"
|
||||
4
gtc/src/Makefile
Normal file
4
gtc/src/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
all:
|
||||
|
||||
tags: *.c *.h
|
||||
ctags *.c *.h
|
||||
201
gtc/src/all.c
Normal file
201
gtc/src/all.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* (on-calc) main file
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#define DECLARE
|
||||
#define FLASH_VERSION
|
||||
#define GTDEV
|
||||
#include "define.h"
|
||||
#ifdef OPTIMIZE_BSS
|
||||
register void *bssdata asm("a5");
|
||||
#endif
|
||||
#define dseg() while (0)
|
||||
#define cseg() while (0)
|
||||
#define nl() while (0)
|
||||
#define compound_done getsym
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
|
||||
#include "flashhdr.h"
|
||||
#ifdef GTDEV
|
||||
#include "GtDevComm.h"
|
||||
#endif
|
||||
#include "flashhdr.c"
|
||||
|
||||
#ifndef debug
|
||||
void debug(int c) {
|
||||
printf("%c ",c);
|
||||
ngetchx();
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef exit
|
||||
#define exit(k) asm(" move.l exit_a7,%sp\n rts")
|
||||
extern char *curname;
|
||||
extern void fatal(char *s) __attribute__ ((noreturn));
|
||||
|
||||
#include "out68k_as.c"
|
||||
|
||||
#include "decl.c"
|
||||
#include "expr.c"
|
||||
#ifdef ASM
|
||||
#include "getasm.c"
|
||||
#endif
|
||||
#include "getsym.c"
|
||||
#include "init.c"
|
||||
#include "intexpr.c"
|
||||
//#include "memmgt.c" // xalloc is common to both modules
|
||||
#include "preproc.c"
|
||||
#include "searchkw.c"
|
||||
#include "stmt.c"
|
||||
#include "symbol.c"
|
||||
|
||||
void *exit_a7 CGLOB;
|
||||
#if 0
|
||||
void _exit(int code) {
|
||||
clean_up();
|
||||
printf("\nerror code %d",code);
|
||||
while (!kbhit());
|
||||
asm(" move.l exit_a7,%sp; rts");
|
||||
// exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void _noreturn assert_terminated();
|
||||
#ifdef GTDEV
|
||||
void fatal(char *message) {
|
||||
clean_up();
|
||||
msg_process(message, ET_FATAL, "", "", -1, -1);
|
||||
exit(0);
|
||||
assert_terminated();
|
||||
}
|
||||
#else
|
||||
void fatal(char *message) {
|
||||
clean_up();
|
||||
msg2("Fatal error!\n%s\n", message);
|
||||
// msg("There may be a syntax error or a compiler bug.\n");
|
||||
// while (!kbhit());
|
||||
ngetchx();
|
||||
asm(" move.l exit_a7,%sp; rts");
|
||||
assert_terminated();
|
||||
// exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void fatal(char *s) __attribute__ ((noreturn));
|
||||
|
||||
#define mk_node near_mk_node
|
||||
#define mk_icon near_mk_icon
|
||||
struct enode *mk_node(enum(e_node) nt, struct enode *v1, struct enode *v2) {
|
||||
/*
|
||||
* build an expression node with a node type of nt and values v1 and v2.
|
||||
*/
|
||||
struct enode *ep;
|
||||
ep = (struct enode *) xalloc((int) sizeof(struct enode), ENODE+MK_NODE);
|
||||
ep->nodetype = nt;
|
||||
ep->etype = bt_void;
|
||||
ep->esize = -1;
|
||||
ep->v.p[0] = v1;
|
||||
ep->v.p[1] = v2;
|
||||
return ep;
|
||||
}
|
||||
|
||||
struct enode *mk_icon(long i) {
|
||||
/*
|
||||
* build an expression node forming an integer constant
|
||||
*/
|
||||
struct enode *ep;
|
||||
// ep = (struct enode *) xalloc((int) sizeof(struct enode), ENODE+MK_ICON);
|
||||
ep = (struct enode *) xalloc((int) sizeof(struct xcon), ENODE+MK_ICON);
|
||||
ep->nodetype = en_icon;
|
||||
ep->etype = bt_void;
|
||||
#ifdef NO_CALLOC
|
||||
ep->esize = 0;
|
||||
#endif
|
||||
ep->v.i = i;
|
||||
return ep;
|
||||
}
|
||||
|
||||
#include "analyze.c"
|
||||
#include "func.c"
|
||||
#include "gen68k.c"
|
||||
#include "genffp.c"
|
||||
#include "genstmt.c"
|
||||
#include "memmgt.c" // xalloc is common to both modules
|
||||
#include "optimize.c"
|
||||
#include "peep68k.c"
|
||||
#include "reg68k.c"
|
||||
|
||||
/* this is reimplemented because old versions of TIGCC didn't check for _F_WRIT */
|
||||
void my_fclose(FILE *f) {
|
||||
if (f->flags&_F_WRIT)
|
||||
HeapRealloc(f->handle,*(unsigned short*)f->base+2);
|
||||
HeapUnlock(f->handle);
|
||||
free(f);
|
||||
}
|
||||
|
||||
asm("bcopy:\n"
|
||||
" move.w (12,%sp),-(%sp)\n"
|
||||
" clr.w -(%sp)\n"
|
||||
" move.l (8,%sp),-(%sp)\n"
|
||||
" move.l (16,%sp),-(%sp)\n"
|
||||
" movea.l 0xC8,%a0\n"
|
||||
" movea.l (%a0,0x26A*4),%a0\n"
|
||||
" jsr (%a0) /* memcpy */\n"
|
||||
" lea (%sp,12),%sp\n"
|
||||
" rts\n"
|
||||
|
||||
"__mulsi3:\n"
|
||||
" move.l (4,%sp),%d1\n"
|
||||
" move.l (8,%sp),%d2\n"
|
||||
" move.l %d2,%d0\n"
|
||||
" mulu %d1,%d0\n"
|
||||
" swap %d2\n"
|
||||
" mulu %d1,%d2\n"
|
||||
" swap %d1\n"
|
||||
" mulu (10,%sp),%d1\n"
|
||||
" add.w %d1,%d2\n"
|
||||
" swap %d2\n"
|
||||
" clr.w %d2\n"
|
||||
" add.l %d2,%d0\n"
|
||||
" rts\n"
|
||||
|
||||
"__modsi3:\n"
|
||||
" move.w #0x2A9*4,%d2 /* _ms32s32 */\n"
|
||||
" bra.s __div_entry\n"
|
||||
"__divsi3:\n"
|
||||
" move.w #0x2A8*4,%d2 /* _ds32s32 */\n"
|
||||
" bra.s __div_entry\n"
|
||||
"__umodsi3:\n"
|
||||
" move.w #0x2A9*4,%d2 /* _mu32u32 */\n"
|
||||
" bra.s __div_entry\n"
|
||||
"__udivsi3:\n"
|
||||
" move.w #0x2A8*4,%d2 /* _du32u32 */\n"
|
||||
" bra.s __div_entry\n"
|
||||
" nop\n"
|
||||
"__div_entry:\n"
|
||||
" move.l (4,%sp),%d1\n"
|
||||
" move.l (8,%sp),%d0\n"
|
||||
" movea.l 0xC8,%a0\n"
|
||||
" movea.l (%a0,%d2.w),%a0\n"
|
||||
" jsr (%a0)\n"
|
||||
" move.l %d1,%d0\n"
|
||||
" rts");
|
||||
|
||||
#include "cmain.c"
|
||||
|
||||
#include "flashend.c"
|
||||
// vim:ts=4:sw=4
|
||||
816
gtc/src/analyze.c
Normal file
816
gtc/src/analyze.c
Normal file
@ -0,0 +1,816 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* analyzer
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
//#undef OPT_ROMCALLS
|
||||
|
||||
/*
|
||||
* this module will step through the parse tree and find all optimizable
|
||||
* expressions. at present these expressions are limited to expressions that
|
||||
* are valid throughout the scope of the function. the list of optimizable
|
||||
* expressions is:
|
||||
*
|
||||
* constants
|
||||
* global and static addresses
|
||||
* auto addresses
|
||||
* contents of auto addresses.
|
||||
*
|
||||
* contents of auto addresses are valid only if the address is never referred to
|
||||
* without dereferencing.
|
||||
*
|
||||
* scan will build a list of optimizable expressions which opt1 will replace
|
||||
* during the second optimization pass.
|
||||
*/
|
||||
|
||||
void scan(struct snode *block);
|
||||
void repcse(struct snode *block);
|
||||
|
||||
#define INIT_EXEC_COUNT 16
|
||||
FILE *list CGLOB;
|
||||
int regs_used CGLOB;
|
||||
struct enode *regexp[REGEXP_SIZE] CGLOBL;
|
||||
xstatic unsigned int exec_count CGLOB;
|
||||
xstatic struct cse *olist CGLOB; /* list of optimizable expressions */
|
||||
|
||||
int equalnode(struct enode *node1, struct enode *node2) {
|
||||
/*
|
||||
* equalnode will return 1 if the expressions pointed to by node1 and node2
|
||||
* are equivalent.
|
||||
*/
|
||||
if (node1 == 0 || node2 == 0)
|
||||
return 0;
|
||||
if (node1->nodetype != node2->nodetype)
|
||||
return 0;
|
||||
switch (node1->nodetype) {
|
||||
#ifndef AS
|
||||
case en_labcon:
|
||||
/* FALLTHROUGH - HACK : v.i==(long)v.ensp */
|
||||
case en_icon:
|
||||
#else
|
||||
case en_labcon:
|
||||
return (node1->v.enlab == node2->v.enlab);
|
||||
case en_icon:
|
||||
#endif
|
||||
case en_autocon:
|
||||
case en_tempref: // note: this one is not necessary when doing CSE, but can be useful in gen68k.c
|
||||
/*infunc("chk_curword")
|
||||
if (node2->v.i=(long)(char)0xCD)
|
||||
bkpt();*/
|
||||
return (node1->v.i == node2->v.i);
|
||||
case en_nacon:
|
||||
return (!strcmp(node1->v.ensp, node2->v.ensp));
|
||||
case en_ref:
|
||||
case en_fieldref:
|
||||
return equalnode(node1->v.p[0], node2->v.p[0]);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct cse *searchnode(struct enode *node) {
|
||||
/*
|
||||
* searchnode will search the common expression table for an entry that
|
||||
* matches the node passed and return a pointer to it.
|
||||
* the top level of equalnode is code inline here for speed
|
||||
*/
|
||||
register struct cse *csp;
|
||||
register struct enode *ep;
|
||||
if (node == 0)
|
||||
return 0;
|
||||
csp = olist;
|
||||
while (csp != 0) {
|
||||
ep = csp->exp;
|
||||
if (ep != 0 && node->nodetype == ep->nodetype) {
|
||||
switch (node->nodetype) {
|
||||
case en_icon:
|
||||
#ifndef AS
|
||||
case en_labcon:
|
||||
#endif
|
||||
case en_autocon:
|
||||
if (node->v.i == ep->v.i)
|
||||
return csp;
|
||||
break;
|
||||
#ifndef AS
|
||||
case en_nacon:
|
||||
if (!strcmp(node->v.ensp, ep->v.ensp))
|
||||
return csp;
|
||||
break;
|
||||
#endif
|
||||
#ifdef AS
|
||||
case en_labcon:
|
||||
case en_nacon:
|
||||
if (node->v.enlab == ep->v.enlab)
|
||||
return csp;
|
||||
break;
|
||||
#endif
|
||||
case en_ref:
|
||||
if (equalnode(node->v.p[0], ep->v.p[0])) {
|
||||
/* 05/09/03: added check for size ; struct or unions
|
||||
* won't work either since Gen68k needs their address
|
||||
*/
|
||||
if (node->esize != ep->esize || bt_aggregate(node->etype))
|
||||
csp->voidf=1;
|
||||
return csp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
csp = csp->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct enode *copynode(struct enode *node) {
|
||||
/*
|
||||
* copy the node passed into a new enode so it wont get corrupted during
|
||||
* substitution.
|
||||
*/
|
||||
struct enode *temp;
|
||||
if (node == 0)
|
||||
return 0;
|
||||
temp = (struct enode *) xalloc((int) sizeof(struct enode), ENODE+COPYNODE);
|
||||
*temp = *node;
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct cse *enternode(struct enode *node, int duse) {
|
||||
/*
|
||||
* enternode will enter a reference to an expression node into the common
|
||||
* expression table. duse is a flag indicating whether or not this reference
|
||||
* will be dereferenced.
|
||||
*/
|
||||
struct cse *csp;
|
||||
if ((csp = searchnode(node)) == 0) { /* add to tree */
|
||||
csp = (struct cse *) xalloc((int) sizeof(struct cse), CSE+ENTERNODE);
|
||||
csp->next = olist;
|
||||
#ifdef NO_CALLOC
|
||||
csp->uses = 0;
|
||||
csp->duses = 0;
|
||||
csp->voidf = 0;
|
||||
#endif
|
||||
csp->exp = copynode(node);
|
||||
olist = csp;
|
||||
if (bt_aggregate(node->etype))
|
||||
csp->voidf++;
|
||||
} else {
|
||||
/*
|
||||
* Integer constants may be in the table with different sizes -- keep
|
||||
* the maximum size
|
||||
*/
|
||||
if (node->nodetype == en_icon && node->esize > csp->exp->esize)
|
||||
csp->exp->esize = node->esize;
|
||||
}
|
||||
/* infunc("chk_curword")
|
||||
if (node->nodetype != en_icon && node->esize==1)
|
||||
bkpt();*/
|
||||
#ifdef REGALLOC_FOR_SIZE
|
||||
#define exec_count INIT_EXEC_COUNT
|
||||
#endif
|
||||
csp->uses+=exec_count;
|
||||
if (duse)
|
||||
csp->duses+=exec_count;
|
||||
#ifdef REGALLOC_FOR_SIZE
|
||||
#undef exec_count
|
||||
#endif
|
||||
return csp;
|
||||
}
|
||||
|
||||
static struct cse *voidauto(struct enode *node) {
|
||||
/*
|
||||
* voidauto will void an auto dereference node which points to the same auto
|
||||
* constant as node.
|
||||
*/
|
||||
struct cse *csp;
|
||||
csp = olist;
|
||||
while (csp != 0) {
|
||||
if (csp->exp->nodetype==en_ref && equalnode(node, csp->exp->v.p[0])) {
|
||||
if (csp->voidf)
|
||||
return 0;
|
||||
csp->voidf = 1;
|
||||
return csp;
|
||||
}
|
||||
csp = csp->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void scanexpr(struct enode *node, int duse) {
|
||||
/*
|
||||
* scanexpr will scan the expression pointed to by node for optimizable
|
||||
* subexpressions. when an optimizable expression is found it is entered into
|
||||
* the tree. if a reference to an autocon node is scanned the corresponding
|
||||
* auto dereferenced node will be voided. duse should be set if the
|
||||
* expression will be dereferenced.
|
||||
*/
|
||||
struct cse *csp, *csp1;
|
||||
if (node == 0)
|
||||
return;
|
||||
switch (node->nodetype) {
|
||||
case en_nacon:
|
||||
#ifdef FLINE_RC
|
||||
if (fline_rc && node->v.ensp &&
|
||||
node->v.ensp[1]=='R' && node->v.ensp[0]=='_' &&
|
||||
!memcmp(node->v.ensp+2,"OM_CALL_",8))
|
||||
break;
|
||||
#endif
|
||||
/*@fallthrough@*/
|
||||
case en_labcon:
|
||||
#ifndef NO_ICONST_SCAN
|
||||
case en_icon:
|
||||
#endif
|
||||
(void) enternode(node, duse);
|
||||
break;
|
||||
case en_autocon:
|
||||
/*
|
||||
* look if the dereferenced use of the node is in the list, remove it
|
||||
* in this case
|
||||
*/
|
||||
if ((csp = voidauto(node)) != 0) {
|
||||
csp1 = enternode(node, duse);
|
||||
csp1->duses += csp->uses;
|
||||
} else if (duse>=0) // don't enter it otherwise (we can already access it)
|
||||
(void) enternode(node, duse);
|
||||
break;
|
||||
|
||||
case en_ref:
|
||||
case en_fieldref:
|
||||
if (node->v.p[0]->nodetype == en_autocon) {
|
||||
/*infunc("ChargerAdressesData")
|
||||
bkpt();*/
|
||||
{
|
||||
int first = (searchnode(node) == 0);
|
||||
/* infunc("chk_curword") if (node->v.p[0]->v.i==(long)(char)0xCD)
|
||||
bkpt();*/
|
||||
csp = enternode(node, duse);
|
||||
/*
|
||||
* take care: the non-derereferenced use of the autocon node may
|
||||
* already be in the list. In this case, set voidf to 1
|
||||
*/
|
||||
if (searchnode(node->v.p[0]) != 0) {
|
||||
csp->voidf = 1;
|
||||
scanexpr(node->v.p[0], 1);
|
||||
} else if (first) {
|
||||
/* look for register nodes */
|
||||
int i = 0;
|
||||
XLST_TYPE j = (XLST_TYPE)node->v.p[0]->v.i, *p;
|
||||
p=reglst; while (i < regptr) {
|
||||
if (*p++ == j) {
|
||||
csp->voidf--; /* this is not in auto_lst */
|
||||
// if (regalloc[i]>=0) csp->reg=regalloc[i];
|
||||
csp->uses += 256 * INIT_EXEC_COUNT * (100 - i);
|
||||
//csp->duses += 30 * (100 - i); // so we know we don't always need an areg
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
/* set voidf if the node is not in autolst */
|
||||
csp->voidf++;
|
||||
i = autoptr;
|
||||
p=autolst;
|
||||
while (i--)
|
||||
if (*p++ == j) {
|
||||
csp->voidf--;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* even if that item must not be put in a register,
|
||||
* it is legal to put its address therein
|
||||
*/
|
||||
if (csp->voidf)
|
||||
scanexpr(node->v.p[0], 1);
|
||||
}
|
||||
}
|
||||
#ifdef OPT_ROMCALLS
|
||||
} else if (node->v.p[0]->nodetype == en_icon && node->v.p[0]->v.i == 0xC8) {
|
||||
enternode(node, 1);
|
||||
#endif
|
||||
} else {
|
||||
scanexpr(node->v.p[0], 1);
|
||||
}
|
||||
break;
|
||||
case en_uminus:
|
||||
case en_compl:
|
||||
case en_ainc:
|
||||
case en_adec:
|
||||
case en_not:
|
||||
case en_cast:
|
||||
case en_deref:
|
||||
scanexpr(node->v.p[0], duse);
|
||||
break;
|
||||
case en_alloca:
|
||||
scanexpr(node->v.p[0], 0);
|
||||
break;
|
||||
case en_asadd:
|
||||
case en_assub:
|
||||
case en_add:
|
||||
case en_sub:
|
||||
#ifndef NO_IMPROVED_CSE_SCAN
|
||||
if (duse) {
|
||||
if (node->v.p[0]->etype==bt_pointer
|
||||
|| (node->v.p[1]->etype!=bt_pointer && node->v.p[0]->esize==4)
|
||||
|| (node->v.p[1]->esize!=4)) {
|
||||
if (node->v.p[1]->nodetype!=en_icon)
|
||||
scanexpr(node->v.p[0], 1),
|
||||
scanexpr(node->v.p[1], 0);
|
||||
else
|
||||
scanexpr(node->v.p[0], -1);
|
||||
} else scanexpr(node->v.p[0], 0), scanexpr(node->v.p[1], 1);
|
||||
} else
|
||||
#endif
|
||||
scanexpr(node->v.p[0], 0), scanexpr(node->v.p[1], 0);
|
||||
/* scanexpr(node->v.p[0], duse); // why ??
|
||||
scanexpr(node->v.p[1], duse);*/
|
||||
break;
|
||||
case en_mul:
|
||||
case en_div:
|
||||
case en_lsh:
|
||||
case en_rsh:
|
||||
case en_mod:
|
||||
case en_and:
|
||||
case en_or:
|
||||
case en_xor:
|
||||
case en_lor:
|
||||
case en_land:
|
||||
case en_eq:
|
||||
case en_ne:
|
||||
case en_gt:
|
||||
case en_ge:
|
||||
case en_lt:
|
||||
case en_le:
|
||||
case en_asmul:
|
||||
case en_asdiv:
|
||||
case en_asmod:
|
||||
case en_aslsh:
|
||||
case en_asrsh:
|
||||
case en_asand:
|
||||
case en_asor:
|
||||
case en_asxor:
|
||||
case en_cond:
|
||||
case en_void:
|
||||
case en_assign:
|
||||
scanexpr(node->v.p[0], 0);
|
||||
scanexpr(node->v.p[1], 0);
|
||||
break;
|
||||
case en_fcall:
|
||||
scanexpr(node->v.p[0], 1);
|
||||
scanexpr(node->v.p[1], 0);
|
||||
break;
|
||||
case en_compound:
|
||||
scan(node->v.st);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void scan(struct snode *block) {
|
||||
/*
|
||||
* scan will gather all optimizable expressions into the expression list for
|
||||
* a block of statements.
|
||||
*/
|
||||
while (block != 0) {
|
||||
unsigned int old=exec_count;
|
||||
switch (block->stype) {
|
||||
case st_return:
|
||||
case st_expr:
|
||||
opt4(&block->exp);
|
||||
scanexpr(block->exp, 0);
|
||||
break;
|
||||
case st_loop:
|
||||
opt4(&block->exp);
|
||||
scanexpr(block->exp, 0);
|
||||
exec_count*=block->count;
|
||||
scanexpr(block->exp->v.p[0],0); // increase desirability of counter reg allocation
|
||||
scan(block->s1);
|
||||
if (block->v2.e) {
|
||||
opt4(&block->v2.e);
|
||||
scanexpr(block->v2.e, 0);
|
||||
}
|
||||
break;
|
||||
case st_while:
|
||||
case st_do:
|
||||
exec_count*=block->count;
|
||||
exec_count++;
|
||||
opt4(&block->exp);
|
||||
scanexpr(block->exp, 0);
|
||||
exec_count--;
|
||||
scan(block->s1);
|
||||
break;
|
||||
case st_for:
|
||||
opt4(&block->exp);
|
||||
scanexpr(block->exp, 0);
|
||||
exec_count*=block->count;
|
||||
opt4(&block->v1.e);
|
||||
scanexpr(block->v1.e, 0);
|
||||
scan(block->s1);
|
||||
opt4(&block->v2.e);
|
||||
scanexpr(block->v2.e, 0);
|
||||
break;
|
||||
case st_if:
|
||||
opt4(&block->exp);
|
||||
scanexpr(block->exp, 0);
|
||||
exec_count=(unsigned int)(((unsigned long)exec_count*(unsigned long)block->count+32768)>>16);
|
||||
scan(block->s1);
|
||||
exec_count=old-exec_count;
|
||||
scan(block->v1.s);
|
||||
break;
|
||||
case st_switch:
|
||||
opt4(&block->exp);
|
||||
scanexpr(block->exp, 0);
|
||||
exec_count>>=1;
|
||||
scan(block->v1.s);
|
||||
break;
|
||||
case st_case:
|
||||
case st_default:
|
||||
scan(block->v1.s);
|
||||
break;
|
||||
case st_compound:
|
||||
case st_label:
|
||||
scan(block->s1);
|
||||
break;
|
||||
}
|
||||
block = block->next;
|
||||
exec_count=old;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long desire(struct cse *csp) {
|
||||
/*
|
||||
* returns the desirability of optimization for a subexpression.
|
||||
*/
|
||||
#ifdef INFINITE_REGISTERS
|
||||
return 4294967295;
|
||||
#endif
|
||||
if (csp->voidf || (csp->exp->nodetype == en_icon &&
|
||||
// (unsigned int)csp->exp->v.i+8 <= 16))
|
||||
csp->exp->v.i < 16 && csp->exp->v.i >= 0))
|
||||
return 0;
|
||||
#ifdef REGPARM_OLD
|
||||
{ struct enode *ep;
|
||||
if (csp->exp->nodetype == en_ref && (ep=csp->exp->v.p[0])->nodetype == en_autocon
|
||||
&& ep->v.i>0 && (ep->v.i®_PARAMS))
|
||||
return 10000000; // if it's a register param, then it *must* be in a long-live reg
|
||||
}
|
||||
#endif
|
||||
if (g_lvalue(csp->exp))
|
||||
return 2 * csp->uses;
|
||||
return csp->uses;
|
||||
}
|
||||
|
||||
void bsort(struct cse **list) {
|
||||
/*
|
||||
* bsort implements a bubble sort on the expression list.
|
||||
*/
|
||||
struct cse *csp1, *csp2;
|
||||
csp1 = *list;
|
||||
if (csp1 == 0 || csp1->next == 0)
|
||||
return;
|
||||
bsort(&(csp1->next));
|
||||
while (csp1 != 0 && (csp2 = csp1->next) != 0 && desire(csp1) < desire(csp2)) {
|
||||
*list = csp2;
|
||||
csp1->next = csp2->next;
|
||||
csp2->next = csp1;
|
||||
list = &(csp2->next);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REGPARM_OLD
|
||||
extern struct typ *head;
|
||||
#define parm_val (_parm_val+1)
|
||||
XLST_TYPE _parm_val[1+MAX_DATA+1+MAX_ADDR+1];
|
||||
int parm_reg[MAX_DATA+1+MAX_ADDR+1];
|
||||
#endif
|
||||
void allocate(void) {
|
||||
/*
|
||||
* allocate will allocate registers for the expressions that have a high
|
||||
* enough desirability.
|
||||
*/
|
||||
struct cse *csp;
|
||||
struct enode *exptr/*,*ep*/;
|
||||
reg_t datareg, addreg;
|
||||
#ifdef AREG_AS_DREG
|
||||
int areg_possible;
|
||||
#endif
|
||||
unsigned int mask, rmask;
|
||||
struct amode *ap, *ap2;
|
||||
//#define __DEBUG__
|
||||
/*#ifdef __DEBUG__
|
||||
int i=0;*
|
||||
#endif*/
|
||||
regs_used = 0;
|
||||
datareg = MAX_DATA+1;
|
||||
addreg = MAX_ADDR+1 + AREGBASE;
|
||||
mask = 0;
|
||||
rmask = 0;
|
||||
bsort(&olist); /* sort the expression list */
|
||||
csp = olist;
|
||||
/* infunc("play")
|
||||
bkpt();*/ //autoptr=0,regptr=0;
|
||||
while (csp != 0) {
|
||||
/*#ifdef __DEBUG__
|
||||
infunc("play")
|
||||
if (i++==2) {
|
||||
csp->voidf=1;
|
||||
regs_used++;
|
||||
rmask = rmask | (1 << (15 - datareg));
|
||||
mask = mask | (1 << datareg);
|
||||
datareg++;
|
||||
}
|
||||
#endif*/
|
||||
/*
|
||||
* If reg_option is not true, the 'desire' value must be at least
|
||||
* 5000, which I hope can only be achieved by the 'register' attribute
|
||||
*/
|
||||
if (desire(csp) < 3*INIT_EXEC_COUNT || (!reg_option && desire(csp) < 5000))
|
||||
csp->reg = -1;
|
||||
#ifndef AREG_AS_DREG
|
||||
else if (csp->duses &&
|
||||
#else
|
||||
else if ((areg_possible=
|
||||
#endif
|
||||
/* && (csp->duses * 3) > csp->uses */
|
||||
addreg <
|
||||
#ifdef USE_LINK
|
||||
FRAMEPTR
|
||||
#else
|
||||
STACKPTR - uses_link
|
||||
#endif
|
||||
/*
|
||||
* integer constants may have different types
|
||||
*/
|
||||
&& (csp->exp->nodetype == en_icon
|
||||
/*
|
||||
* the types which are fine in address registers
|
||||
*/
|
||||
|| (csp->exp->etype == bt_short ||
|
||||
csp->exp->etype == bt_long ||
|
||||
csp->exp->etype == bt_ulong ||
|
||||
csp->exp->etype == bt_pointer))
|
||||
#ifndef AREG_AS_DREG
|
||||
)
|
||||
#else
|
||||
) && csp->duses)
|
||||
#endif
|
||||
csp->reg = addreg++;
|
||||
else if (datareg < AREGBASE && csp->exp->nodetype!=en_autocon)
|
||||
csp->reg = datareg++;
|
||||
#ifdef AREG_AS_DREG
|
||||
else if (areg_possible)
|
||||
csp->reg = addreg++;
|
||||
#endif
|
||||
else
|
||||
csp->reg = -1;
|
||||
/* infunc("chk_curword")
|
||||
if (csp->reg==AREGBASE+2 || csp->reg==AREGBASE+3 || csp->reg==4)
|
||||
bkpt();*/
|
||||
if (csp->reg IS_VALID) {
|
||||
regexp[reg_t_to_regexp(csp->reg)] = csp->exp;
|
||||
regs_used++;
|
||||
rmask = rmask | (1 << (15 - csp->reg));
|
||||
mask = mask | (1 << csp->reg);
|
||||
}
|
||||
csp = csp->next;
|
||||
}
|
||||
#ifdef ADD_REDUNDANCY
|
||||
if (regs_used>=6) { /* >=6 : won't increase the push/pop time very much */
|
||||
mask = 0x7CF8, rmask = 0x1F3E;
|
||||
regs_used = 10;
|
||||
/* (note that we could use less than 6 as a threshold, but the benefit lies around
|
||||
+0.5% while the runtime cost is rather high for such functions)
|
||||
(note too that the benefit for the optimization with threshold 6 is around 0.5%
|
||||
only, but it is so inexpensive that we really can afford it :] ) */
|
||||
}
|
||||
#endif
|
||||
if (mask != 0) {
|
||||
g_code(op_movem, 4, mk_rmask(rmask), push_am);
|
||||
#ifdef ICODE
|
||||
if (icode_option)
|
||||
fprintf(icode, "\t$regpush %04x\n", rmask);
|
||||
#endif
|
||||
}
|
||||
save_mask = mask;
|
||||
csp = olist;
|
||||
while (csp != 0) {
|
||||
if (csp->reg IS_VALID) { /* see if preload needed */
|
||||
exptr = csp->exp;
|
||||
#ifdef REGPARM_OLD
|
||||
/* the following code works since REGPARM's are always
|
||||
* handled first -- their desire() is highest */
|
||||
if (exptr->nodetype==en_ref && (ep=exptr->v.p[0])->nodetype==en_autocon
|
||||
&& ep->v.i>0 && (ep->v.i®_PARAMS)) {
|
||||
ap = mk_reg(ep->v.i>>REG_PARAMLOG);
|
||||
ap2 = mk_reg(csp->reg);
|
||||
g_code(op_move, (int) exptr->esize, ap, ap2);
|
||||
} else
|
||||
#endif
|
||||
if (exptr->nodetype!=en_ref
|
||||
#ifdef OPT_ROMCALLS
|
||||
|| exptr->v.p[0]->nodetype!=en_autocon
|
||||
#endif
|
||||
#ifdef REGPARM
|
||||
|| ((XLST_TYPE)exptr->v.p[0]->v.i >= -reg_size)) {
|
||||
#else
|
||||
|| ((XLST_TYPE)exptr->v.p[0]->v.i > 0)) {
|
||||
#endif
|
||||
initstack();
|
||||
ap = g_expr(exptr, F_ALL | F_SRCOP);
|
||||
ap2 = mk_reg(csp->reg);
|
||||
g_code(op_move, (int) exptr->esize, ap, ap2);
|
||||
freeop(ap);
|
||||
#ifdef ICODE
|
||||
if (icode_option) {
|
||||
fprintf(icode, "$reg ");
|
||||
if (csp->reg < AREGBASE)
|
||||
fprintf(icode, "D%d\n", csp->reg);
|
||||
else
|
||||
fprintf(icode, "A%d\n", csp->reg - AREGBASE);
|
||||
g_icode(exptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
csp = csp->next;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NO_EXTENDED_AUTOS
|
||||
void repexpr(struct enode *node) {
|
||||
#else
|
||||
#define repexpr(node) _repexpr(&(node))
|
||||
void _repexpr(struct enode **ep) {
|
||||
struct enode *node=*ep;
|
||||
#endif
|
||||
/*
|
||||
* repexpr will replace all allocated references within an expression with
|
||||
* tempref nodes.
|
||||
*/
|
||||
struct cse *csp;
|
||||
if (node == 0)
|
||||
return;
|
||||
switch (node->nodetype) {
|
||||
case en_icon:
|
||||
case en_nacon:
|
||||
case en_labcon:
|
||||
case en_autocon:
|
||||
if ((csp = searchnode(node)) != 0) {
|
||||
if (csp->reg > 0) {
|
||||
node->nodetype = en_tempref;
|
||||
node->v.i = csp->reg;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case en_ref:
|
||||
case en_fieldref:
|
||||
if ((csp = searchnode(node)) != 0) {
|
||||
if (csp->reg > 0) {
|
||||
node->nodetype = en_tempref;
|
||||
node->v.i = csp->reg;
|
||||
} else
|
||||
repexpr(node->v.p[0]);
|
||||
} else
|
||||
repexpr(node->v.p[0]);
|
||||
break;
|
||||
case en_uminus:
|
||||
case en_not:
|
||||
case en_compl:
|
||||
case en_ainc:
|
||||
case en_adec:
|
||||
case en_cast:
|
||||
case en_deref:
|
||||
case en_alloca:
|
||||
repexpr(node->v.p[0]);
|
||||
break;
|
||||
case en_add:
|
||||
if (node->v.p[0]->nodetype==en_autocon && node->v.p[1]->nodetype==en_icon) {
|
||||
/**ep=mk_icon(node->v.p[0]->v.i+node->v.p[1]->v.i);
|
||||
(*ep)->nodetype=en_autocon;
|
||||
(*ep)->etype=bt_pointer;
|
||||
(*ep)->esize=4;*/
|
||||
node->v.p[0]->v.i+=node->v.p[1]->v.i;
|
||||
*ep=node->v.p[0];
|
||||
return;
|
||||
}
|
||||
/*@fallthrough@*/
|
||||
case en_sub:
|
||||
case en_mul:
|
||||
case en_div:
|
||||
case en_mod:
|
||||
case en_lsh:
|
||||
case en_rsh:
|
||||
case en_and:
|
||||
case en_or:
|
||||
case en_xor:
|
||||
case en_land:
|
||||
case en_lor:
|
||||
case en_eq:
|
||||
case en_ne:
|
||||
case en_lt:
|
||||
case en_le:
|
||||
case en_gt:
|
||||
case en_ge:
|
||||
case en_cond:
|
||||
case en_void:
|
||||
case en_asadd:
|
||||
case en_assub:
|
||||
case en_asmul:
|
||||
case en_asdiv:
|
||||
case en_asor:
|
||||
case en_asxor:
|
||||
case en_asand:
|
||||
case en_asmod:
|
||||
case en_aslsh:
|
||||
case en_asrsh:
|
||||
case en_fcall:
|
||||
case en_assign:
|
||||
repexpr(node->v.p[0]);
|
||||
repexpr(node->v.p[1]);
|
||||
break;
|
||||
case en_compound:
|
||||
repcse(node->v.st);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void repcse(struct snode *block) {
|
||||
/*
|
||||
* repcse will scan through a block of statements replacing the optimized
|
||||
* expressions with their temporary references.
|
||||
*/
|
||||
while (block != 0) {
|
||||
switch (block->stype) {
|
||||
case st_return:
|
||||
case st_expr:
|
||||
repexpr(block->exp);
|
||||
break;
|
||||
case st_loop:
|
||||
repexpr(block->exp);
|
||||
repcse(block->s1);
|
||||
repexpr(block->v2.e);
|
||||
break;
|
||||
case st_while:
|
||||
case st_do:
|
||||
repexpr(block->exp);
|
||||
repcse(block->s1);
|
||||
break;
|
||||
case st_for:
|
||||
repexpr(block->exp);
|
||||
repexpr(block->v1.e);
|
||||
repcse(block->s1);
|
||||
repexpr(block->v2.e);
|
||||
break;
|
||||
case st_if:
|
||||
repexpr(block->exp);
|
||||
repcse(block->s1);
|
||||
repcse(block->v1.s);
|
||||
break;
|
||||
case st_switch:
|
||||
repexpr(block->exp);
|
||||
repcse(block->v1.s);
|
||||
break;
|
||||
case st_case:
|
||||
case st_default:
|
||||
repcse(block->v1.s);
|
||||
break;
|
||||
case st_compound:
|
||||
case st_label:
|
||||
repcse(block->s1);
|
||||
break;
|
||||
}
|
||||
block = block->next;
|
||||
}
|
||||
}
|
||||
|
||||
void opt1(struct snode *block) {
|
||||
/*
|
||||
* opt1 is the externally callable optimization routine. it will collect and
|
||||
* allocate common subexpressions and substitute the tempref for all
|
||||
* occurrances of the expression within the block.
|
||||
*
|
||||
*/
|
||||
if (!opt_option)
|
||||
return;
|
||||
olist = 0;
|
||||
exec_count = INIT_EXEC_COUNT;
|
||||
scan(block); /* collect expressions */
|
||||
allocate(); /* allocate registers */
|
||||
repcse(block); /* replace allocated expressions */
|
||||
}
|
||||
// vim:ts=4:sw=4
|
||||
102
gtc/src/bin2calc.c
Normal file
102
gtc/src/bin2calc.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* binary to TI calculator format conversion
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "define.h"
|
||||
#include "gtpack/gtpack.c"
|
||||
|
||||
// This structure comes from ttools.
|
||||
typedef struct {
|
||||
char signature[8]; // "**TI92P*" or "**TI89**"
|
||||
unsigned char fill1[2]; // 01 00
|
||||
char folder[8]; // folder name
|
||||
char desc[40]; // ---- not used ----
|
||||
unsigned char fill2[6]; // 01 00 52 00 00 00
|
||||
char name[8]; // varname
|
||||
unsigned char type[4]; // 0C 00 00 00
|
||||
unsigned char size[4]; // complete file size (including checksum)
|
||||
unsigned char fill3[6]; // A5 5A 00 00 00 00
|
||||
unsigned char datasize[2]; // data size
|
||||
} TI_FILE_HDR;
|
||||
|
||||
|
||||
static void put_little_endian(unsigned char *dest, unsigned long val, int len) {
|
||||
while (len--) {
|
||||
*dest++ = (unsigned char)(val&0xFF);
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
static void put_big_endian(unsigned char *dest, unsigned long val, int len) {
|
||||
dest += len;
|
||||
while (len--) {
|
||||
*--dest = (unsigned char)(val&0xFF);
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
char *create_ti_file(int calc,int tigl_type,char *name,char *folder,char *content,unsigned long content_size,unsigned long *ti_file_size) {
|
||||
TI_FILE_HDR h;
|
||||
memset(&h, 0, sizeof h);
|
||||
memcpy(h.signature, "********", 8);
|
||||
#define sig(x) memcpy(h.signature+2,x,sizeof(x)-1)
|
||||
switch (calc) {
|
||||
case 0:
|
||||
sig("TI89");
|
||||
break;
|
||||
case 1:
|
||||
sig("TI92P");
|
||||
break;
|
||||
case 2:
|
||||
sig("TI92P");
|
||||
break;
|
||||
default:
|
||||
fatal("unknown calc type");
|
||||
}
|
||||
#undef sig
|
||||
h.fill1[0] = 1;
|
||||
strncpy(h.folder, folder?folder:"main", 8);
|
||||
h.fill2[0] = 1; h.fill2[2] = 0x52;
|
||||
strncpy(h.name, name, 8);
|
||||
h.type[0] = tigl_type; h.type[2] = 3;
|
||||
h.fill3[0] = 0xA5; h.fill3[1] = 0x5A;
|
||||
{
|
||||
unsigned long oncalc_size = 88+content_size+2;
|
||||
put_little_endian(h.size, oncalc_size, 4);
|
||||
}
|
||||
put_big_endian(h.datasize, content_size, 2);
|
||||
|
||||
if (content_size>=65520)
|
||||
fatal("TIOS variables can't be more than 65520 bytes long.");
|
||||
|
||||
{
|
||||
char *ret = malloc(sizeof(h)+content_size+2);
|
||||
if (!ret)
|
||||
fatal("Memory");
|
||||
if (ti_file_size)
|
||||
*ti_file_size = sizeof(h)+content_size+2;
|
||||
memcpy(ret, &h, sizeof(h));
|
||||
memcpy(ret+sizeof(h), content, content_size);
|
||||
{
|
||||
unsigned int crc = h.datasize[0]+h.datasize[1];
|
||||
unsigned long n = content_size;
|
||||
while (n--)
|
||||
crc += 0xff & (unsigned char)*content++;
|
||||
put_little_endian(ret+sizeof(h)+content_size, crc, 2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
548
gtc/src/c.h
Normal file
548
gtc/src/c.h
Normal file
@ -0,0 +1,548 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* C
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifndef C_H
|
||||
#define C_H
|
||||
#ifdef PC
|
||||
#ifdef SHORT_INT
|
||||
#undef int
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
//#include <times.h>
|
||||
#include <stdio.h>
|
||||
#ifdef SHORT_INT
|
||||
#define int short
|
||||
#endif
|
||||
#else
|
||||
#include "define.h"
|
||||
#endif
|
||||
//#warning hey hey!
|
||||
#include "error.h"
|
||||
|
||||
#ifdef CPU_DEFINED
|
||||
#undef CPU_DEFINED
|
||||
#endif
|
||||
|
||||
#ifdef MC68000
|
||||
#define MC680X0
|
||||
#ifdef CPU_DEFINED
|
||||
error, define only one target CPU!
|
||||
#endif
|
||||
#define CPU_DEFINED
|
||||
#define LIST_NAME "gtclist.txt"
|
||||
#define ICODE_NAME "gtcicode.txt"
|
||||
#endif
|
||||
|
||||
#ifdef MC68010
|
||||
#define MC680X0
|
||||
#ifdef CPU_DEFINED
|
||||
error, define only one target CPU!
|
||||
#endif
|
||||
#define CPU_DEFINED
|
||||
#define LIST_NAME "gtclist.txt"
|
||||
#define ICODE_NAME "gtcicode.txt"
|
||||
#endif
|
||||
|
||||
#ifdef MC68020
|
||||
#define MC680X0
|
||||
#ifdef CPU_DEFINED
|
||||
error, define only one target CPU!
|
||||
#endif
|
||||
#define CPU_DEFINED
|
||||
#define LIST_NAME "gtclist.txt"
|
||||
#define ICODE_NAME "gtcicode.txt"
|
||||
#endif
|
||||
|
||||
#ifdef MC68030
|
||||
#define MC680X0
|
||||
#ifdef CPU_DEFINED
|
||||
error, define only one target CPU!
|
||||
#endif
|
||||
#define CPU_DEFINED
|
||||
#define LIST_NAME "gtclist.txt"
|
||||
#define ICODE_NAME "gtcicode.txt"
|
||||
#endif
|
||||
|
||||
#ifdef MC68040
|
||||
#define MC680X0
|
||||
#ifdef CPU_DEFINED
|
||||
error, define only one target CPU!
|
||||
#endif
|
||||
#define CPU_DEFINED
|
||||
#define LIST_NAME "gtclist.txt"
|
||||
#define ICODE_NAME "gtcicode.txt"
|
||||
#endif
|
||||
|
||||
#ifdef INTEL_486
|
||||
#ifndef INTEL_386
|
||||
#define INTEL_386
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef INTEL_386
|
||||
#ifdef CPU_DEFINED
|
||||
#error define only one target CPU!
|
||||
#endif
|
||||
#define CPU_DEFINED
|
||||
#define LIST_NAME "c386.list"
|
||||
#define ICODE_NAME "c386.icode"
|
||||
/*
|
||||
* if FUNCS_USE_387 is defined, extra library calls are generated if the
|
||||
* nofpu option is in effect that allows to use code generated by
|
||||
* this compiler to be linked with functions that return values
|
||||
* on the 387 stack
|
||||
*/
|
||||
#define FUNCS_USE_387
|
||||
#endif
|
||||
|
||||
#ifndef CPU_DEFINED
|
||||
#error target CPU type must be defined
|
||||
#endif
|
||||
|
||||
/* the tokens returned from lexical analysis */
|
||||
|
||||
/* assumptions about the order :
|
||||
* none currently (beware of is_lang_ext though) */
|
||||
enum e_sym {
|
||||
// 0x00
|
||||
cconst, iconst, lconst, uconst, ulconst, sconst, rconst, plus, minus,
|
||||
// 0x09
|
||||
divide, lshift, rshift, modop, eq, neq, lt, leq, gt,
|
||||
// 0x12
|
||||
geq, assign, asplus, asminus, astimes, asdivide, asmodop,
|
||||
asuparrow,
|
||||
// 0x1A
|
||||
aslshift, asrshift, asand, asor, autoinc, autodec, hook, compl,
|
||||
// 0x22
|
||||
comma, colon, semicolon, uparrow, openbr, closebr, begin, end,
|
||||
// 0x2A
|
||||
closepa, pointsto, dot, lor, land, not, or, and,
|
||||
// 0x32
|
||||
star, openpa, id, kw_int, kw_char, kw_short, kw_long,
|
||||
kw_void, kw_float, kw_double, kw_struct, kw_union,
|
||||
kw_enum, kw_unsigned, kw_signed, kw_auto, kw_extern,
|
||||
kw_const, kw_volatile,
|
||||
// 0x45
|
||||
kw_register, kw_typedef, kw_static, kw_goto, kw_return,
|
||||
kw_sizeof, kw_break, kw_continue, kw_if, kw_else, kw_for,
|
||||
kw_do, kw_while, kw_switch, kw_case, kw_default,
|
||||
// 0x55
|
||||
eof,
|
||||
// ANSI extensions
|
||||
kw_typeof, dots, kw_alloca,
|
||||
// GTC extensions
|
||||
kw_loop, kw_until, kw_count, kw_eval, // (lang extensions)
|
||||
kw_defined, kw_incbin, kw_softcast, kw_c,
|
||||
// GNU C extensions
|
||||
kw_asm, kwb_constant_p, kw_attr,
|
||||
// ASM keywords
|
||||
kw_dreg, kw_areg, sharp,
|
||||
#ifdef OLD_AMODE_INPUT
|
||||
kw_offs_end,
|
||||
#endif
|
||||
kw_instr,
|
||||
};
|
||||
#define is_lang_ext(__st) (__st>=kw_loop && __st<=kw_eval)
|
||||
|
||||
/* storage classes */
|
||||
|
||||
enum e_sc {
|
||||
sc_static, sc_auto, sc_global, sc_external, sc_type, sc_const,
|
||||
sc_member, sc_label, sc_ulabel, sc_typedef, sc_parms, sc_parms2,
|
||||
sc_define, sc_vamac
|
||||
};
|
||||
|
||||
/* basic data types */
|
||||
|
||||
#ifndef BCDFLT
|
||||
#define bt_size(__x) ((__x)<bt_long?((__x)<bt_short?1:2):4)
|
||||
#define float_size 4
|
||||
#else
|
||||
#ifdef DOUBLE
|
||||
#define bt_size(__x) ((__x)<bt_long?((__x)<bt_short?1:2):((__x)==bt_double?10:4))
|
||||
#define float_size !!! CAUTION, VARIES BETWEEN DOUBLE AND FLOAT !!!
|
||||
#else
|
||||
#define bt_size(__x) ((__x)<bt_long?((__x)<bt_short?1:2):((__x)==bt_float?10:4))
|
||||
#define float_size 10
|
||||
#endif
|
||||
#endif
|
||||
#define bt_uns(__x) ((__x)&1)
|
||||
#define bt_integral(__x) ((__x)<=bt_ulong)
|
||||
#ifndef DOUBLE
|
||||
#define bt_bcd bt_float
|
||||
#define bt_double bt_float
|
||||
#define tp_double tp_float
|
||||
#define bt_scalar(__x) ((__x)<=bt_double)
|
||||
#else
|
||||
#define bt_bcd bt_double
|
||||
#endif
|
||||
#ifdef NOBCDFLT
|
||||
#undef bt_bcd
|
||||
#endif
|
||||
#define bt_comparable(__x) ((__x)<=bt_pointer)
|
||||
#ifndef NOBCDFLT
|
||||
#define bt_aggregate(__x) ((__x)==bt_bcd || (__x)>=bt_struct)
|
||||
#else
|
||||
#define bt_aggregate(__x) ((__x)>=bt_struct)
|
||||
#endif
|
||||
#define bt_uncastable(__x) ((__x)>=bt_struct)
|
||||
#define iscomparable(tp) bt_comparable((tp)->type)
|
||||
#define isscalar(tp) bt_scalar((tp)->type)
|
||||
#define integral(tp) bt_integral((tp)->type)
|
||||
#define isaggregate(tp) bt_aggregate((tp)->type)
|
||||
enum e_bt {
|
||||
bt_char, bt_uchar, bt_short, bt_ushort,
|
||||
bt_long, bt_ulong, bt_float,
|
||||
#ifdef DOUBLE
|
||||
bt_double,
|
||||
#endif
|
||||
bt_pointer,
|
||||
bt_func,
|
||||
bt_void, bt_bitfield,
|
||||
bt_struct, bt_union,
|
||||
};
|
||||
|
||||
/* these form the string literal pool */
|
||||
|
||||
struct slit {
|
||||
struct slit *next;
|
||||
char *str;
|
||||
short label;
|
||||
short len;
|
||||
};
|
||||
|
||||
/* a symbol table */
|
||||
struct stab {
|
||||
int hash;
|
||||
struct sym *head;
|
||||
struct sym *tail;
|
||||
};
|
||||
/* important points for reconsidering N_HASH value :
|
||||
- a HTABLE is about 8*N_HASH -byte long
|
||||
- each imbricated 'compound()' call takes the space of 2 HTABLEs on the stack
|
||||
(512 bytes with N_HASH=32, thus allowing only 20 imbricated compound stmts)
|
||||
- there are 6 static HTABLEs, 7 if AS is defined (but could be improved with malloc() / BSS)
|
||||
- N_HASH = 1 << HASH_LOG */
|
||||
#define N_HASH 32
|
||||
#define N_HASH_AND "31"
|
||||
#define HASH_LOG 5
|
||||
typedef struct hstab {
|
||||
int hash;
|
||||
struct htab {
|
||||
struct sym *head;
|
||||
struct sym *tail;
|
||||
} h[N_HASH];
|
||||
} HTABLE;
|
||||
|
||||
/* structure defining a data type */
|
||||
|
||||
struct typ {
|
||||
struct stab lst;
|
||||
struct typ *btp;
|
||||
#ifdef LISTING
|
||||
char *sname;
|
||||
#endif
|
||||
long size;
|
||||
enum(e_bt) type;
|
||||
/*
|
||||
* The following six chars may be unsigned -- no harm.
|
||||
* They could be ints without restriction -- this is to save memory
|
||||
*/
|
||||
/*
|
||||
* val_flag is normally 0, except for:
|
||||
* - type==bt_pointer: set to 1 if it's an array, to 0 if it's a pointer
|
||||
* - type==bt_func: always set to 1
|
||||
* (passing a function is like passing an array, we should actually be passing a pointer;
|
||||
* and like an array, we do not want cond_deref() to build an en_ref node)
|
||||
* - type==bt_integral: set to 1 to indicate an enum (this feature is currently unused)
|
||||
*/
|
||||
char val_flag;
|
||||
|
||||
char st_flag; // is the type already stored globally?
|
||||
char const_flag; // is it a 'const' type?
|
||||
char vol_flag; // is it a 'volatile' type?
|
||||
char bit_width;
|
||||
char bit_offset;
|
||||
};
|
||||
#ifdef REGPARM
|
||||
#define rp_dn bit_width
|
||||
#define rp_an bit_offset
|
||||
#endif
|
||||
|
||||
/* a symbol table entry */
|
||||
|
||||
struct sym {
|
||||
char *name;
|
||||
struct sym *prev;
|
||||
struct sym *next;
|
||||
struct typ *tp;
|
||||
union {
|
||||
long i;
|
||||
unsigned long u;
|
||||
int splab;
|
||||
char *s;
|
||||
} value;
|
||||
enum(e_sc) storage_class;
|
||||
int used; // note:
|
||||
// - for 'normal' symbols (C variables), this belongs to {-1,0,1}
|
||||
// - for preprocessor symbols, the lower 8 bits is the number of arguments to the macro
|
||||
// and the higher 8 bits are described in enum(e_ppsymflags) below
|
||||
};
|
||||
enum e_ppsymflags {
|
||||
PPSYM_UNDER_EXPANSION = 0x8000, // set if we are currently expanding this symbol (avoid recursive expansion)
|
||||
#ifdef ASM
|
||||
PPSYM_ASM_KEYWORD = 0x4000, // set if this an ASM reserved keyword ('move', 'b', 'w', 'l', 'd7', 'sp')
|
||||
PPSYM_DEFINED_IN_ASM = 0x2000, // set if this symbol was defined inside an asm{} statement
|
||||
#endif
|
||||
};
|
||||
|
||||
#define SYM struct sym
|
||||
#define TYP struct typ
|
||||
#define TABLE struct stab
|
||||
|
||||
#ifdef PC
|
||||
#define MAX_ERROR_COUNT 1
|
||||
#else
|
||||
#define MAX_ERROR_COUNT 1
|
||||
#endif
|
||||
#define MAX_STRLEN 1500
|
||||
#define MAX_ID_LEN 50
|
||||
#ifdef OLD_MACRO
|
||||
#define MAX_MAC_LEN 800
|
||||
#define LINE_LENGTH (1800+MAX_MAC_LEN+1)
|
||||
#else
|
||||
#define LINE_LENGTH (1800+1)
|
||||
#endif
|
||||
#define MAX_PARAMS 20
|
||||
#define REG_LIST 20
|
||||
#define AUTO_LIST 100
|
||||
|
||||
#define ERR_SYNTAX 0 /* general error */
|
||||
#define ERR_ILLCHAR 1 /* illegal character */
|
||||
#define ERR_FPCON 2 /* illegal floating-point constant */
|
||||
#define ERR_ILLTYPE 3 /* illegal type */
|
||||
#define ERR_UNDEFINED 4 /* undefined identifier */
|
||||
#define ERR_FIELD 5 /* no field allowed here */
|
||||
#define ERR_PUNCT 6 /* expected symbol not found */
|
||||
#define ERR_IDEXPECT 7 /* identifier expected */
|
||||
#define ERR_NOINIT 8 /* initialization invalid */
|
||||
#define ERR_INCOMPLETE 9 /* incomplete struct/union/enum declaration */
|
||||
#define ERR_ILLINIT 10 /* illegal initialization */
|
||||
#define ERR_INITSIZE 11 /* too many initializers */
|
||||
#define ERR_ILLCLASS 12 /* illegal storage class */
|
||||
#define ERR_BLOCK 13 /* function body expected */
|
||||
#define ERR_NOPOINTER 14 /* pointer type expected */
|
||||
#define ERR_NOFUNC 15 /* function type expected */
|
||||
#define ERR_NOMEMBER 16 /* struct/union member expected */
|
||||
#define ERR_LVALUE 17 /* l-value required */
|
||||
#define ERR_DEREF 18 /* error dereferencing a pointer */
|
||||
#define ERR_MISMATCH 19 /* type mismatch error */
|
||||
#define ERR_EXPREXPECT 20 /* expression expected */
|
||||
#define ERR_WHILEXPECT 21 /* 'while' expected in do-loop */
|
||||
#define ERR_ENUMVAL 22 /* enum value out of range */
|
||||
#define ERR_DUPCASE 23 /* duplicate case label */
|
||||
#define ERR_LABEL 24 /* undefined label */
|
||||
//#define ERR_PREPROC 25 /* preprocessing error */
|
||||
#define ERR_ARG 26 /* declared Argument missing */
|
||||
#define ERR_WIDTH 27 /* illegal field width */
|
||||
#define ERR_INTEXPR 28 /* illegal constant integer expression */
|
||||
#define ERR_CAST 29 /* error doing a cast */
|
||||
#define ERR_INTEGER 30 /* integer-valued type expected */
|
||||
#define ERR_CASTCON 31 /* error casting a constant */
|
||||
#define ERR_REDECL 32 /* illegal redeclaration */
|
||||
//#define ERR_PARMS 33 /* error while scanning a parameter list */
|
||||
#define ERR_FTYPE 34 /* bad host type for bit fields */
|
||||
#define ERR_INCLFILE 35 /* #include: no include file specified */
|
||||
#define ERR_CANTOPEN 36 /* can't open include file */
|
||||
#define ERR_DEFINE 37 /* wrong #define */
|
||||
#define ERR_CUSTOM 38 /* #error */
|
||||
#define ERR_DUPSYM 39 /* duplicate symbol */
|
||||
#define ERR_CONSTEXPECT 40 /* constant expression expected */
|
||||
#define ERR_OUTRANGE 41 /* value out of range */
|
||||
#define ERR_TOOMPARAMS 42 /* too many parameters to function */
|
||||
#define ERR_TOOFPARAMS 43 /* too few parameters to function */
|
||||
#define ERR_CASERANGE 44 /* invalid case range */
|
||||
#define ERR_UNEXPECTEOF 45 /* unexpected end of file */
|
||||
#define ERR_OTH 46 /* (custom error) */
|
||||
#define ERR_SYS 47 /* (system limitation) */
|
||||
#define ERRA_INVALIDREL 48 /* invalid relocation in expression */
|
||||
|
||||
/* alignment sizes */
|
||||
|
||||
#ifdef MC68000
|
||||
/*
|
||||
* MC68000 is a 16-bit processor. Word alignment is OK in all cases
|
||||
*/
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT 2
|
||||
#define AL_LONG 2
|
||||
#define AL_POINTER 2
|
||||
#define AL_FLOAT 2
|
||||
#define AL_DOUBLE 2
|
||||
#define AL_STRUCT 2
|
||||
#define AL_FUNC 2
|
||||
|
||||
#define AL_DEFAULT 2 /* alignment suitable for all types */
|
||||
#endif /* MC68000 */
|
||||
|
||||
#ifdef MC68010
|
||||
/*
|
||||
* MC68010 is a 16-bit processor. Word alignment is OK in all cases
|
||||
*/
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT 2
|
||||
#define AL_LONG 2
|
||||
#define AL_POINTER 2
|
||||
#define AL_FLOAT 2
|
||||
#define AL_DOUBLE 2
|
||||
#define AL_STRUCT 2
|
||||
#define AL_FUNC 2
|
||||
|
||||
#define AL_DEFAULT 2 /* alignment suitable for all types */
|
||||
#endif /* MC68010 */
|
||||
|
||||
#ifdef MC68020
|
||||
/*
|
||||
* perhaps not necessary, but useful: 32-bit alignment for 32-bit types
|
||||
*/
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT 2
|
||||
#define AL_LONG 4
|
||||
#define AL_POINTER 4
|
||||
#define AL_FLOAT 4
|
||||
#define AL_DOUBLE 4
|
||||
#define AL_STRUCT 4
|
||||
#define AL_FUNC 4
|
||||
|
||||
#define AL_DEFAULT 4 /* alignment suitable for all types */
|
||||
#endif /* MC68020 */
|
||||
|
||||
#ifdef MC68030
|
||||
/*
|
||||
* perhaps not necessary, but useful: 32-bit alignment for 32-bit types
|
||||
*/
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT 2
|
||||
#define AL_LONG 4
|
||||
#define AL_POINTER 4
|
||||
#define AL_FLOAT 4
|
||||
#define AL_DOUBLE 4
|
||||
#define AL_STRUCT 4
|
||||
#define AL_FUNC 4
|
||||
|
||||
#define AL_DEFAULT 4 /* alignment suitable for all types */
|
||||
#endif /* MC68030 */
|
||||
|
||||
#ifdef MC68040
|
||||
/*
|
||||
* perhaps not necessary, but useful: 32-bit alignment for 32-bit types
|
||||
*/
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT 2
|
||||
#define AL_LONG 4
|
||||
#define AL_POINTER 4
|
||||
#define AL_FLOAT 4
|
||||
#define AL_DOUBLE 4
|
||||
#define AL_STRUCT 4
|
||||
#define AL_FUNC 4
|
||||
|
||||
#define AL_DEFAULT 4 /* alignment suitable for all types */
|
||||
#endif /* MC68040 */
|
||||
|
||||
#ifdef INTEL_386
|
||||
/*
|
||||
* perhaps not necessary, but useful: 32-bit alignment for 32-bit types
|
||||
*/
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT 2
|
||||
#define AL_LONG 4
|
||||
#define AL_POINTER 4
|
||||
#define AL_FLOAT 4
|
||||
#define AL_DOUBLE 4
|
||||
#define AL_STRUCT 4
|
||||
#define AL_FUNC 4
|
||||
|
||||
#define AL_DEFAULT 4 /* alignment suitable for all types */
|
||||
#endif /* INTEL_386 */
|
||||
|
||||
|
||||
#ifdef SPARC
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT 2
|
||||
#define AL_LONG 4
|
||||
#define AL_POINTER 4
|
||||
#define AL_FLOAT 4
|
||||
#define AL_DOUBLE 8
|
||||
#define AL_STRUCT 8
|
||||
#define AL_FUNC 4
|
||||
|
||||
#define AL_DEFAULT 8 /* alignment suitable for all types */
|
||||
#endif /* SPARC */
|
||||
|
||||
|
||||
int *_xalloc(int);
|
||||
struct sym *search();
|
||||
struct sym *gsearch();
|
||||
char *strsave();
|
||||
TYP *expression();
|
||||
TYP *exprnc();
|
||||
TYP *cast_op();
|
||||
TYP *mk_type();
|
||||
long intexpr();
|
||||
int getch();
|
||||
//void error();
|
||||
void getsym();
|
||||
void needpunc();
|
||||
void initsym();
|
||||
void append();
|
||||
long strip_icon();
|
||||
long push_param();
|
||||
void do_warning(char *,...);
|
||||
|
||||
struct sym *symremove();
|
||||
void getidstr();
|
||||
void skipspace();
|
||||
void msg(char *s);
|
||||
|
||||
void rel_local();
|
||||
void rel_global();
|
||||
void clean_up();
|
||||
|
||||
void out_init();
|
||||
void out_close();
|
||||
void do_compile();
|
||||
void initpch();
|
||||
void closepch();
|
||||
|
||||
void insert(SYM *sp,HTABLE *table);
|
||||
|
||||
#ifdef DUAL_STACK
|
||||
extern void *dualstack;
|
||||
extern void *ds_currentlo,*ds_currenthi;
|
||||
void ds_allocatleast(unsigned int size);
|
||||
void ds_free(void);
|
||||
#define ds_remaining (unsigned int)((char *)ds_currenthi-(char *)dualstack)
|
||||
#define ds_ensure(size) ((ds_remaining>=(size) ? 0 : ds_allocatleast(size),0), dualstack)
|
||||
#define ds_pop(target) (void)((target)!=ds_currentlo ? (dualstack = (target)) : ds_free(),0)
|
||||
#ifdef PC
|
||||
#define ds_update(ptr) (void)(dualstack=(ptr),dualstack+=(-(size_t)dualstack)&3,0)
|
||||
#else
|
||||
#define ds_update(ptr) (void)(dualstack=(ptr),1&(short)(long)dualstack ? ++dualstack,0 : 0,0)
|
||||
#endif
|
||||
#define ds_var(type) (type)dualstack
|
||||
#define DS_BSIZE 6000 // we set aside 6 kb for each stack block
|
||||
#endif
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
303
gtc/src/cglbdec.h
Normal file
303
gtc/src/cglbdec.h
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* C global declarations
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifndef CGLBDEC_H
|
||||
#define CGLBDEC_H
|
||||
#ifdef PC
|
||||
#define outstr stderr
|
||||
#define msg(s) fprintf(outstr,s)
|
||||
#define msg2(s,a) fprintf(outstr,s,a)
|
||||
#define msg3(s,a,b) fprintf(outstr,s,a,b)
|
||||
#define msg4(s,a,b,c) fprintf(outstr,s,a,b,c)
|
||||
#define msg5(s,a,b,c,d) fprintf(outstr,s,a,b,c,d)
|
||||
#define msg6(s,a,b,c,d,e) fprintf(outstr,s,a,b,c,d,e)
|
||||
#define vmsg(s,va) vfprintf(outstr,s,va)
|
||||
#else
|
||||
#define msg printf
|
||||
#define msg2(s,a) printf(s,a)
|
||||
#define msg3(s,a,b) printf(s,a,b)
|
||||
#define msg4(s,a,b,c) printf(s,a,b,c)
|
||||
#define msg5(s,a,b,c,d) printf(s,a,b,c,d)
|
||||
#define msg6(s,a,b,c,d,e) printf(s,a,b,c,d,e)
|
||||
#undef vcbprintf
|
||||
#define vcbprintf ({register long __a=32+*(long*)(*(long*)0xC8+0x14C); \
|
||||
(void(*)(void(*)(char,void**),void**,char*,void*))(__a+*(short*)__a);})
|
||||
#define vmsg(s,va) vcbprintf((void(*)(char,void**))fputchar,NULL,s,va)
|
||||
#endif
|
||||
|
||||
#define int_bits 16
|
||||
#define tp_int tp_short
|
||||
#define tp_uint tp_ushort
|
||||
#define fpu_option 0
|
||||
#define short_option 1
|
||||
#ifdef LISTING
|
||||
#define list_option 1
|
||||
#else
|
||||
#define list_option 0
|
||||
#endif
|
||||
#define reg_option 1
|
||||
#define opt_option 1
|
||||
#define warn_option 1
|
||||
#define trans_option 0
|
||||
#ifdef ICODE
|
||||
#define icode_option 1
|
||||
#else
|
||||
#define icode_option 0
|
||||
#endif
|
||||
enum e_xt {
|
||||
X_MID_DECL=0x1, X_COMP_STRING=0x2, X_LANG_EXT=0x4,
|
||||
};
|
||||
#define flags_fullgtc -1 /* all flags, even those that break compatibility */
|
||||
#define flags_basegtc (X_MID_DECL|X_COMP_STRING) /* all flags, except those that break compatibility */
|
||||
#define flags_cplusplus X_MID_DECL
|
||||
#define flags_ansi 0
|
||||
extern int flags;
|
||||
#ifdef SPEED_OPT
|
||||
extern int speed_opt_value;
|
||||
extern int default_speed_opt_value;
|
||||
#endif
|
||||
extern int verbose;
|
||||
#ifdef PC
|
||||
enum {
|
||||
VERBOSITY_PRINT_SEARCH_DIRS=0x1,
|
||||
VERBOSITY_PRINT_INCLUDES=0x2,
|
||||
};
|
||||
extern int verbosity;
|
||||
#endif
|
||||
|
||||
extern FILE *input, *list, *output;
|
||||
extern char *outputname,*calcname;
|
||||
extern char proj_file[];
|
||||
extern char export_pfx[]; extern short_size export_pfx_len;
|
||||
#ifdef ICODE
|
||||
extern FILE *icode;
|
||||
#endif
|
||||
extern int nextlabel;
|
||||
extern int lastch;
|
||||
extern enum(e_sym) lastst;
|
||||
#ifdef PC
|
||||
extern enum(e_sym) cached_sym;
|
||||
#else
|
||||
extern enum(e_sym) _cached_sym;
|
||||
#endif
|
||||
extern int cached_flag;
|
||||
extern char lastid[MAX_ID_LEN+1];
|
||||
extern int lastcrc;
|
||||
extern int lastreg;
|
||||
extern struct sym *lastsp;
|
||||
extern char laststr[MAX_STRLEN + 1];
|
||||
extern int lstrlen;
|
||||
extern unsigned long ival;
|
||||
#ifndef NOFLOAT
|
||||
extern double rval;
|
||||
#endif
|
||||
|
||||
extern HTABLE gsyms, lsyms, labsyms, gtags, ltags;
|
||||
|
||||
extern struct slit *strtab;
|
||||
extern struct slit *datatab;
|
||||
extern XLST_TYPE lc_auto;
|
||||
extern XLST_TYPE reg_size;
|
||||
extern XLST_TYPE max_scratch;
|
||||
extern XLST_TYPE act_scratch;
|
||||
extern long lc_bss; /* local bss counter */
|
||||
extern int global_flag;
|
||||
extern int global_strings;
|
||||
extern int temp_mem,temp_local,min_temp_mem;
|
||||
extern int asm_flag,asm_xflag,asm_zflag;
|
||||
extern int nostub_mode;
|
||||
extern int exestub_mode;
|
||||
#ifdef MC680X0
|
||||
extern unsigned int save_mask; /* register save mask */
|
||||
#endif
|
||||
extern char *declid;
|
||||
extern int nparms;
|
||||
extern int store_lst;
|
||||
extern int pch_init;
|
||||
extern int middle_decl;
|
||||
extern char *names[MAX_PARAMS];
|
||||
extern int bit_offset; /* the actual offset */
|
||||
extern int bit_width; /* the actual width */
|
||||
extern int bit_next; /* offset for next variable */
|
||||
extern int decl1_level;
|
||||
|
||||
#ifdef ASM
|
||||
extern struct ocode *asm_head;
|
||||
#endif
|
||||
#ifdef AS
|
||||
extern struct ocode *scope_head;
|
||||
#else
|
||||
#ifdef ASM
|
||||
extern struct ocode *peep_head;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef FLINE_RC
|
||||
extern int fline_rc;
|
||||
#endif
|
||||
|
||||
//extern int list_option;
|
||||
//extern int short_option;
|
||||
//extern int opt_option;
|
||||
//extern int trans_option;
|
||||
//extern int warn_option;
|
||||
//extern int fpu_option;
|
||||
//extern int reg_option;
|
||||
//#ifdef ICODE
|
||||
//extern int icode_option;
|
||||
//#endif
|
||||
extern TYP *ret_type;
|
||||
|
||||
extern int regptr;
|
||||
extern XLST_TYPE reglst[REG_LIST];
|
||||
extern int autoptr;
|
||||
extern XLST_TYPE autolst[AUTO_LIST];
|
||||
|
||||
extern struct enode *init_node;
|
||||
#ifdef MID_DECL_IN_EXPR
|
||||
extern struct enode *md_expr;
|
||||
extern struct typ *md_type;
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSE
|
||||
extern struct tms tms_buf;
|
||||
extern long decl_time, parse_time, opt_time, gen_time, flush_time;
|
||||
#endif /* VERBOSE */
|
||||
|
||||
extern readonly TYP tp_void, tp_long, tp_ulong, tp_char, tp_uchar;
|
||||
extern readonly TYP tp_short, tp_ushort, tp_float;
|
||||
extern readonly TYP tp_econst, tp_string, tp_void_ptr, tp_int, tp_uint, tp_func;
|
||||
extern readonly TYP tp_double;
|
||||
|
||||
//extern int int_bits;
|
||||
|
||||
#ifdef MC680X0
|
||||
extern readonly struct amode push, pop;
|
||||
#define push_am (struct amode *)&push
|
||||
#define pop_am (struct amode *)&pop
|
||||
#endif
|
||||
/*extern int uses_structassign;*/
|
||||
extern int regs_used;
|
||||
extern int pushed;
|
||||
extern int is_leaf_function, uses_link;
|
||||
#ifdef INTEL_386
|
||||
extern int edi_used, esi_used, ebx_used;
|
||||
#endif
|
||||
|
||||
extern int lineno,lineid,lastch;
|
||||
extern int prevlineid,cached_lineid;
|
||||
|
||||
extern int err_force_line,err_cur_line,err_assembly;
|
||||
|
||||
#ifdef DECLARE
|
||||
extern TYP *head, *tail;
|
||||
|
||||
extern int total_errors;
|
||||
|
||||
/*extern FILE *input,
|
||||
*list,
|
||||
*output,
|
||||
*bin;*/
|
||||
|
||||
//extern long ival;
|
||||
extern double rval;
|
||||
|
||||
extern SYM *lasthead;
|
||||
extern struct slit *strtab;
|
||||
extern struct slit *datatab;
|
||||
extern int lc_static;
|
||||
//extern int lc_auto;
|
||||
extern struct snode *bodyptr;
|
||||
extern int global_flag;
|
||||
//extern int save_mask; /* register save mask */
|
||||
extern SYM *func_sp;
|
||||
|
||||
extern TYP *lastexpr_tp;
|
||||
extern int lastexpr_size, lastexpr_type;
|
||||
#endif
|
||||
extern struct amode *lastexpr_am;
|
||||
extern int need_res;
|
||||
|
||||
extern SYM *func_sp;
|
||||
|
||||
#ifdef TWIN_COMPILE
|
||||
extern int twinc_necessary;
|
||||
extern int *twinc_info,*twinc_prev;
|
||||
#endif
|
||||
|
||||
SYM *search(char *na, int crc, HTABLE *tab);
|
||||
void dodecl(enum(e_sc) defclass);
|
||||
int eq_type(TYP *tp1, TYP *tp2);
|
||||
|
||||
#ifndef integral
|
||||
int integral(TYP *tp);
|
||||
#endif
|
||||
int isshort(struct enode *node);
|
||||
int isbyte(struct enode *node);
|
||||
|
||||
int radix36(char c);
|
||||
|
||||
int equal_address();
|
||||
|
||||
int crcN(char *na);
|
||||
|
||||
#ifdef ASM
|
||||
void asm_getsym();
|
||||
#endif
|
||||
|
||||
extern HTABLE defsyms;
|
||||
|
||||
#define MAX_IF_DEPTH 50
|
||||
extern int ifdepth,ifreldepth,ifskip,ifsd;
|
||||
extern int ifcount[MAX_IF_DEPTH];
|
||||
extern int ifval[MAX_IF_DEPTH];
|
||||
#endif
|
||||
|
||||
#ifndef PCHS_MODES
|
||||
#define PCHS_MODES
|
||||
enum { PCHS_ADD=1, PCHS_UNLOAD=-1 };
|
||||
#endif
|
||||
|
||||
#ifdef USE_MEMMGT
|
||||
/*
|
||||
* Memory is allocated in blocks of 4 kb, which form a linked list
|
||||
*/
|
||||
|
||||
#define BLKLEN 4096
|
||||
|
||||
#ifndef BLK_STRUCT
|
||||
#define BLK_STRUCT
|
||||
struct blk {
|
||||
char m[BLKLEN]; /* memory area */
|
||||
struct blk *next;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define NIL_BLK ((struct blk *)0)
|
||||
|
||||
extern int glbsize, /* size left in current global block */
|
||||
locsize, /* size left in current local block */
|
||||
glbindx, /* global index */
|
||||
locindx; /* local index */
|
||||
|
||||
extern int glbmem,locmem;
|
||||
|
||||
extern struct blk *locblk, /* pointer to local block list */
|
||||
*glbblk; /* pointer to global block list */
|
||||
|
||||
void tmp_use();
|
||||
void tmp_free();
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
675
gtc/src/cmain.c
Normal file
675
gtc/src/cmain.c
Normal file
@ -0,0 +1,675 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* main entry point
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#define CMAIN_C
|
||||
#define DECLARE
|
||||
|
||||
#ifdef PC
|
||||
#ifdef _WIN32
|
||||
#define DIR_SEPARATOR '\\'
|
||||
#define ENVPATH_SEPARATOR ';'
|
||||
#else
|
||||
#ifdef UNIXOID
|
||||
#define DIR_SEPARATOR '/'
|
||||
#define ENVPATH_SEPARATOR ':'
|
||||
#else
|
||||
#error Please define a directory and a $PATH separator for your platform.
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PC
|
||||
/*
|
||||
#define memcmp memcmp2
|
||||
#define strcmp stricmp
|
||||
//#define strlen strlen2
|
||||
#define abs abs2
|
||||
#define _rotl _rotl2
|
||||
#define _rotr _rotr2
|
||||
//#include <signal.h>
|
||||
|
||||
// --> what was this crap ???
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
|
||||
extern char *curname;
|
||||
|
||||
#ifdef SPEED_OPT
|
||||
int default_speed_opt_value CGLOB;
|
||||
#endif
|
||||
|
||||
static void openfile();
|
||||
static void closefile();
|
||||
static void initialize_files();
|
||||
static void close_files();
|
||||
#ifdef LISTING
|
||||
static summary();
|
||||
#endif
|
||||
|
||||
#ifdef PC
|
||||
void fatal(char *s);
|
||||
#else
|
||||
void fatal(char *s) __attribute__ ((noreturn));
|
||||
#endif
|
||||
|
||||
#ifdef PC
|
||||
#ifndef debug
|
||||
void debug(int c) {
|
||||
fprintf(stderr,"debug step '%c'\n",c);
|
||||
}
|
||||
#endif
|
||||
#ifdef EXCEPTION_MGT
|
||||
static void exception(int sig) {
|
||||
msg2("\n\nSIGNAL %d -- TERMINATING.\n", sig);
|
||||
fatal("EXCEPTION");
|
||||
}
|
||||
#endif
|
||||
#define _exit __exit
|
||||
int pause_on_error=0;
|
||||
void _exit(int code) {
|
||||
clean_up();
|
||||
if (pause_on_error)
|
||||
getchar();
|
||||
exit(code);
|
||||
}
|
||||
#endif
|
||||
|
||||
char export_pfx[20]; short_size export_pfx_len;
|
||||
|
||||
#ifdef TWIN_COMPILE
|
||||
int twinc_necessary CGLOB;
|
||||
int *twinc_info CGLOB,*twinc_info0 CGLOB,*twinc_prev CGLOB,*twinc_prev0 CGLOB;
|
||||
#endif
|
||||
|
||||
#ifdef PC
|
||||
char *calcfolder=0;
|
||||
static char _calcfolder[100];
|
||||
char *outputname=0,*calcname=0;
|
||||
static char _calcname[100];
|
||||
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#if 0
|
||||
void TempName(char *dest) {
|
||||
int i;
|
||||
srand(clock());
|
||||
*dest++='~';
|
||||
*dest++='g';
|
||||
*dest++='t';
|
||||
*dest++='c';
|
||||
for (i=0;i<4;i++)
|
||||
*dest++='0'+(rand()*10)/(RAND_MAX+1);
|
||||
strcpy(dest,".tmp");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* warning: duplicated in getsym.c! */
|
||||
enum OptionModes { optn_parse=0, optn_global_init, optn_global_init_post, optn_preproc_init };
|
||||
size_t option_parse(size_t listc,char **listv,enum(OptionModes) ex_mode);
|
||||
void option_parse_all(enum(OptionModes) ex_mode);
|
||||
|
||||
char *incfolders[10] CGLOBL;
|
||||
size_t incfoldernum CGLOB;
|
||||
|
||||
size_t optnc,optnmax; char **optnv;
|
||||
size_t filec,filemax; char **filev;
|
||||
|
||||
#define LST_INIT(lst,len) (lst##c=0, lst##max=(len), lst##v=alloca((len)*sizeof(*lst##v)))
|
||||
#define LST_ADD(lst,val) (lst##c>=lst##max?exit(EXIT_FAILURE):(void)0, lst##v[lst##c++]=(val))
|
||||
|
||||
void cmdline_parse(size_t argc, char **argv) {
|
||||
size_t i;
|
||||
int force_files = 0;
|
||||
for (i=1; i<argc; ) {
|
||||
size_t listc = argc-i, skip;
|
||||
char **listv = &argv[i];
|
||||
char *arg = listv[0];
|
||||
if (!force_files && arg[0] == '-') {
|
||||
if (!strcmp(arg,"--")) {
|
||||
force_files = 1;
|
||||
i++;
|
||||
} else {
|
||||
if ((skip = option_parse(listc,listv,optn_parse))) {
|
||||
size_t j;
|
||||
for (j=0; j<skip; j++)
|
||||
LST_ADD(optn,listv[j]);
|
||||
i+=j;
|
||||
} else {
|
||||
msg2("Invalid option '%s', ignoring option.\n", arg);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LST_ADD(file,arg);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void search_installdir(char *exe_name) {
|
||||
char *gtcpath=alloca(strlen(exe_name)+40);
|
||||
strcpy(gtcpath,exe_name);
|
||||
if (strrchr(gtcpath,DIR_SEPARATOR)) strrchr(gtcpath,DIR_SEPARATOR)[1]=0; // strip 'gtc.exe'
|
||||
else {
|
||||
#if 0
|
||||
gtcpath=""; // 'gtc.exe' is in the current folder... (this assumption is OK under Win9x)
|
||||
#else
|
||||
// things don't stop here as WinXP sets argv[0] to be 'gtc.exe' if it is in the
|
||||
// PATH environment variable... (and the same goes for Unixoids)
|
||||
char *path=getenv("PATH");
|
||||
while ((gtcpath="",path)) {
|
||||
char *limit=strchr(path,ENVPATH_SEPARATOR),*base_limit=limit; char *buf;
|
||||
FILE *fp;
|
||||
if (!limit) limit=path+strlen(path);
|
||||
if (path[0]=='"' && path[limit-path-1]=='"')
|
||||
path++,limit--;
|
||||
gtcpath=alloca(limit-path+2);
|
||||
memcpy(gtcpath,path,(size_t)(limit-path)); gtcpath[limit-path]=DIR_SEPARATOR; gtcpath[limit-path+1]=0;
|
||||
buf=alloca(strlen(gtcpath)+sizeof("gtc.exe"));
|
||||
strcpy(buf,gtcpath);
|
||||
strcat(buf,"gtc.exe");
|
||||
if ((fp=fopen(buf,"rb"))) {
|
||||
fclose(fp);
|
||||
break;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
strcpy(buf,gtcpath);
|
||||
strcat(buf,"gtc");
|
||||
if ((fp=fopen(buf,"rb"))) {
|
||||
fclose(fp);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
path = base_limit ? base_limit+1 : NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
{
|
||||
char *incl_cmd=malloc(sizeof("-I")-1+strlen(gtcpath)+sizeof("include"));
|
||||
assert(incl_cmd!=0);
|
||||
strcpy(incl_cmd,"-I");
|
||||
strcat(incl_cmd,gtcpath);
|
||||
strcat(incl_cmd,"include");
|
||||
LST_ADD(optn,incl_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int _argc, char **argv) {
|
||||
size_t argc = (size_t)_argc;
|
||||
LST_INIT(optn,argc+10);
|
||||
LST_INIT(file,argc+10);
|
||||
#ifdef UNIXOID
|
||||
pause_on_error=0;
|
||||
#endif
|
||||
|
||||
// initialize optn* and file*
|
||||
cmdline_parse(argc, argv);
|
||||
search_installdir(argv[0]);
|
||||
#ifdef INCL_PATH
|
||||
LST_ADD(optn,"-I"INCL_PATH);
|
||||
#endif
|
||||
|
||||
// now setup options
|
||||
// defaults
|
||||
calcfolder=NULL; outputname=NULL; calcname=NULL;
|
||||
tp_econst = tp_int;
|
||||
tp_econst.val_flag=1;
|
||||
// user-defined options
|
||||
option_parse_all(optn_global_init);
|
||||
option_parse_all(optn_global_init_post);
|
||||
|
||||
if (verbosity&VERBOSITY_PRINT_SEARCH_DIRS)
|
||||
verbose_print_searchdirs();
|
||||
|
||||
#ifdef TWIN_COMPILE
|
||||
twinc_info0=0;
|
||||
do {
|
||||
twinc_prev0=twinc_prev=twinc_info0;
|
||||
twinc_info=twinc_info0=malloc(100000);
|
||||
twinc_necessary=0;
|
||||
#endif
|
||||
initialize_files();
|
||||
out_init();
|
||||
/* initsym();
|
||||
getch();
|
||||
getsym();
|
||||
compile();*/
|
||||
initpch();
|
||||
{
|
||||
size_t optnc_save = optnc; // for twin compilation
|
||||
size_t i;
|
||||
for (i=0; i<filec; i++) {
|
||||
if (i==1) // the current version of the library needs it :(
|
||||
LST_ADD(optn,"-D__SECONDARY_FILE__");
|
||||
openfile(i);
|
||||
do_compile();
|
||||
closefile();
|
||||
}
|
||||
optnc = optnc_save;
|
||||
}
|
||||
closepch();
|
||||
#ifdef LISTING
|
||||
if (list_option)
|
||||
summary();
|
||||
else
|
||||
/* This emits all the global and external directives */
|
||||
list_table(&gsyms, 0);
|
||||
#endif
|
||||
#ifdef VERBOSE
|
||||
msg("\n -- %d errors found.\n", total_errors);
|
||||
#endif
|
||||
out_close();
|
||||
// rel_global(); in out_close()
|
||||
close_files();
|
||||
#ifdef TWIN_COMPILE
|
||||
if (twinc_prev0) free(twinc_prev0);
|
||||
} while (twinc_necessary);
|
||||
free(twinc_info0);
|
||||
#endif
|
||||
#ifdef VERBOSE
|
||||
decl_time -= parse_time;
|
||||
parse_time -= gen_time + flush_time;
|
||||
gen_time -= opt_time;
|
||||
msg("Times: %6ld + %6ld + %6ld + %6ld + %6ld\n",
|
||||
decl_time, parse_time, opt_time, gen_time, flush_time);
|
||||
#endif
|
||||
if (total_errors > 0)
|
||||
_exit(1);
|
||||
if (temp_mem)
|
||||
printf("TEMP MEM LEAK\n"), temp_mem=0;
|
||||
return 0;
|
||||
}
|
||||
#else /* !defined(PC) */
|
||||
#ifdef OPTIMIZE_BSS
|
||||
#define PRI_MAIN
|
||||
void _zmain(void);
|
||||
#include "identity.h"
|
||||
int has_error CGLOB;
|
||||
#ifndef GTDEV
|
||||
void _main(void) {
|
||||
bssdata=malloc(BSS_SIZE);
|
||||
if (!bssdata) return;
|
||||
memset(bssdata,0,BSS_SIZE);
|
||||
has_error=1;
|
||||
asm("movem.l d0-d7/a0-a4/a6,-(a7)"); /* do not include 'a5' :o */
|
||||
_zmain();
|
||||
asm("movem.l (a7)+,d0-d7/a0-a4/a6");
|
||||
bssdata=identity(bssdata); /* volatilize 'bssdata' =) */
|
||||
if (bssdata) { /* in case 'input' or 'output' couldn't be opened... */
|
||||
if (bin) free(bin);
|
||||
fclose(output);
|
||||
fclose(input);
|
||||
free(bssdata);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void _main(void) {
|
||||
ST_helpMsg("Please use the IDE to compile.");
|
||||
ngetchx();
|
||||
}
|
||||
#endif
|
||||
#ifdef GTDEV
|
||||
void _gtdevmain(void) {
|
||||
has_error=1;
|
||||
asm("movem.l d0-d7/a0-a4/a6,-(a7)"); /* do not include 'a5' :o */
|
||||
_zmain();
|
||||
asm("movem.l (a7)+,d0-d7/a0-a4/a6");
|
||||
bssdata=identity(bssdata); /* volatilize 'bssdata' =) */
|
||||
if (bssdata) { /* in case 'input' or 'output' couldn't be opened... */
|
||||
if (bin) free(bin);
|
||||
fclose(output);
|
||||
fclose(input);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void _zmain(void) {
|
||||
#else
|
||||
void _main(void) {
|
||||
#endif
|
||||
int n;
|
||||
#ifndef GTDEV
|
||||
clrscr();
|
||||
#endif
|
||||
// __HALT;
|
||||
/* tp_econst = tp_int;
|
||||
tp_econst.val_flag=1;*/
|
||||
#ifndef PRI_MAIN
|
||||
#ifdef OPTIMIZE_BSS
|
||||
bssdata=malloc(BSS_SIZE);
|
||||
if (!bssdata) return;
|
||||
memset(bssdata,0,BSS_SIZE);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GTDEV
|
||||
#define in_file "in"
|
||||
#ifdef AS
|
||||
#define out_file "outbin"
|
||||
#else
|
||||
#define out_file "out"
|
||||
#endif
|
||||
#endif
|
||||
if (!(input=fopen(in_file,"r"))) goto quit;
|
||||
#ifdef AS
|
||||
if (!(output=fopen(out_file,"wb"))) { fclose(input); quit: free(bssdata); bssdata=0; return; }
|
||||
#else
|
||||
if (!(output=fopen(out_file,"w"))) { fclose(input); quit: free(bssdata); bssdata=0; return; }
|
||||
#endif
|
||||
|
||||
/*********************************************************
|
||||
* [!BUG-SOURCE!] THE FOLLOWING LINE IS FAIRLY GORE SO *
|
||||
* *ANY* MODIFICATION WHATSOEVER TO _MAIN (OR EVEN ANY *
|
||||
* COMPILER UPDATE...) MIGHT BREAK COMPATIBILITY! *
|
||||
* */
|
||||
#ifndef GTDEV
|
||||
/**/ asm("lea 12(%sp),%a0\n move.l %a0,exit_a7"); /**/
|
||||
#else
|
||||
/**/ asm("lea 4(%sp),%a0\n move.l %a0,exit_a7"); /**/
|
||||
#endif
|
||||
/* *
|
||||
*********************************************************/
|
||||
out_init();
|
||||
initpch();
|
||||
strcpy(export_pfx,strrchr(in_file,'\\')?:in_file);
|
||||
strcat(export_pfx,"__"); export_pfx_len=strlen(export_pfx);
|
||||
do_compile();
|
||||
closepch();
|
||||
debug('E');
|
||||
out_close();
|
||||
debug('Q');
|
||||
// rel_global(); in out_close()
|
||||
if (ferror(output)) fatal("Memory");
|
||||
#ifndef PRI_MAIN
|
||||
fclose(output);
|
||||
fclose(input);
|
||||
#endif
|
||||
#ifndef GTDEV
|
||||
if (temp_mem) printf("TEMP MEM LEAK\n"), temp_mem=0;
|
||||
#endif
|
||||
/* if (total_errors > 0) { printf("\nThere were errors."); while (!kbhit()); }
|
||||
else*/ {
|
||||
#ifdef PRI_MAIN
|
||||
has_error=0;
|
||||
#endif
|
||||
#ifndef GTDEV
|
||||
FILE *fp=fopen("gtcerr","wb");
|
||||
if (fp) {
|
||||
fputc(0,fp);
|
||||
fputc(POSINT_TAG,fp);
|
||||
fclose(fp);
|
||||
}
|
||||
printf("\nsuccess");
|
||||
n=4000;
|
||||
while (n-- && !kbhit());
|
||||
if (kbhit()) ngetchx();
|
||||
#endif
|
||||
}
|
||||
#ifndef PRI_MAIN
|
||||
#ifdef OPTIMIZE_BSS
|
||||
free(bssdata);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif /* !defined(PC) */
|
||||
|
||||
|
||||
#ifdef PC
|
||||
int forbid_bss=0;
|
||||
|
||||
char *fill_calcvar(char *buffer, char *input) {
|
||||
int i=0;
|
||||
while (*input) {
|
||||
char c=tolower(*input++);
|
||||
if (c=='-' || c==' ' || c=='.')
|
||||
c='_';
|
||||
if (isalnum(c) && i<8)
|
||||
buffer[i++] = c;
|
||||
}
|
||||
buffer[i]=0;
|
||||
if (!buffer[0])
|
||||
fatal("bad calculator variable name");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Takes as an input the list of remaining arguments, returning:
|
||||
// * 0: can't parse the option
|
||||
// * n>0: the option was parsed successfully, n = number of arguments
|
||||
// to skip for this option
|
||||
size_t option_parse(size_t listc,char **listv,enum(OptionModes) ex_mode) {
|
||||
char *s = listv[0];
|
||||
size_t value = 1; // number of arguments read so far
|
||||
char *next_chunk, *_next_chunk;
|
||||
#define strscmp(s,t) (next_chunk=_next_chunk="", strcmp(s,t))
|
||||
#define strbcmp(s,t) (next_chunk=_next_chunk=s+strlen(t), strncmp(s,t,strlen(t)))
|
||||
// get_next_chunk is only necessary if you want to handle options split into several arguments
|
||||
#define get_next_chunk() \
|
||||
do { \
|
||||
next_chunk = *_next_chunk ? _next_chunk : listc > value ? listv[value++] : NULL; \
|
||||
if (!next_chunk) return 0; \
|
||||
} while (0)
|
||||
|
||||
// PURELY SYNTACTIC TRANSFORMATIONS
|
||||
if (!strscmp(s,"-exe"))
|
||||
s = "-DEXE_OUT";
|
||||
|
||||
// STANDALONE OPTIONS (strscmp)
|
||||
if (!strscmp(s,"-o")) {
|
||||
get_next_chunk();
|
||||
if (ex_mode==optn_global_init)
|
||||
outputname = next_chunk;
|
||||
} else if (!strscmp(s,"-v")) {
|
||||
#ifdef PC
|
||||
verbose=1;
|
||||
#endif
|
||||
#ifdef PC
|
||||
} else if (!strscmp(s,"-print-search-dirs")) {
|
||||
verbosity|=VERBOSITY_PRINT_SEARCH_DIRS;
|
||||
} else if (!strscmp(s,"-print-includes")) {
|
||||
verbosity|=VERBOSITY_PRINT_INCLUDES;
|
||||
#endif
|
||||
} else if (!strscmp(s,"-mno-bss")) {
|
||||
if (ex_mode==optn_global_init)
|
||||
forbid_bss=1;
|
||||
} else if (!strcmp(s,"-O2")) {
|
||||
default_speed_opt_value = 1;
|
||||
} else if (!strcmp(s,"-O3")) {
|
||||
default_speed_opt_value = 3;
|
||||
} else if (!strcmp(s,"-Os")) {
|
||||
default_speed_opt_value = -1;
|
||||
// CHUNKED OPTIONS (strbcmp)
|
||||
} else if (!strbcmp(s,"-I")) {
|
||||
get_next_chunk();
|
||||
if (ex_mode==optn_global_init)
|
||||
if (incfoldernum<sizeof(incfolders)/sizeof(*incfolders))
|
||||
incfolders[incfoldernum++] = next_chunk;
|
||||
} else if (!strbcmp(s,"--std-include=")) {
|
||||
get_next_chunk();
|
||||
if (ex_mode==optn_global_init_post)
|
||||
if (incfoldernum<sizeof(incfolders)/sizeof(*incfolders))
|
||||
incfolders[incfoldernum++] = next_chunk;
|
||||
} else if (!strbcmp(s,"-D")) {
|
||||
if (ex_mode==optn_preproc_init) {
|
||||
struct sym *sp = (SYM *)xalloc((int)sizeof(SYM), _SYM);
|
||||
char *name = next_chunk;
|
||||
char *name_end = strchr(name,'=');
|
||||
if (!name_end)
|
||||
name_end = name+strlen(name);
|
||||
sp->name = (char *)xalloc(name_end-name+1, STR);
|
||||
memcpy(sp->name, name, (size_t)(name_end-name));
|
||||
sp->name[name_end-name] = 0;
|
||||
sp->value.s = *name_end ? name_end+1 : "1";
|
||||
insert(sp,&defsyms);
|
||||
}
|
||||
// LONG OPTIONS
|
||||
} else if (!strbcmp(s,"--")) {
|
||||
// STANDALONE OPTIONS (strscmp)
|
||||
if (!strscmp(s,"--nobss")) {
|
||||
if (ex_mode==optn_global_init)
|
||||
forbid_bss=1;
|
||||
// CHUNKED OPTIONS (strbcmp)
|
||||
} else if (!strbcmp(s,"--folder=")) {
|
||||
if (ex_mode==optn_global_init)
|
||||
calcfolder = fill_calcvar(_calcfolder,next_chunk);
|
||||
} else if (!strbcmp(s,"--output=")) {
|
||||
if (ex_mode==optn_global_init)
|
||||
calcname = fill_calcvar(_calcname,next_chunk);
|
||||
// ERROR
|
||||
} else
|
||||
return 0;
|
||||
// ERROR
|
||||
} else
|
||||
return 0;
|
||||
return value;
|
||||
#undef get_next_chunk
|
||||
#undef strbcmp
|
||||
#undef strscmp
|
||||
}
|
||||
void option_parse_all(enum(OptionModes) ex_mode) {
|
||||
size_t i;
|
||||
for (i=0; i<optnc; )
|
||||
i += option_parse(optnc-i, &optnv[i], ex_mode);
|
||||
}
|
||||
|
||||
static char _outputname[300];
|
||||
char proj_file[300];
|
||||
#ifdef PC
|
||||
char tempname[20];
|
||||
#endif
|
||||
static void openfile(size_t idx) {
|
||||
if (!(input = fopen(curname=filev[idx], "r"))) {
|
||||
msg2("can't open input file '%s'\n",curname);
|
||||
_exit(2);
|
||||
}
|
||||
}
|
||||
static void closefile() {
|
||||
fclose(input);
|
||||
}
|
||||
// obtain the last part delimited by the character c
|
||||
// (e.g. "xxx/yyy/zzz" -> "zzz", and "zzz" -> "zzz")
|
||||
static char *strlast(char *s,char c) {
|
||||
char *t = strrchr(s,c);
|
||||
return t ? t+1 : s;
|
||||
}
|
||||
|
||||
static void initialize_files() {
|
||||
if (filec < 1) {
|
||||
msg("no input file specified!\n");
|
||||
_exit(2);
|
||||
}
|
||||
|
||||
if (!outputname) {
|
||||
outputname = _outputname;
|
||||
strncpy(outputname,filev[0],sizeof(_outputname)-1);
|
||||
outputname[sizeof(_outputname)-1]=0;
|
||||
if (strrchr(outputname,'.'))
|
||||
*strrchr(outputname,'.')=0;
|
||||
}
|
||||
strncpy(proj_file,outputname,sizeof(proj_file)-4-1);
|
||||
proj_file[sizeof(proj_file)-4-1]=0;
|
||||
strcat(proj_file,".gtc");
|
||||
|
||||
if (!calcname) {
|
||||
char *zcalcname;
|
||||
calcname = outputname;
|
||||
calcname = strlast(calcname,'\\'); // for Windows
|
||||
calcname = strlast(calcname,'/'); // for Unix
|
||||
zcalcname = alloca(strlen(calcname)+1);
|
||||
strcpy(zcalcname,calcname);
|
||||
if (strrchr(zcalcname,'.'))
|
||||
*strrchr(zcalcname,'.')=0;
|
||||
calcname = fill_calcvar(_calcname,zcalcname);
|
||||
}
|
||||
strcpy(export_pfx,calcname);
|
||||
strcat(export_pfx,"__"); export_pfx_len=strlen(export_pfx);
|
||||
#ifndef AS
|
||||
{
|
||||
char *buffer=alloca(strlen(outputname)+strlen(".asm")+1);
|
||||
sprintf(buffer,"%s.asm",outputname);
|
||||
if (!(output = fopen(buffer, "w"))) {
|
||||
msg("can't open output file\n");
|
||||
_exit(2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef LISTING
|
||||
if (list_option && (list = fopen(LIST_NAME, "w")) == 0) {
|
||||
msg("can't open listfile\n");
|
||||
_exit(1);
|
||||
}
|
||||
#endif
|
||||
#ifdef ICODE
|
||||
if (icode_option && ((icode = fopen(ICODE_NAME, "w")) == 0)) {
|
||||
msg("can't open icode file\n");
|
||||
_exit(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LISTING
|
||||
static void summary(void) {
|
||||
// if (gsyms.head != NULL) {
|
||||
fprintf(list, "\f\n *** global scope symbol table ***\n\n");
|
||||
list_table(&gsyms, 0);
|
||||
// }
|
||||
// if (gtags.head != NULL) {
|
||||
fprintf(list, "\n *** structures and unions ***\n\n");
|
||||
list_table(>ags, 0);
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PC
|
||||
static void close_files(void) {
|
||||
#ifdef LISTING
|
||||
if (list_option)
|
||||
fclose(list);
|
||||
#endif
|
||||
#ifdef ICODE
|
||||
if (icode_option)
|
||||
fclose(icode);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PC
|
||||
void fatal(char *message) {
|
||||
debug('f');
|
||||
clean_up();
|
||||
msg2("Fatal error!\n%s\n", message);
|
||||
#ifdef PC
|
||||
fflush(outstr);
|
||||
if (pause_on_error)
|
||||
getchar();
|
||||
exit(EXIT_FAILURE);
|
||||
#else
|
||||
// while (!kbhit());
|
||||
ngetchx();
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
1657
gtc/src/decl.c
Normal file
1657
gtc/src/decl.c
Normal file
File diff suppressed because it is too large
Load Diff
378
gtc/src/define.h
Normal file
378
gtc/src/define.h
Normal file
@ -0,0 +1,378 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* #define's
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
//#define SHOWSTEP
|
||||
|
||||
#ifndef DEFINE_H
|
||||
#define DEFINE_H
|
||||
#if 0
|
||||
#ifdef PC
|
||||
#define debugcls() (void)0
|
||||
#define debugf printf
|
||||
#else
|
||||
#define debugcls clrscr
|
||||
extern int progr;
|
||||
#define debugf(f...) (printf(f),progr_process(func_sp?func_sp->name:0,curname,progr),ngetchx())
|
||||
#endif
|
||||
#define debugfq printf
|
||||
#else
|
||||
#define debugcls() (void)0
|
||||
#if defined(PC) && !defined(__GNUC__)
|
||||
/*@unused@*/ static void debugf(char *s,...) {}
|
||||
/*@unused@*/ static void debugfq(char *s,...) {}
|
||||
#else
|
||||
#define debugf(f...) (void)0
|
||||
#define debugfq(f...) (void)0
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(PC) || !defined(DEBUGGING)
|
||||
#define enum(tp) unsigned int // some compilers make enums signed, make them happy
|
||||
#else
|
||||
#define enum(tp) enum tp // we want nice debugging output
|
||||
#endif
|
||||
#define IS_VALID >=0
|
||||
#define IS_INVALID <0
|
||||
#define nxtlabel() (short)(nextlabel++)
|
||||
#ifdef AS
|
||||
#define nxtglabel() (short)(glblabel++)
|
||||
#else
|
||||
#define nxtglabel() (short)(nextlabel++)
|
||||
#endif
|
||||
#define local(__l) (__l>=0)
|
||||
#define global(__l) (((unsigned short)__l)<0xC000) // only valid if !local(__l)
|
||||
#define external(__l) (((unsigned short)__l)>=0xC000)
|
||||
#ifdef PC
|
||||
#define splbl(__sp) (__sp->value.splab?__sp->value.splab:(__sp->value.splab=label(__sp->name)))
|
||||
#else
|
||||
#define splbl(__sp) (__sp->value.splab?:(__sp->value.splab=label(__sp->name)))
|
||||
#endif
|
||||
#ifdef PC
|
||||
#define TWIN_COMPILE
|
||||
#endif
|
||||
#define DUAL_STACK // save space on the stack by allocating on a temporary buffer just the size we need
|
||||
#ifdef PC
|
||||
#define OBJ_OUT
|
||||
#endif
|
||||
|
||||
//#define INFINITE_REGISTERS // compile for a virtual machine with an arbitrarily high number of registers
|
||||
#ifdef DISABLE_OPTS
|
||||
#undef VCG
|
||||
#endif
|
||||
#define USE_WORDS_IN_SWITCH // use dc.w instead of dc.l in 'real' switch statements
|
||||
#define NEW_ATTR // allows TI-GCC-like attribute declaration
|
||||
#ifdef PC
|
||||
#ifndef DISABLE_OPTS
|
||||
#define ADV_OPT // is it worth the extra exe size & comp time ? => disabled on-calc
|
||||
#endif
|
||||
#endif
|
||||
#ifdef VCG
|
||||
#define GENERATE_ROL_ROR // optimize (x<<12)|(x>>4) into a ror; depends on VCG because commutativity is not tested
|
||||
#endif
|
||||
//#define NO_ICONST_SCAN
|
||||
//#define ALTERNATE_HOOK
|
||||
#define OPT_ROMCALLS // assumes that *(void **)0xC8 is never modified
|
||||
//#define DEFAULT_STKPARM
|
||||
#define TWOBYTE_ARRAY_EXTRA_OPT // {add.w d3,a0;add.w d3,a0} instead of
|
||||
// {move.w d3,d0;add.w d0,d0;add.w d0,a0}
|
||||
//#define AREG_AS_DREG // some fine-tune should be done before this switch provides any benefit
|
||||
#define PREFER_POS_VALUES // allows for better CSE collection (seems like there's a bug in
|
||||
// Optimize which is fixed or reduced by this switch too...)
|
||||
#define ADVANCED_TEMP_REGS // to be fit one day in Gen68k in order to optimize free temp regs
|
||||
#if 0
|
||||
#define ADVANCED_MEMORY_MOVE // optimize contiguous sequences of move's (< auto_init/g_fcall)
|
||||
// (rather time-consuming, for very low consequences...
|
||||
// => disabled, even on PC)
|
||||
#endif
|
||||
#ifdef PC // only valid on PC!
|
||||
#define REQ_MGT // enable required files management
|
||||
#endif
|
||||
#define MULTIFILE // enable multiple file support
|
||||
#define OPTIMIZED_AINCDEC_TEST // allows for dbf too
|
||||
#define LONG_ADDS_IN_AREG // so that lea can be used rather than addi.l
|
||||
//#define NO_OFFSET_AUTOCON // useless as of now
|
||||
#define ADD_REDUNDANCY // increases compression ratios at the cost of function-overhead speed
|
||||
#define REGALLOC_FOR_SIZE
|
||||
//#define HARDCORE_FOR_UNPACKED_SIZE // favour size wherever possible, with little improvement
|
||||
// of packed size and even more probably regression (lsl.w #2...)
|
||||
#define SPEED_OPT
|
||||
//#define speed_opt_value 1 // we may add n instruction before the bra (1 : useful for dbf)
|
||||
//#define G_CAST2 // this might remove some op_ext's : to be tested
|
||||
#define RAM_CALLS // support for RAM_CALLs
|
||||
#ifdef PC
|
||||
#define FLINE_RC // support for F-Line ROM_CALLs
|
||||
#endif
|
||||
#define SHORT_STRUCT_PASSING // allows HSym to be defined as a structure
|
||||
#ifdef PC
|
||||
#define EXE_OUT // output an EXE program (implementation incomplete)
|
||||
#endif
|
||||
#define NO_SECURE_POINTERS // assert that all array accesses are less than 32kb
|
||||
//#define POP_OPT // still buggy as of now
|
||||
#define NO_TRIVIAL_CASTS // suppresses trivial en_cast's ; might add bugs, but not certain
|
||||
#define NO_VERYTRIVIAL_CASTS // suppresses obvious en_cast's ; was already there, but possibly buggy
|
||||
#define MID_DECL // allows for powerful middle decl handler
|
||||
#define MINIMAL_SIZES // so that (long)x>>(char)y won't be converted to (long)x>>(long)y
|
||||
//#define USE_SWAP_FOR_SHIFT16 // use op_swap wherever possible for shifts (buggy, FIXME)
|
||||
#define AUTOINIT_PAD // pad auto_init statements ('side' requires this, for example)
|
||||
#define MACRO_PPDIR
|
||||
#define MEXP_SUPPORTS_PCH // this is mandatory for TiGccLib's RR_* support.
|
||||
// The way speed is affected I don't know, but perhaps it's
|
||||
// faster with this option enabled... (slightly more PCH
|
||||
// searches, very slightly fewer HTable searches)
|
||||
// Some tests should be performed about this.
|
||||
// TODO:
|
||||
// - add FAVOUR_RELATIVE_BSS directive so that once a BSS is CSE'd, all other BSS
|
||||
// refer to it rather than to the classical BSS (what's more, CSE::scan should favour
|
||||
// such optimizations by doing some sort of most_used_BSS_cse->desire += (other_BSS_cse's)>>1)
|
||||
// This would allow for intensive use of BSS :)
|
||||
// - add RELATIVE_CSE directive so that when constantly using mylib__0000+2,
|
||||
// CSE searches for all mylib__0000 occurrences and finds out that it's better to use
|
||||
// mylib__0000+2 (replacing should take this into a count)
|
||||
// -- but complicated and not *that* useful...
|
||||
#if !defined(NONSTD_MACRO_CONCAT) && !defined(NONSTD_MACRO_CONCAT_V2)
|
||||
#define STD_MACRO_CONCAT
|
||||
#endif
|
||||
#define EXT_AS_ID // enabled since the dirty getch() management of .b/.w/.l is no more necessary
|
||||
#if defined(NOFLOAT) || !defined(BCDFLT)
|
||||
#define NOBCDFLT
|
||||
#endif
|
||||
#ifndef AS
|
||||
#ifdef AS92p
|
||||
#define FORBID_TABLES
|
||||
#endif
|
||||
#endif
|
||||
#define push_local_mem_ctx() { int _locsize=locsize,_locindx=locindx; \
|
||||
struct blk *_locblk=locblk; locblk=0; locsize=0
|
||||
#define pop_local_mem_ctx() rel_local(); locsize=_locsize; locindx=_locindx; locblk=_locblk; }
|
||||
#define put_align(__a) put_align2()
|
||||
#ifdef VCG
|
||||
#define VCG_MAX 5
|
||||
#endif
|
||||
#ifdef EXE_OUT
|
||||
#ifdef PC
|
||||
//#ifndef _DEBUG
|
||||
#define SIZE_STATS // include statistics to determine the part of code generated from C code
|
||||
//#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FLASH_VERSION
|
||||
#define HAS_CMDLINE_EXTENSION
|
||||
#endif
|
||||
#ifdef BIGSTACK
|
||||
#define XLST_TYPE long
|
||||
#define REG_PARAMS 0xF000
|
||||
#define REG_PARAMLOG 12
|
||||
#else
|
||||
#define XLST_TYPE int
|
||||
/* limits the param size to 2 kb - not much of a problem ;) */
|
||||
#define REG_PARAMS 0x7800
|
||||
#define REG_PARAMLOG 11
|
||||
#endif
|
||||
#ifndef HAS_TI_SHORT
|
||||
#ifdef PC
|
||||
typedef struct {
|
||||
unsigned char x0,x1,x2,x3;
|
||||
} TI_LONG;
|
||||
typedef struct {
|
||||
unsigned char hi,lo;
|
||||
} TI_SHORT;
|
||||
#else
|
||||
typedef unsigned long TI_LONG;
|
||||
typedef unsigned short TI_SHORT;
|
||||
#endif
|
||||
#ifdef PC
|
||||
extern unsigned long _w2ul(TI_LONG *p);
|
||||
extern unsigned short _w2us(TI_SHORT *p);
|
||||
#define w2ul(x) _w2ul(&(x))
|
||||
#define w2us(x) _w2us(&(x))
|
||||
#else
|
||||
#define w2ul(x) (x)
|
||||
#define w2us(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef NOFLOAT
|
||||
#ifndef PC
|
||||
#ifndef BCDFLT
|
||||
#define double long
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifndef NOBCDFLT
|
||||
#define BCDLEN 8
|
||||
typedef struct bcd {
|
||||
unsigned short exponent;
|
||||
unsigned char mantissa[BCDLEN];
|
||||
} BCD;
|
||||
#endif
|
||||
#ifdef PC
|
||||
#define infunc(f) if (!strcmp(func_sp->name,f))
|
||||
#define bkpt() printf("")
|
||||
#define DB_POSSIBLE
|
||||
#define DEBUG 1
|
||||
#ifdef SHORT_INT
|
||||
#define int short
|
||||
#endif
|
||||
#ifdef CMAIN_C
|
||||
long alloc[3][0xE000];
|
||||
#else
|
||||
extern long alloc[][0xE000];
|
||||
#endif
|
||||
enum myEnum {
|
||||
ANONYMOUS=0, COPYNODE=1, ENTERNODE=2, STRINGLIT=3, LITLATE=4,
|
||||
STRSAVE=5, MK_TYPE=6, _DECLARE=7, DECLENUM=8, ENUMBODY=9,
|
||||
DECLSTRUCT=0xA, SV_TYPE=0xB, MK_NODE=0xC, MK_ICON=0xD,
|
||||
NAMEREF=0xE, FUNCBODY=0xF, MK_INT=0x10, MK_SCRATCH=0x11,
|
||||
MK_LABEL=0x12, MK_IMMED=0x13, MK_OFFSET=0x14, COPY_ADDR=0x15,
|
||||
G_DEREF=0x16, G_EXPR=0x17, MK_REG=0x18, MK_MASK=0x19,
|
||||
MK_STRLAB=0x1A, GENLOOP=0x1B, G_CODE=0x1C, G_LABEL=0x1D,
|
||||
DODEFINE=0x1E, G_PUSH=0x1F, TEMP_DATA=0x20, TEMP_ADDR=0x21,
|
||||
SYMBOL=0x22, REF_ADD=0x23, LAB_ADD_REF=0x24, RT_ADD_REF=0x25,
|
||||
ENODE=0x1000, CSE=0x2000, SLIT=0x3000, STR=0x4000, _TYP=0x5000,
|
||||
_SYM=0x6000, AMODE=0x7000, OCODE=0x8000, _TABLE=0x9000,
|
||||
SNODE=0xA000, _TAB=0xB000, _REF=0xC000, _RT=0xD000,
|
||||
};
|
||||
#define xalloc(s,c) (alloc[temp_mem?2:!!global_flag][(c)]+=(s)+((s)&1),_xalloc(((s)+3)&-4))
|
||||
#define _FILE(x)
|
||||
#define dseg() while (0)
|
||||
#define cseg() while (0)
|
||||
#define compound_done getsym
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4033 4013 4716 4715 4133)
|
||||
#pragma warning (disable : 4996) // strcpy/fopen/... are declared deprecated in VC++ 2005 :D
|
||||
#ifdef SHORT_INT
|
||||
#pragma warning (disable : 4305 4244 4761)
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SHORT_INT
|
||||
#undef int
|
||||
#endif
|
||||
#define debug(x) ((void)0)
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#ifndef _MSC_VER
|
||||
#ifndef __MINGW32__
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#else
|
||||
#define alloca _alloca
|
||||
#endif
|
||||
#ifdef SHORT_INT
|
||||
#define int short
|
||||
#endif
|
||||
#ifndef max
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
#define getline getline_gtc
|
||||
typedef size_t short_size;
|
||||
#else
|
||||
#define infunc(f) if (0)
|
||||
#define bkpt() {}
|
||||
#define DB_POSSIBLE
|
||||
#define DEBUG 0
|
||||
#define xalloc(__s,__c) _xalloc(__s+(__s&1))
|
||||
//#define _FILE(x) asm(".ascii \""x"\";.even");
|
||||
#define _FILE(__x)
|
||||
#define cached_sym (int)_cached_sym
|
||||
#define AS92p
|
||||
#ifndef CMAIN_C
|
||||
#define NOSTUB
|
||||
#define _rom_call(type,args,ind) (*(type(**)args)(*(long*)0xC8+0x##ind*4))
|
||||
#else
|
||||
#include "lib_map.h"
|
||||
#define USE_KERNEL
|
||||
//#define USE_FULL_LONGMUL_PATCH
|
||||
//#define USE_FULL_LONGDIV_PATCH
|
||||
int _ti89;
|
||||
#endif
|
||||
#ifndef gtc_compiled
|
||||
#include <tigcclib.h>
|
||||
#else
|
||||
#define FILE void
|
||||
#define NULL (void *)0
|
||||
#endif
|
||||
#undef off
|
||||
//#define stkparm
|
||||
#ifndef FLASH_VERSION
|
||||
#define debug(x) ((void)0)
|
||||
#undef clrscr
|
||||
#define clrscr gtcrt__0000
|
||||
#undef printf
|
||||
#define printf gtcrt__0001
|
||||
#undef vcbprintf
|
||||
#define vcbprintf gtcrt__0002
|
||||
#undef fopen
|
||||
#define fopen gtcrt__0008
|
||||
FILE *fopen(const char *,const char *);
|
||||
#undef fclose
|
||||
#define fclose gtcrt__0009
|
||||
#undef fputc
|
||||
#define fputc gtcrt__000a
|
||||
int fputc(int,FILE *);
|
||||
#undef fgetc
|
||||
#define fgetc gtcrt__000b
|
||||
#undef fwrite
|
||||
#define fwrite gtcrt__000c
|
||||
int fwrite(void *,int,int,FILE *);
|
||||
#undef fputs
|
||||
#define fputs gtcrt__0010
|
||||
#undef fgets
|
||||
#define fgets gtcrt__0011
|
||||
char *fgets(char *,int,FILE *);
|
||||
#undef fprintf
|
||||
#define fprintf gtcrt__0014
|
||||
#else
|
||||
#define debug(x) ((void)0) // for flash ver
|
||||
#undef fclose
|
||||
#define fclose my_fclose // fix buggy fclose
|
||||
void my_fclose(FILE *f);
|
||||
#define OPTIMIZE_BSS
|
||||
#define BSS_SIZE 8192
|
||||
#endif /* FLASH_VERSION */
|
||||
|
||||
typedef short short_size;
|
||||
|
||||
//#undef printf
|
||||
//#undef fputchar
|
||||
//#define printf print
|
||||
//#define printf(f...) (((void(*)(void*,char*,...))prtf)(fputchar,##f))
|
||||
//#define fputchar ((short(*)(char))ptch)
|
||||
#endif
|
||||
#ifndef FLASH_VERSION
|
||||
#define CGLOB =0
|
||||
#define CGLOBL ={0}
|
||||
#define xstatic static
|
||||
#define readonly
|
||||
#else
|
||||
#define CGLOB
|
||||
#define CGLOBL
|
||||
#define xstatic
|
||||
#define readonly const
|
||||
#endif
|
||||
|
||||
#include "protos.h"
|
||||
#ifndef nl
|
||||
void nl(void);
|
||||
#endif
|
||||
#ifndef PC
|
||||
char *__attribute__((stkparm)) sUnpack(char *in,char *out,char *dic);
|
||||
#else
|
||||
char *sUnpack(char *in,char *out,char *dic);
|
||||
#endif
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
150
gtc/src/error.c
Normal file
150
gtc/src/error.c
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* error handling
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
/*#include "define.h"
|
||||
#include "c.h"
|
||||
#include "cglbdec.h"*/
|
||||
#include <stdarg.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
extern int pause_on_error;
|
||||
|
||||
#ifndef GTDEV
|
||||
//#ifdef PC
|
||||
void _err_attr err_int(int m) {
|
||||
clean_up();
|
||||
msg2("\nAn internal error occurred (error ID #%04d)\n"
|
||||
"Please report this bug to paul.froissart@libertysurf.fr\n",m);
|
||||
#ifdef PC
|
||||
fflush(outstr);
|
||||
if (pause_on_error)
|
||||
getchar();
|
||||
exit(16);
|
||||
#else
|
||||
ngetchx();
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
void err_usr(int m,...) {
|
||||
va_list args;
|
||||
va_start(args,m);
|
||||
#ifdef PC
|
||||
if (verbose)
|
||||
#endif
|
||||
msg("\nCompilation error:\n");
|
||||
if (err_force_line IS_INVALID && err_assembly)
|
||||
err_force_line=err_cur_line;
|
||||
locate();
|
||||
if (m==ERR_OTH) {
|
||||
char *s=va_arg(args,char *);
|
||||
vmsg(s,args);
|
||||
} else
|
||||
vmsg((char *)__err[m],args);
|
||||
msg("\n");
|
||||
va_end(args);
|
||||
clean_up();
|
||||
#ifdef PC
|
||||
fflush(outstr);
|
||||
if (pause_on_error)
|
||||
getchar();
|
||||
exit(16);
|
||||
#else
|
||||
ngetchx();
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
void _err_attr warn_int(int m) {
|
||||
msg2("\nAn unexpected event occurred (event ID #%04d)\n"
|
||||
"It might be possible to continue, but the generated code may "
|
||||
"contain bugs.\nDo you want to continue [y/n]?",m);
|
||||
#ifdef PC
|
||||
fflush(outstr);
|
||||
if ((pause_on_error && (msg("\nn\n"),1)) || getchar()=='n') {
|
||||
clean_up();
|
||||
exit(16);
|
||||
}
|
||||
msg("\n");
|
||||
#else
|
||||
while (!kbhit());
|
||||
if (ngetchx()=='n') {
|
||||
clean_up();
|
||||
exit(0);
|
||||
} else msg("\n");
|
||||
#endif
|
||||
}
|
||||
void warn_usr(char *s,...) {
|
||||
va_list args;
|
||||
va_start(args,s);
|
||||
locate();
|
||||
msg("warning: ");
|
||||
vmsg(s,args);
|
||||
msg("\n");
|
||||
va_end(args);
|
||||
}
|
||||
//#endif
|
||||
#else
|
||||
void _err_attr error_do(char *msg,int type) {
|
||||
char _func[100],file[40];
|
||||
char *func=0;
|
||||
int line,chr=0;
|
||||
if (func_sp) strcpy(func=_func,func_sp->name);
|
||||
strcpy(file,curname);
|
||||
if (err_force_line IS_INVALID && err_assembly)
|
||||
err_force_line=err_cur_line;
|
||||
if (err_force_line IS_VALID)
|
||||
line=err_force_line;
|
||||
else line=lineno,chr=0/*to be improved*/;
|
||||
if (et_iserror(type))
|
||||
clean_up();
|
||||
msg_process(msg,type,func,file,line,chr);
|
||||
if (et_iserror(type))
|
||||
exit(0);
|
||||
}
|
||||
void _noreturn assert_terminated();
|
||||
asm("assert_terminated:\n rts\n");
|
||||
void _err_attr err_int(int m) {
|
||||
char b[30];
|
||||
sprintf(b,"error ID #%04d",m);
|
||||
error_do(b,ET_INTERNAL_FAILURE);
|
||||
assert_terminated();
|
||||
}
|
||||
void err_usr(int m,...) {
|
||||
va_list args;
|
||||
va_start(args,m);
|
||||
char b[200];
|
||||
if (m==ERR_OTH) {
|
||||
char *s=va_arg(args,char *);
|
||||
vsprintf(b,s,args);
|
||||
} else
|
||||
vsprintf(b,(char *)__err[m],args);
|
||||
va_end(args);
|
||||
error_do(b,ET_ERROR);
|
||||
assert_terminated();
|
||||
}
|
||||
void _err_attr warn_int(int m) {
|
||||
char b[30];
|
||||
sprintf(b,"event ID #%04d",m);
|
||||
error_do(b,ET_INTERNAL_WARNING);
|
||||
}
|
||||
void warn_usr(char *s,...) {
|
||||
va_list args;
|
||||
va_start(args,s);
|
||||
char b[200];
|
||||
vsprintf(b,s,args);
|
||||
va_end(args);
|
||||
error_do(b,ET_WARNING);
|
||||
}
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
58
gtc/src/error.h
Normal file
58
gtc/src/error.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* error handling
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#define error(x) uerr(x)
|
||||
#define ierr(f,n) err_int(((FUNC_##f)<<8)+n)
|
||||
#define uerr err_usr
|
||||
#define uerrc(m) uerr(ERR_OTH,m)
|
||||
#define uerrc2(m,a) uerr(ERR_OTH,m,a)
|
||||
#define uerrc3(m,a,b) uerr(ERR_OTH,m,a,b)
|
||||
#define uerrsys(m) uerr(ERR_SYS,m)
|
||||
#define iwarn(f,n) warn_int(((FUNC_##f)<<8)+n)
|
||||
#define uwarn warn_usr
|
||||
|
||||
#ifdef PC
|
||||
#define _noreturn
|
||||
#define _err_attr
|
||||
#else
|
||||
#define _noreturn __attribute__((noreturn))
|
||||
#define _err_attr
|
||||
//#define _err_attr __attribute__((regparm(1)))
|
||||
#endif
|
||||
|
||||
void _noreturn fatal(char *message);
|
||||
void _noreturn _err_attr err_int(int e);
|
||||
void _noreturn err_usr(int e,...);
|
||||
void _err_attr warn_int(int w);
|
||||
void warn_usr(char *w,...);
|
||||
|
||||
// rules for adding new items : add them *ALWAYS* at the end
|
||||
enum {
|
||||
FUNC_NONE=0,
|
||||
|
||||
/*$01*/ FUNC_ALIGNMENT, FUNC_MK_LEGAL, FUNC_COPY_ADDR, FUNC_G_DEREF, FUNC_G_UNARY,
|
||||
/*$06*/ FUNC_G_ADDSUB, FUNC_G_DIV, FUNC_G_MOD, FUNC_G_MUL, FUNC_G_HOOK, FUNC_G_ASADD,
|
||||
/*$0C*/ FUNC_G_ASXOR, FUNC_G_ASSHIFT, FUNC_G_ASMUL, FUNC_G_ASDIV, FUNC_G_ASMOD, FUNC_G_AINCDEC,
|
||||
/*$12*/ FUNC_G_PARMS, FUNC_REGPARM, FUNC_FUNC_RESULT, FUNC_G_CAST, FUNC_G_EXPR, FUNC_G_COMPARE,
|
||||
/*$18*/ FUNC_TRUEJP, FUNC_FALSEJP, FUNC_GENLOOP, FUNC_GENRETURN, FUNC_GENSTMT, FUNC_ADD_CODE,
|
||||
/*$1E*/ FUNC_ASM_GETSYM, FUNC_LISTING, FUNC_OPT0, FUNC_PASS3, FUNC_UNINIT_TEMP, __FUNC_UNUSED1,
|
||||
/*$24*/ FUNC_G_CODE, FUNC_PEEP_DELETE, FUNC_G_PUSH, FUNC_G_POP, FUNC_CHECKSTACK, FUNC_TEMP_DATA,
|
||||
/*$2A*/ FUNC_TEMP_ADDR, FUNC_FREEOP, FUNC_DOOPER, FUNC_PEEP_LABEL, FUNC_BBLK_INIT,
|
||||
|
||||
/*$2F*/ FUNC_LINK_MISPL, FUNC_TABLE_HASH,
|
||||
/*$31*/ FUNC_WARN_LC_STK,
|
||||
|
||||
};
|
||||
// vim:ts=4:sw=4
|
||||
2157
gtc/src/expr.c
Normal file
2157
gtc/src/expr.c
Normal file
File diff suppressed because it is too large
Load Diff
169
gtc/src/expr.h
Normal file
169
gtc/src/expr.h
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* expressions
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifndef EXPR_H
|
||||
#define EXPR_H
|
||||
|
||||
/* expression tree descriptions */
|
||||
|
||||
//enum e_node {
|
||||
// en_void,
|
||||
// en_icon/*1*/, en_fcon, en_labcon/*3*/, en_nacon/*4*/, en_autocon/*5*/,
|
||||
// en_fcall, en_tempref, en_add, en_sub, en_mul, en_mod,
|
||||
// en_div, en_lsh, en_rsh, en_cond, en_assign/*16*/, en_eq, en_ne,
|
||||
// en_asadd, en_assub, en_asmul, en_asdiv, en_asmod, en_asrsh,
|
||||
// en_asxor,
|
||||
// en_aslsh, en_asand, en_asor, en_uminus, en_not, en_compl,
|
||||
// en_lt/*32*/, en_le, en_gt, en_ge, en_and, en_or, en_land, en_lor,
|
||||
// en_xor, en_ainc, en_adec,
|
||||
// en_ref, en_cast, en_deref,
|
||||
// en_fieldref,
|
||||
//};
|
||||
/* BEWARE!!! en_add must be even, and en_sub=en_add+1 (used in opt0) */
|
||||
enum e_node {
|
||||
// 0x00
|
||||
en_icon, en_fcon, en_labcon, en_nacon, en_autocon,
|
||||
// 0x05
|
||||
en_tempref, en_ref, en_fieldref,
|
||||
// 0x08
|
||||
en_void,
|
||||
en_compound,
|
||||
// 0x0A
|
||||
en_fcall, en_cast, en_add, en_sub, en_mul, en_mod,
|
||||
// 0x10
|
||||
en_div, en_lsh, en_rsh, en_cond, en_assign, en_eq, en_ne,
|
||||
// 0x17
|
||||
en_asadd, en_assub, en_asmul, en_asdiv, en_asmod, en_asrsh,
|
||||
en_asxor,
|
||||
// 0x1E
|
||||
en_aslsh, en_asand, en_asor, en_uminus, en_not, en_compl,
|
||||
en_lt, en_le, en_gt, en_ge, en_and, en_or, en_land, en_lor,
|
||||
en_xor, en_ainc, en_adec,
|
||||
en_deref,
|
||||
// extensions
|
||||
en_alloca,
|
||||
};
|
||||
/* below is the list of all nodes that need to have finer type considerations than below :
|
||||
- char/uchar
|
||||
- short/ushort
|
||||
- long/ulong/pointer
|
||||
- float
|
||||
- struct
|
||||
- union
|
||||
- void
|
||||
(these are considerations about the *parent* node, not about its children, whose type
|
||||
may safely be accessed)
|
||||
*/
|
||||
#define needs_trivial_casts(x) ( \
|
||||
/* pointer vs long/ulong */ \
|
||||
(x)==en_fcall || \
|
||||
/* signed vs unsigned */ \
|
||||
(x)==en_div || (x)==en_mod || (x)==en_mul || (x)==en_rsh || \
|
||||
(x)==en_asdiv || (x)==en_asmod || (x)==en_asmul || (x)==en_asrsh || \
|
||||
0)
|
||||
|
||||
/* statement node descriptions */
|
||||
|
||||
enum e_stmt {
|
||||
st_expr, st_while, st_for, st_do, st_if, st_switch,
|
||||
st_case, st_goto, st_break, st_continue, st_label,
|
||||
st_return, st_compound, st_default,
|
||||
// GTC extensions
|
||||
st_loop, st_asm,
|
||||
};
|
||||
|
||||
struct xcon {
|
||||
enum(e_node) nodetype;
|
||||
enum(e_bt) etype;
|
||||
long esize;
|
||||
union {
|
||||
long i;
|
||||
#ifndef XCON_DOESNT_SUPPORT_FLOATS
|
||||
#ifndef NOFLOAT
|
||||
double f;
|
||||
#endif
|
||||
#endif
|
||||
} v;
|
||||
};
|
||||
|
||||
struct enode {
|
||||
enum(e_node) nodetype;
|
||||
enum(e_bt) etype;
|
||||
long esize;
|
||||
union {
|
||||
long i;
|
||||
#ifndef NOFLOAT
|
||||
double f;
|
||||
#endif
|
||||
int enlab;
|
||||
char *__sp[2];
|
||||
struct enode *p[2];
|
||||
struct snode *st;
|
||||
} v;
|
||||
char bit_width, bit_offset; /* possibly unsigned char */
|
||||
};
|
||||
|
||||
#ifdef AS
|
||||
#define ensp __sp[1]
|
||||
#else
|
||||
#define ensp __sp[0]
|
||||
#endif
|
||||
int not_lvalue(struct enode *node);
|
||||
#define g_lvalue(node) (!not_lvalue(node))
|
||||
#define lvalue(node) (!not_lvalue(node))
|
||||
#define NIL_ENODE ( (struct enode *) 0)
|
||||
|
||||
struct snode {
|
||||
enum(e_stmt) stype;
|
||||
struct snode *next; /* next statement */
|
||||
struct enode *exp; /* condition or expression */
|
||||
struct snode *s1; /* internal statement */
|
||||
union {
|
||||
struct enode *e; /* condition or expression */
|
||||
struct snode *s; /* internal statement (else) */
|
||||
long i; /* (case)label or flag */
|
||||
} v1, v2;
|
||||
unsigned int count; /* execution count */
|
||||
#ifdef DB_POSSIBLE
|
||||
int line;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define NIL_SNODE ( (struct snode *) 0)
|
||||
|
||||
|
||||
struct cse {
|
||||
struct cse *next;
|
||||
struct enode *exp; /* optimizable expression */
|
||||
unsigned long uses; /* number of uses */
|
||||
unsigned long duses; /* number of dereferenced uses */
|
||||
short voidf; /* cannot optimize flag */
|
||||
#ifdef INFINITE_REGISTERS
|
||||
int reg; /* allocated register */
|
||||
#else
|
||||
short reg; /* allocated register */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct enode *mk_node(enum(e_node) nt, struct enode *v1, struct enode *v2);
|
||||
struct enode *mk_icon(long v);
|
||||
struct enode *parmlist();
|
||||
struct enode *copynode();
|
||||
struct snode *statement();
|
||||
struct snode *compound();
|
||||
|
||||
void opt4(struct enode **);
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
74
gtc/src/ffplib.h
Normal file
74
gtc/src/ffplib.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* Fast Floating Point routines
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifndef FFPLIB_H
|
||||
#define FFPLIB_H
|
||||
#ifndef str
|
||||
#define STR(__x) #__x
|
||||
#define str(__y) STR(__y)
|
||||
#endif
|
||||
|
||||
#define ffpver ffplib__0000
|
||||
#define ffpadd ffplib__0001
|
||||
#define ffpsub ffplib__0002
|
||||
#define ffpcmp ffplib__0003
|
||||
#define ffpcmp_c ffplib__0004
|
||||
#define ffpipart ffplib__0005
|
||||
#define ffputof ffplib__0006
|
||||
#define ffpltof ffplib__0007
|
||||
#define ffpftou ffplib__0008
|
||||
#define ffpftol ffplib__0009
|
||||
#define ffpmul ffplib__000A
|
||||
#define ffpmulxp ffplib__000B
|
||||
#define ffpsqr ffplib__000C
|
||||
#define ffpdiv ffplib__000D
|
||||
#define ffpftoa ffplib__000E
|
||||
#define ffpftobcd ffplib__000F
|
||||
#define ffplog ffplib__0010
|
||||
#define ffplog2 ffplib__0011
|
||||
#define ffpexp ffplib__0012
|
||||
#define ffpexp2 ffplib__0013
|
||||
#define ffppwr ffplib__0014
|
||||
#define ffpsincos ffplib__0015
|
||||
#define ffpsin ffplib__0016
|
||||
#define ffpcos ffplib__0017
|
||||
#define ffptan ffplib__0018
|
||||
#define sqrt ffplib__0019
|
||||
|
||||
double ffpadd(double a,double b);
|
||||
double ffpsub(double a,double b);
|
||||
void ffpcmp(double a,double b);
|
||||
long ffpcmp_c(double a,double b);
|
||||
double ffpipart(double a);
|
||||
double ffputof(unsigned long x);
|
||||
double ffpltof(long x);
|
||||
unsigned long ffpftou(double a); // + round
|
||||
long ffpftol(double a); // + round / floor
|
||||
double ffpmul(double a,double b);
|
||||
double ffpdiv(double a,double b);
|
||||
void ffpftoa(double a,char *s);
|
||||
void ffpftobcd(double a,void *d);
|
||||
double ffplog(double a);
|
||||
double ffplog2(double a);
|
||||
double ffpexp(double a);
|
||||
double ffpexp2(double a);
|
||||
double ffppwr(double a,double b);
|
||||
// {d0:double, d1:double} ffpsincos(double a);
|
||||
double ffpsin(double a);
|
||||
double ffpcos(double a);
|
||||
double ffptan(double a);
|
||||
int sqrt(long x);
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
24
gtc/src/flashend.c
Normal file
24
gtc/src/flashend.c
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* (on-calc) end of flashapp marker
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
asm(
|
||||
" .text\n"
|
||||
" .align 4\n"
|
||||
" .fdat\n"
|
||||
" .align 4\n"
|
||||
" .bss\n"
|
||||
" .align 4\n"
|
||||
" .fdat\n");
|
||||
// vim:ts=4:sw=4
|
||||
210
gtc/src/flashhdr.c
Normal file
210
gtc/src/flashhdr.c
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* (on-calc) flashapp header
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
//#define TEXT_SEG_SUPPORTED
|
||||
#ifdef GTDEV
|
||||
extern const SecureTab SecTab;
|
||||
const SecureTab *SecTabPtr=&SecTab;
|
||||
#endif
|
||||
|
||||
#ifdef TEXT_SEG_SUPPORTED
|
||||
/* note that this is only useful to generate the ASM code below */ #ifdef VERYBASIC_OO
|
||||
/* note that this is only useful to generate the ASM code below */ static void AP_app(pFrame self, EVENT *ev);
|
||||
/* note that this is only useful to generate the ASM code below */ FRAME(appObj, OO_SYSTEM_FRAME, 0, OO_APP_FLAGS, 3)
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_FLAGS, APP_INTERACTIVE)
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_NAME, "GTC")
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_PROCESS_EVENT, &AP_app)
|
||||
/* note that this is only useful to generate the ASM code below */ // ATTR(OO_APP_DEFAULT_MENU, &AppMenu )
|
||||
/* note that this is only useful to generate the ASM code below */ ENDFRAME
|
||||
/* note that this is only useful to generate the ASM code below */ #else
|
||||
/* note that this is only useful to generate the ASM code below */ #define H_Compile 0
|
||||
/* note that this is only useful to generate the ASM code below */ #define H_HELP 100
|
||||
/* note that this is only useful to generate the ASM code below */ APP_EXTENSION const extensions[] = {
|
||||
/* note that this is only useful to generate the ASM code below */ /* function name #, help string #, function index */
|
||||
/* note that this is only useful to generate the ASM code below */ #ifdef HAS_CMDLINE_EXTENSION
|
||||
/* note that this is only useful to generate the ASM code below */ {OO_APPSTRING+H_Compile, OO_APPSTRING+H_HELP+H_Compile, H_Compile },
|
||||
/* note that this is only useful to generate the ASM code below */ #endif
|
||||
/* note that this is only useful to generate the ASM code below */ };
|
||||
/* note that this is only useful to generate the ASM code below */ void _scr_main();
|
||||
/* note that this is only useful to generate the ASM code below */ APP_EXT_ENTRY const extEntries[] = {
|
||||
/* note that this is only useful to generate the ASM code below */ {_scr_main, APP_EXT_PROGRAM},
|
||||
/* note that this is only useful to generate the ASM code below */ };
|
||||
/* note that this is only useful to generate the ASM code below */ void AP_app(pFrame self, EVENT *ev);
|
||||
/* note that this is only useful to generate the ASM code below */ const char *AP_about(AppID self);
|
||||
/* note that this is only useful to generate the ASM code below */ FRAME(appObj, OO_SYSTEM_FRAME, 0, OO_APP_FLAGS, 10)
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_FLAGS, APP_INTERACTIVE)
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_NAME, "GTC")
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_TOK_NAME, "gtc")
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_PROCESS_EVENT, &AP_app)
|
||||
/* note that this is only useful to generate the ASM code below */ #ifdef HAS_CMDLINE_EXTENSION
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_EXT_COUNT, 1)
|
||||
/* note that this is only useful to generate the ASM code below */ #else
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_EXT_COUNT, 0)
|
||||
/* note that this is only useful to generate the ASM code below */ #endif
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_EXTENSIONS, extensions)
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_EXT_ENTRIES, extEntries)
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APP_ABOUT, &AP_about)
|
||||
/* note that this is only useful to generate the ASM code below */ #ifdef HAS_CMDLINE_EXTENSION
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APPSTRING+H_Compile, "compile")
|
||||
/* note that this is only useful to generate the ASM code below */ ATTR(OO_APPSTRING+H_HELP+H_Compile, "COMPILE A C PROGRAM")
|
||||
/* note that this is only useful to generate the ASM code below */ #endif
|
||||
/* note that this is only useful to generate the ASM code below */ ENDFRAME
|
||||
/* note that this is only useful to generate the ASM code below */ #endif
|
||||
/* note that this is only useful to generate the ASM code below */
|
||||
/* note that this is only useful to generate the ASM code below */ pFrame pAppObj = (pFrame)&appObj; /* Must be 1st! */
|
||||
#else
|
||||
#define CODESEG ".text"
|
||||
#define DATASEG ".fdat"
|
||||
#ifdef VERYBASIC_OO
|
||||
asm(
|
||||
" .globl appObj\n"
|
||||
" " CODESEG "\n"
|
||||
" .align 4\n"
|
||||
"appObj:\n"
|
||||
" .long -16777216\n"
|
||||
" .long 0\n"
|
||||
" .word 3\n"
|
||||
" .long 1\n"
|
||||
" .long 3\n"
|
||||
"appObjAttr:\n"
|
||||
" .long 1\n"
|
||||
" .long 1\n"
|
||||
" .long 2\n"
|
||||
" .long __GTC_str\n"
|
||||
" .long 4\n"
|
||||
" .long AP_app\n"
|
||||
"__GTC_str:\n"
|
||||
" .ascii \"GTC\\0\"\n"
|
||||
" .align 4\n"
|
||||
" .globl pAppObj\n"
|
||||
" " DATASEG "\n"
|
||||
" .even\n"
|
||||
"pAppObj:\n"
|
||||
" .long appObj\n"
|
||||
" " CODESEG "\n");
|
||||
#else
|
||||
asm(
|
||||
" " CODESEG "\n"
|
||||
" .even\n"
|
||||
#ifdef HAS_CMDLINE_EXTENSION
|
||||
" .globl extensions\n"
|
||||
"extensions:"
|
||||
" .long 4096\n"
|
||||
" .long 4196\n"
|
||||
" .word 0\n"
|
||||
" .globl extEntries\n"
|
||||
" .even\n"
|
||||
"extEntries:"
|
||||
" .long _scr_main\n"
|
||||
" .word 0\n"
|
||||
#endif
|
||||
" .globl appObj\n"
|
||||
" .even\n"
|
||||
"appObj:"
|
||||
" .long -16777216\n"
|
||||
" .long 0\n"
|
||||
" .word 3\n"
|
||||
" .long 1\n"
|
||||
" .long 10\n"
|
||||
" .even\n"
|
||||
"appObjAttr:"
|
||||
" .long 1\n"
|
||||
" .long 1\n"
|
||||
" .long 2\n"
|
||||
" .long MC0\n"
|
||||
" .long 3\n"
|
||||
" .long MC1\n"
|
||||
" .long 4\n"
|
||||
" .long AP_app\n"
|
||||
" .long 7\n"
|
||||
#ifdef HAS_CMDLINE_EXTENSION
|
||||
" .long 1\n"
|
||||
" .long 8\n"
|
||||
" .long extensions\n"
|
||||
" .long 9\n"
|
||||
" .long extEntries\n"
|
||||
#else
|
||||
" .long 0\n"
|
||||
#endif
|
||||
" .long 18\n"
|
||||
" .long AP_about\n"
|
||||
#ifdef HAS_CMDLINE_EXTENSION
|
||||
" .long 4096\n"
|
||||
" .long MC2\n"
|
||||
" .long 4196\n"
|
||||
" .long MC3\n"
|
||||
#endif
|
||||
"MC0:"
|
||||
" .ascii \"GTC\\0\"\n"
|
||||
"MC1:"
|
||||
" .ascii \"gtc\\0\"\n"
|
||||
#ifdef HAS_CMDLINE_EXTENSION
|
||||
"MC2:"
|
||||
" .ascii \"compile\\0\"\n"
|
||||
"MC3:"
|
||||
" .ascii \"COMPILE A C PROGRAM\\0\"\n"
|
||||
#endif
|
||||
" .globl pAppObj\n"
|
||||
" " DATASEG "\n"
|
||||
" .even\n"
|
||||
"pAppObj:"
|
||||
" .long appObj\n"
|
||||
" " CODESEG "\n");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void _main();
|
||||
void _scr_main();
|
||||
#define EV_quit() asm(".word $F800+1166")
|
||||
void AP_app(pFrame self, EVENT *ev) {
|
||||
switch (ev->Type) {
|
||||
case CM_STARTTASK:
|
||||
_scr_main();
|
||||
EV_quit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *AP_about(AppID self) {
|
||||
return "GTC compiler\n\n(c) 2001-2003 by Paul Froissart\n\nInternal beta i1";
|
||||
}
|
||||
|
||||
void _scr_main() {
|
||||
_main();
|
||||
// now redraw the screen... (thanks to PpHd for this code)
|
||||
// 1) the current application
|
||||
{ WINDOW w;
|
||||
WinOpen(&w,&(WIN_RECT){0,0,239,127},WF_NOBOLD|WF_NOBORDER);
|
||||
WinActivate(&w);
|
||||
WinClose(&w); }
|
||||
// 2) the status bar
|
||||
ST_showHelp("");
|
||||
ST_eraseHelp();
|
||||
// 3) the black line
|
||||
#if !defined(_92) && !defined(_V200)
|
||||
memset(LCD_MEM+30*(100-7),-1,30);
|
||||
#else
|
||||
memset(LCD_MEM+30*(128-7),-1,30);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef GTDEV
|
||||
#include "gtdevcomm.c"
|
||||
const SecureTab SecTab = {
|
||||
0,
|
||||
Compile
|
||||
};
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
301
gtc/src/flashhdr.h
Normal file
301
gtc/src/flashhdr.h
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* (on-calc) flashapp header define's
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#define OO_HANDLE (0xFF000000u)
|
||||
#define OO_SYSTEM_FRAME OO_HANDLE
|
||||
typedef ULONG pFrame;
|
||||
typedef HANDLE AppID;
|
||||
|
||||
typedef void (* APP_EXT_FUNC)(void);
|
||||
typedef struct SAppExtension
|
||||
{
|
||||
unsigned long name;
|
||||
unsigned long help;
|
||||
unsigned short index;
|
||||
} APP_EXTENSION;
|
||||
typedef struct SAppExtEntry
|
||||
{
|
||||
APP_EXT_FUNC extension;
|
||||
unsigned short flags;
|
||||
} APP_EXT_ENTRY;
|
||||
enum {APP_EXT_PROGRAM=0x0000, APP_EXT_FUNCTION=0x0001};
|
||||
typedef enum
|
||||
{
|
||||
ACB_BUILTIN =0x0001,
|
||||
ACB_INSTALLED =0x0002,
|
||||
ACB_LOCALIZER =0x0004,
|
||||
ACB_LOCK =0x0008,
|
||||
ACB_JT_VERSION=0x0010,
|
||||
ACB_SELECTED =0x0020,
|
||||
ACB_COLLAPSE =0x0800,
|
||||
ACB_BG =0x1000,
|
||||
ACB_COMPRESS =0x4000,
|
||||
ACB_DELETE =0x8000
|
||||
} ACB_Flags;
|
||||
|
||||
#define MAKE_OO_HANDLE(h) ((h) | OO_HANDLE)
|
||||
#define OO_GET_HANDLE(h) ((h) & ~OO_HANDLE)
|
||||
#define IS_OO_HANDLE(h) ((h) > OO_HANDLE)
|
||||
typedef enum {OO_RW=0, OO_RO=1,
|
||||
OO_SEQ=0, OO_KEYED=2} OO_Flags;
|
||||
typedef struct
|
||||
{
|
||||
ULONG key;
|
||||
void *value;
|
||||
} OO_Attr;
|
||||
typedef struct SFrameHdr
|
||||
{
|
||||
pFrame parent;
|
||||
pFrame prototype;
|
||||
OO_Flags flags;
|
||||
ULONG first;
|
||||
ULONG count;
|
||||
} OO_Hdr;
|
||||
typedef struct SFrame
|
||||
{
|
||||
OO_Hdr head;
|
||||
union
|
||||
{
|
||||
void *value[65000];
|
||||
OO_Attr pair[65000];
|
||||
} attr;
|
||||
} Frame;
|
||||
typedef void (* const OO_MethodPtr)(void);
|
||||
#define STRING_FRAME(name, parent, proto, first, count) \
|
||||
const OO_Hdr name = \
|
||||
{ \
|
||||
(pFrame)parent, \
|
||||
(pFrame)proto, \
|
||||
OO_RO | OO_SEQ, \
|
||||
first, \
|
||||
count \
|
||||
}; \
|
||||
static const char * const name##Attr[count] = \
|
||||
{
|
||||
#define FRAME(name, parent, proto, first, count) \
|
||||
const OO_Hdr name = \
|
||||
{ \
|
||||
(pFrame)parent, \
|
||||
(pFrame)proto, \
|
||||
OO_RO | OO_KEYED, \
|
||||
first, \
|
||||
count \
|
||||
}; \
|
||||
static const OO_Attr name##Attr[count] = \
|
||||
{
|
||||
#define ATTR(selector, val) {selector, (void *)(val)},
|
||||
#define STRING_ATTR(sel, s) {OO_FIRST_STRING+(sel), s},
|
||||
#define ENDFRAME };
|
||||
#define MAX_APPLET_NAME_SIZE (8)
|
||||
|
||||
#define OO_APP_FLAGS (1)
|
||||
#define GetAppFlags(obj) \
|
||||
(APP_Flags)OO_GetAppAttr(obj,1)
|
||||
#define SetAppFlags(obj,value) \
|
||||
OO_SetAppAttr(obj,1,(void *)value)
|
||||
#define OO_APP_NAME (2)
|
||||
#define GetAppName(obj) \
|
||||
(UCHAR *)OO_GetAppAttr(obj,2)
|
||||
#define SetAppName(obj,value) \
|
||||
OO_SetAppAttr(obj,2,(void *)value)
|
||||
#define OO_APP_TOK_NAME (3)
|
||||
#define GetAppTokName(obj) \
|
||||
(UCHAR *)OO_GetAppAttr(obj,3)
|
||||
#define SetAppTokName(obj,value) \
|
||||
OO_SetAppAttr(obj,3,(void *)value)
|
||||
#define OO_APP_PROCESS_EVENT (4)
|
||||
#define AppProcessEvent(obj,a) \
|
||||
((void (* const)(pFrame, PEvent))OO_GetAttr(obj,4))(obj,a)
|
||||
#define OO_APP_DEFAULT_MENU (5)
|
||||
#define GetAppDefaultMenu(obj) \
|
||||
(MENU *)OO_GetAppAttr(obj,5)
|
||||
#define SetAppDefaultMenu(obj,value) \
|
||||
OO_SetAppAttr(obj,5,(void *)value)
|
||||
#define OO_APP_DEFAULT_MENU_HANDLE (6)
|
||||
#define GetAppDefaultMenuHandle(obj) \
|
||||
(HANDLE)OO_GetAppAttr(obj,6)
|
||||
#define SetAppDefaultMenuHandle(obj,value) \
|
||||
OO_SetAppAttr(obj,6,(void *)value)
|
||||
#define OO_APP_EXT_COUNT (7)
|
||||
#define GetAppExtCount(obj) \
|
||||
(long)OO_GetAppAttr(obj,7)
|
||||
#define SetAppExtCount(obj,value) \
|
||||
OO_SetAppAttr(obj,7,(void *)value)
|
||||
#define OO_APP_EXTENSIONS (8)
|
||||
#define GetAppExtensions(obj) \
|
||||
(APP_EXTENSION const *)OO_GetAppAttr(obj,8)
|
||||
#define SetAppExtensions(obj,value) \
|
||||
OO_SetAppAttr(obj,8,(void *)value)
|
||||
#define OO_APP_EXT_ENTRIES (9)
|
||||
#define GetAppExtEntries(obj) \
|
||||
(APP_EXT_ENTRY const *)OO_GetAppAttr(obj,9)
|
||||
#define SetAppExtEntries(obj,value) \
|
||||
OO_SetAppAttr(obj,9,(void *)value)
|
||||
#define OO_APP_LOCALIZE (10)
|
||||
#define AppLocalize(obj,a) \
|
||||
((BOOL (* const)(AppID, UCHAR const *))OO_GetAppAttr(obj,10))(obj,a)
|
||||
#define OO_APP_UNLOCALIZE (11)
|
||||
#define AppUnlocalize(obj) \
|
||||
((void (* const)(AppID))OO_GetAppAttr(obj,11))(obj)
|
||||
#define OO_APP_CAN_DELETE (12)
|
||||
#define AppCanDelete(obj) \
|
||||
((BOOL (* const)(AppID))OO_GetAppAttr(obj,12))(obj)
|
||||
#define OO_APP_CAN_MOVE (13)
|
||||
#define AppCanMove(obj) \
|
||||
((BOOL (* const)(AppID))OO_GetAppAttr(obj,13))(obj)
|
||||
#define OO_APP_VIEWER (14)
|
||||
#define AppViewer(obj,a,b,c) \
|
||||
((BOOL (* const)(AppID, BYTE *, WINDOW *, HSYM))OO_GetAppAttr(obj,14))(obj,a,b,c)
|
||||
#define OO_APP_ICON (15)
|
||||
#define GetAppIcon(obj) \
|
||||
(BITMAP *)OO_GetAppAttr(obj,15)
|
||||
#define SetAppIcon(obj,value) \
|
||||
OO_SetAppAttr(obj,15,(void *)value)
|
||||
#define OO_APP_EXT_HELP (16)
|
||||
#define AppExtHelp(obj,a) \
|
||||
((void (* const)(AppID, USHORT))OO_GetAppAttr(obj,16))(obj,a)
|
||||
#define OO_APP_NOTICE_INSTALL (17)
|
||||
#define AppNoticeInstall(obj,a) \
|
||||
((void (* const)(AppID, ACB const *))OO_GetAppAttr(obj,17))(obj,a)
|
||||
#define OO_APP_ABOUT (18)
|
||||
#define AppAbout(obj) \
|
||||
((char const * (* const)(AppID))OO_GetAppAttr(obj,18))(obj)
|
||||
#define OO_SFONT (768)
|
||||
#define Getsfont(obj) \
|
||||
(SF_CHAR *)OO_GetAttr(obj,768)
|
||||
#define Setsfont(obj,value) \
|
||||
OO_SetAttr(obj,768,(void *)value)
|
||||
#define OO_LFONT (769)
|
||||
#define Getlfont(obj) \
|
||||
(LF_CHAR *)OO_GetAttr(obj,769)
|
||||
#define Setlfont(obj,value) \
|
||||
OO_SetAttr(obj,769,(void *)value)
|
||||
#define OO_HFONT (770)
|
||||
#define Gethfont(obj) \
|
||||
(HF_CHAR *)OO_GetAttr(obj,770)
|
||||
#define Sethfont(obj,value) \
|
||||
OO_SetAttr(obj,770,(void *)value)
|
||||
#define OO_APP_SFONT (768)
|
||||
#define GetAppSFont(obj) \
|
||||
(SF_CHAR *)OO_GetAppAttr(obj,768)
|
||||
#define SetAppSFont(obj,value) \
|
||||
OO_SetAppAttr(obj,768,(void *)value)
|
||||
#define OO_APP_LFONT (769)
|
||||
#define GetAppLFont(obj) \
|
||||
(LF_CHAR *)OO_GetAppAttr(obj,769)
|
||||
#define SetAppLFont(obj,value) \
|
||||
OO_SetAppAttr(obj,769,(void *)value)
|
||||
#define OO_APP_HFONT (770)
|
||||
#define GetAppHFont(obj) \
|
||||
(HF_CHAR *)OO_GetAppAttr(obj,770)
|
||||
#define SetAppHFont(obj,value) \
|
||||
OO_SetAppAttr(obj,770,(void *)value)
|
||||
#define OO_LANGUAGE (784)
|
||||
#define GetLanguage(obj) \
|
||||
(WORD)OO_GetAttr(obj,784)
|
||||
#define SetLanguage(obj,value) \
|
||||
OO_SetAttr(obj,784,(void *)value)
|
||||
#define OO_DATE_FORMAT (785)
|
||||
#define GetDateFormat(obj) \
|
||||
(char const *)OO_GetAttr(obj,785)
|
||||
#define SetDateFormat(obj,value) \
|
||||
OO_SetAttr(obj,785,(void *)value)
|
||||
#define OO_BUILTIN_HELP (786)
|
||||
#define BuiltinHelp(obj,a) \
|
||||
((void (* const)(pFrame, USHORT))OO_GetAttr(obj,786))(obj,a)
|
||||
#define OO_KTLIST (800)
|
||||
#define GetKTList(obj) \
|
||||
(keytag const *)OO_GetAttr(obj,800)
|
||||
#define SetKTList(obj,value) \
|
||||
OO_SetAttr(obj,800,(void *)value)
|
||||
#define OO_CAT_TABLE (801)
|
||||
#define GetCAT_table(obj) \
|
||||
(CATALOG const *)OO_GetAttr(obj,801)
|
||||
#define SetCAT_table(obj,value) \
|
||||
OO_SetAttr(obj,801,(void *)value)
|
||||
#define OO_CAT_INDEX (802)
|
||||
#define GetCAT_index(obj) \
|
||||
(short const *)OO_GetAttr(obj,802)
|
||||
#define SetCAT_index(obj,value) \
|
||||
OO_SetAttr(obj,802,(void *)value)
|
||||
#define OO_CAT_COUNT (803)
|
||||
#define GetCAT_count(obj) \
|
||||
(short)OO_GetAttr(obj,803)
|
||||
#define SetCAT_count(obj,value) \
|
||||
OO_SetAttr(obj,803,(void *)value)
|
||||
#define OO_CHAR_MENU (816)
|
||||
#define GetCharMenu(obj) \
|
||||
(const MENU *)OO_GetAttr(obj,816)
|
||||
#define SetCharMenu(obj,value) \
|
||||
OO_SetAttr(obj,816,(void *)value)
|
||||
#define OO_CHAR_HANDLER (817)
|
||||
#define CharHandler(obj) \
|
||||
((void (* const)(pFrame))OO_GetAttr(obj,817))(obj)
|
||||
#define OO_APPS_HANDLER (818)
|
||||
#define AppsHandler(obj) \
|
||||
((void (* const)(pFrame))OO_GetAttr(obj,818))(obj)
|
||||
#define OO_FLASH_APPS_HANDLER (819)
|
||||
#define FlashAppsHandler(obj) \
|
||||
((void (* const)(pFrame))OO_GetAttr(obj,819))(obj)
|
||||
#define OO_MATH_HANDLER (820)
|
||||
#define MathHandler(obj) \
|
||||
((void (* const)(pFrame))OO_GetAttr(obj,820))(obj)
|
||||
#define OO_MEM_HANDLER (821)
|
||||
#define MemHandler(obj) \
|
||||
((void (* const)(pFrame))OO_GetAttr(obj,821))(obj)
|
||||
#define OO_STO_HANDLER (822)
|
||||
#define StoHandler(obj) \
|
||||
((void (* const)(pFrame))OO_GetAttr(obj,822))(obj)
|
||||
#define OO_QUIT_HANDLER (823)
|
||||
#define QuitHandler(obj) \
|
||||
((void (* const)(pFrame))OO_GetAttr(obj,823))(obj)
|
||||
|
||||
#define OO_FIRST_STRING 2048
|
||||
#define OO_FIRST_APP_STRING 2048
|
||||
#define OO_APPSTRING (OO_FIRST_STRING+OO_FIRST_APP_STRING)
|
||||
#define OO_FIRST_APP_ATTR 0x10000
|
||||
typedef enum {APP_NONE=0,
|
||||
APP_INTERACTIVE=1,
|
||||
APP_CON=2,
|
||||
APP_ACCESS_SYSVARS=4,
|
||||
APP_BACKGROUND=8}
|
||||
APP_Flags;
|
||||
|
||||
typedef struct SAppHdr
|
||||
{
|
||||
ULONG magic;
|
||||
UCHAR name[MAX_APPLET_NAME_SIZE];
|
||||
BYTE zeros[24];
|
||||
USHORT flags;
|
||||
ULONG dataLen;
|
||||
ULONG codeOffset;
|
||||
ULONG initDataOffset;
|
||||
ULONG initDataLen;
|
||||
ULONG optlen;
|
||||
} AppHdr;
|
||||
typedef struct SACB
|
||||
{
|
||||
USHORT flags;
|
||||
AppID myID;
|
||||
AppID next;
|
||||
AppID prev;
|
||||
ULONG publicstorage;
|
||||
AppHdr const *appHeader;
|
||||
BYTE const *certhdr;
|
||||
pFrame appData;
|
||||
} ACB;
|
||||
#define MY_ACB(p) ((ACB*)((BYTE*)&(p)-OFFSETOF(ACB,appData)))
|
||||
#define MY_APP_ID(p) (MY_ACB(p)->myID)
|
||||
// vim:ts=4:sw=4
|
||||
471
gtc/src/func.c
Normal file
471
gtc/src/func.c
Normal file
@ -0,0 +1,471 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* function routines
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#define DECLARE
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
|
||||
int is_leaf_function CGLOB, uses_link CGLOB, pushed CGLOB;
|
||||
XLST_TYPE reg_size CGLOB;
|
||||
|
||||
|
||||
void funcbottom(void);
|
||||
void block(struct sym *sp); /* CAUTION : always requires a compound_done() after call */
|
||||
|
||||
/* function compilation routines */
|
||||
|
||||
#ifdef REGPARM
|
||||
SYM *parmsp[CONVENTION_MAX_DATA+1+CONVENTION_MAX_ADDR+1+1];
|
||||
#endif
|
||||
void funcbody(SYM *sp, char *names[], int nparms) {
|
||||
/*
|
||||
* funcbody starts with the current symbol being the begin for the local
|
||||
* block or the first symbol of the parameter declaration
|
||||
*/
|
||||
long poffset;
|
||||
int i, j;
|
||||
struct sym *sp1, *mk_int();
|
||||
int old_global;
|
||||
long old_spvalue;
|
||||
XLST_TYPE *p;
|
||||
#ifdef REGPARM
|
||||
int regs=sp->tp->rp_dn+sp->tp->rp_an;
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSE
|
||||
time_t ltime;
|
||||
#endif /* VERBOSE */
|
||||
|
||||
#ifdef VERBOSE
|
||||
times(&tms_buf);
|
||||
ltime = tms_buf.tms_utime;
|
||||
#endif /* VERBOSE */
|
||||
/* uses_structassign=0;*/
|
||||
lc_auto = 0;
|
||||
max_scratch = 0;
|
||||
is_leaf_function = 1;
|
||||
uses_link = 0;
|
||||
pushed = 0;
|
||||
init_node = 0;
|
||||
old_global = global_flag;
|
||||
global_flag = 0;
|
||||
poffset = 8; /* size of return block */
|
||||
#ifdef REGPARM
|
||||
memset(parmsp,0,sizeof(parmsp));
|
||||
#endif
|
||||
/*if (!strcmp(declid,"MnuSel"))
|
||||
printf("sgio");*/
|
||||
if (bt_aggregate(sp->tp->btp->type))
|
||||
poffset = 12;
|
||||
if (!start_block(0))
|
||||
dodecl(sc_parms); /* declare parameters */
|
||||
/* undeclared parameters are int's */
|
||||
if (!lc_auto) /* otherwise there are declared vars that aren't parameters : error */
|
||||
for (i = 0; i < nparms; ++i) {
|
||||
if (!(sp1 = search(names[i], -1, &lsyms))) {
|
||||
sp1 = mk_int(names[i]);
|
||||
// do_warning("argument '%s' implicitly declared 'int'",names[i]);
|
||||
}
|
||||
old_spvalue = sp1->value.i;
|
||||
sp1->value.i = poffset;
|
||||
sp1->storage_class = sc_auto;
|
||||
#ifdef REGPARM
|
||||
if (regs) {
|
||||
int siz;
|
||||
if (sp1->tp->type==bt_pointer || sp1->tp->type==bt_func) {
|
||||
/*
|
||||
* arrays and functions are never passed. They are really
|
||||
* Pointers
|
||||
*/
|
||||
if (sp1->tp->val_flag != 0) {
|
||||
TYP *tp1 = (TYP *) xalloc((int) sizeof(TYP), _TYP+FUNCBODY);
|
||||
*tp1 = *(sp1->tp);
|
||||
sp1->tp = tp1;
|
||||
tp1->st_flag = 0;
|
||||
sp1->tp->val_flag = 0;
|
||||
sp1->tp->size = 4;
|
||||
}
|
||||
}
|
||||
siz=sp1->tp->size;
|
||||
#ifdef AS
|
||||
sp1->value.i = -(lc_auto+siz+(siz&1)/* dirty hack, but it works */);
|
||||
#else
|
||||
sp1->value.i = -(lc_auto+siz+(siz&1)/* dirty hack, but it works */);
|
||||
// if (siz&1) printf("[crp]"),getchar();
|
||||
#endif
|
||||
siz+=siz&1;
|
||||
lc_auto+=siz;
|
||||
parmsp[i]=sp1;
|
||||
regs--;
|
||||
// goto ok_param;
|
||||
poffset -= siz; /* to undo the effect of the following statements */
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* char, unsigned char, short, unsigned short, enum have been widened
|
||||
* to int by the caller. This has to be un-done The same is true for
|
||||
* float/double but float==double actually convert x[] to *x by
|
||||
* clearing val_flag
|
||||
*
|
||||
* It is shown here how to do this correctly, but if we know something
|
||||
* about the data representation, it can be done much more
|
||||
* effectively. Therefore, we define MC680X0 and do the cast
|
||||
* by hand. This means that we can retrieve a char, widened to short
|
||||
* and put at machine address n, at machine address n+1. This should
|
||||
* work on most machines. BIGendian machines can do it like it is
|
||||
* shown here, LOWendian machines must not adjust sp1->value.i The
|
||||
* function castback is still needed if someone decides to have a
|
||||
* double data type which is not equivalent to float.
|
||||
* This approach is, of course, ugly since some
|
||||
* assumptions on the target machine enter the front end here, but
|
||||
* they do anyway through the initial value of poffset which is the
|
||||
* number of bytes that separate the local block from the argument
|
||||
* block. On a 68000 this are eight bytes since we do a link a6,...
|
||||
* always.
|
||||
*/
|
||||
switch (sp1->tp->type) {
|
||||
case bt_char:
|
||||
case bt_uchar:
|
||||
#ifdef MC680X0
|
||||
if (short_option) {
|
||||
sp1->value.i += 1;
|
||||
poffset += 2;
|
||||
} else {
|
||||
sp1->value.i += 3;
|
||||
poffset += 4;
|
||||
}
|
||||
#endif
|
||||
#ifdef INTEL_386
|
||||
/* note that we only support 32-bit integers */
|
||||
poffset += 4; /* byte already right there */
|
||||
#endif
|
||||
break;
|
||||
case bt_short:
|
||||
case bt_ushort:
|
||||
#ifdef MC680X0
|
||||
if (short_option) {
|
||||
poffset += 2;
|
||||
} else {
|
||||
sp1->value.i += 2;
|
||||
poffset += 4;
|
||||
}
|
||||
#endif
|
||||
#ifdef INTEL_386
|
||||
poffset += 4; /* word already right there */
|
||||
#endif
|
||||
break;
|
||||
case bt_float:
|
||||
#ifdef MC68000
|
||||
/* float is the same as double in the 68000 implementation */
|
||||
poffset += float_size;
|
||||
#endif
|
||||
#ifdef INTEL_386
|
||||
castback(poffset, &tp_double, &tp_float);
|
||||
poffset += 8;
|
||||
#endif
|
||||
break;
|
||||
case bt_pointer:
|
||||
case bt_func:
|
||||
poffset += 4;
|
||||
/*
|
||||
* arrays and functions are never passed. They are really
|
||||
* Pointers
|
||||
*/
|
||||
if (sp1->tp->val_flag != 0) {
|
||||
TYP *tp1 = (TYP *) xalloc((int) sizeof(TYP), _TYP+FUNCBODY);
|
||||
*tp1 = *(sp1->tp);
|
||||
sp1->tp = tp1;
|
||||
tp1->st_flag = 0;
|
||||
sp1->tp->val_flag = 0;
|
||||
sp1->tp->size = 4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
poffset += sp1->tp->size;
|
||||
break;
|
||||
}
|
||||
// ok_param:
|
||||
/*
|
||||
* The following code updates the reglst and autolst arrays
|
||||
* old_spvalue is zero for undeclared parameters (see mk_int), so it
|
||||
* works. We do a linear search through the reglst and autolst array,
|
||||
* so this is inefficient. Howewer, these arrays are usually short
|
||||
* since they only contain the function arguments at moment. In
|
||||
* short, function argument processing need not be efficient.
|
||||
*/
|
||||
p=reglst; j=regptr; while (j--) {
|
||||
if ((XLST_TYPE)*p++ == (XLST_TYPE)old_spvalue) {
|
||||
p[-1] = sp1->value.i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
p=autolst; j=autoptr; while (j--) {
|
||||
if ((XLST_TYPE)*p++ == (XLST_TYPE)old_spvalue) {
|
||||
p[-1] = sp1->value.i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
/*
|
||||
* Check if there are declared parameters missing in the argument list.
|
||||
* (this needs to be done iff lc_auto!=0, so with DETAILED_ERR not defined
|
||||
* this is just OK)
|
||||
*/
|
||||
#ifdef DETAILED_ERR
|
||||
for (i=0;i<N_HASH;i++) {
|
||||
sp1 = lsyms.h[i].tail;
|
||||
while (sp1 != 0) {
|
||||
/*
|
||||
* assume that value.i is negative for normal auto variables
|
||||
* and positive for parameters -- in fact this is correct either
|
||||
* with REGPARM not defined, or before the parameter scan whose code is
|
||||
* just above this
|
||||
*/
|
||||
if (sp1->value.i <= 0)
|
||||
#endif
|
||||
error(ERR_ARG);
|
||||
#ifdef DETAILED_ERR
|
||||
sp1 = sp1->prev;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef REGPARM
|
||||
reg_size=lc_auto;
|
||||
#endif
|
||||
if (!start_block(0))
|
||||
error(ERR_BLOCK);
|
||||
else {
|
||||
block(sp);
|
||||
funcbottom();
|
||||
}
|
||||
global_flag = old_global;
|
||||
compound_done(); // due to block(sp)
|
||||
#ifdef VERBOSE
|
||||
times(&tms_buf);
|
||||
parse_time += tms_buf.tms_utime - ltime;
|
||||
#endif /* VERBOSE */
|
||||
}
|
||||
|
||||
struct sym *mk_int(char *name) {
|
||||
struct sym *sp;
|
||||
TYP *tp;
|
||||
sp = (struct sym *) xalloc((int) sizeof(struct sym), _SYM+MK_INT);
|
||||
tp = (TYP *) xalloc((int) sizeof(TYP),_TYP+MK_INT);
|
||||
if (short_option) {
|
||||
tp->type = bt_short;
|
||||
tp->size = 2;
|
||||
} else {
|
||||
tp->type = bt_long;
|
||||
tp->size = 4;
|
||||
}
|
||||
#ifdef NO_CALLOC
|
||||
tp->btp = 0;
|
||||
tp->lst.tail = tp->lst.head = 0; tp->lst.hash = 0;
|
||||
tp->vol_flag = tp->val_flag = tp->const_flag = tp->st_flag = 0;
|
||||
#ifdef LISTING
|
||||
tp->sname = 0;
|
||||
#endif
|
||||
#endif
|
||||
sp->name = name;
|
||||
sp->storage_class = sc_auto;
|
||||
sp->tp = tp;
|
||||
#ifdef NO_CALLOC
|
||||
sp->value.i = 0; /* dummy -> means param is undeclared */
|
||||
#endif
|
||||
append(&sp, &lsyms);
|
||||
return sp;
|
||||
}
|
||||
|
||||
void check_table(HTABLE *table) {
|
||||
SYM *head;
|
||||
struct htab *ptr; int i;
|
||||
ptr=&table->h[0];
|
||||
i=N_HASH;
|
||||
while (i--) {
|
||||
head=ptr->head;
|
||||
while (head != 0) {
|
||||
if (head->storage_class == sc_ulabel) {
|
||||
uerrc2("undefined label '%s'",head->name);
|
||||
// msg2("*** UNDEFINED LABEL - %s\n", head->name);
|
||||
#ifdef LISTING
|
||||
if (list_option)
|
||||
fprintf(list, "*** UNDEFINED LABEL - %s\n", head->name);
|
||||
#endif
|
||||
}
|
||||
head = head->next;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
void funcbottom(void) {
|
||||
nl();
|
||||
check_table(&labsyms);
|
||||
#ifdef LISTING
|
||||
// if (list_option && lsyms.head != 0) {
|
||||
fprintf(list, "\n\n*** argument symbol table ***\n\n");
|
||||
list_table(&lsyms, 0);
|
||||
fprintf(list, "\n\n\n");
|
||||
// }
|
||||
// if (list_option && labsyms.head != 0) {
|
||||
fprintf(list, "\n\n*** label symbol table ***\n\n");
|
||||
list_table(&labsyms, 0);
|
||||
fprintf(list, "\n\n\n");
|
||||
// }
|
||||
#endif
|
||||
#ifdef AS
|
||||
local_clean();
|
||||
#endif
|
||||
rel_local(); /* release local symbols */
|
||||
hashinit(&lsyms);
|
||||
hashinit(<ags);
|
||||
hashinit(&labsyms);
|
||||
}
|
||||
|
||||
extern char *curname;
|
||||
xstatic struct enode save_sp CGLOBL;
|
||||
struct snode *dump_stmt;
|
||||
SYM *func_sp CGLOB;
|
||||
void block(struct sym *sp) { /* CAUTION : always requires a compound_done() after call */
|
||||
struct snode *stmt;
|
||||
int local_total_errors = total_errors;
|
||||
int line0;
|
||||
#ifdef VERBOSE
|
||||
time_t ltime;
|
||||
#endif /* VERBOSE */
|
||||
|
||||
//#ifdef VERBOSE
|
||||
#ifdef AS
|
||||
scope_init();
|
||||
#endif
|
||||
func_sp=sp;
|
||||
/*infunc("fire")
|
||||
bkpt();*/
|
||||
#ifndef GTDEV
|
||||
#ifdef PC
|
||||
if (verbose)
|
||||
#endif
|
||||
msg2("Compiling '%s'... ", sp->name);
|
||||
#endif
|
||||
//#endif /* VERBOSE */
|
||||
|
||||
#ifdef ICODE
|
||||
if (icode_option)
|
||||
if (sp->storage_class == sc_external || sp->storage_class == sc_global)
|
||||
fprintf(icode, "%s:\n", sp->name);
|
||||
else
|
||||
fprintf(icode, "L%ld:\n", sp->value.i);
|
||||
#endif
|
||||
#ifdef SHOWSTEP
|
||||
printf("\nparsing");
|
||||
#endif
|
||||
start_block(1);
|
||||
line0=prevlineid;
|
||||
dump_stmt = stmt = compound(-1);
|
||||
#ifdef SHOWSTEP
|
||||
printf(" ok ");
|
||||
#endif
|
||||
#ifdef VERBOSE
|
||||
times(&tms_buf);
|
||||
ltime = tms_buf.tms_utime;
|
||||
#endif /* VERBOSE */
|
||||
/*
|
||||
* If errors so far, do not try to generate code
|
||||
*/
|
||||
if (total_errors > local_total_errors) {
|
||||
cseg();
|
||||
dumplits();
|
||||
return;
|
||||
}
|
||||
lineid=line0;
|
||||
genfunc(stmt);
|
||||
#ifdef VERBOSE
|
||||
times(&tms_buf);
|
||||
gen_time += tms_buf.tms_utime - ltime;
|
||||
ltime = tms_buf.tms_utime;
|
||||
#endif /* VERBOSE */
|
||||
cseg();
|
||||
dumplits();
|
||||
put_align(AL_FUNC);
|
||||
#ifndef AS
|
||||
if (sp->storage_class == sc_external || sp->storage_class == sc_global)
|
||||
g_strlab(sp->name);
|
||||
else
|
||||
put_label((unsigned int) sp->value.i);
|
||||
#else
|
||||
put_label(splbl(sp));
|
||||
#endif
|
||||
if (!strcmp(sp->name,"__main") && !search("NO_EXIT_SUPPORT",-1,&defsyms)) {
|
||||
save_sp.nodetype = en_nacon;
|
||||
save_sp.etype = bt_pointer;
|
||||
save_sp.esize = 4;
|
||||
save_sp.v.ensp = "__save__sp__";
|
||||
#ifdef AS
|
||||
save_sp.v.enlab = label("__save__sp__");
|
||||
#endif
|
||||
g_coder(op_move,4,mk_reg(STACKPTR),mk_offset(&save_sp));
|
||||
}
|
||||
flush_peep();
|
||||
#ifdef AS
|
||||
scope_flush();
|
||||
#endif
|
||||
func_sp=NULL;
|
||||
#ifdef VERBOSE
|
||||
times(&tms_buf);
|
||||
flush_time += tms_buf.tms_utime - ltime;
|
||||
#endif /* VERBOSE */
|
||||
}
|
||||
|
||||
void castback(long offset, TYP *tp1, TYP *tp2) {
|
||||
/*
|
||||
* cast an argument back which has been widened on the caller's side.
|
||||
* append the resulting assignment expression to init_node
|
||||
*/
|
||||
struct enode *ep1, *ep2;
|
||||
|
||||
ep2 = mk_node(en_autocon, NIL_ENODE, NIL_ENODE);
|
||||
ep2->v.i = offset;
|
||||
ep2->etype = bt_pointer;
|
||||
ep2->esize = 4;
|
||||
|
||||
ep1 = copynode(ep2);
|
||||
|
||||
ep2 = mk_node(en_ref, ep2, NIL_ENODE);
|
||||
ep2->etype = tp1->type;
|
||||
ep2->esize = tp1->size;
|
||||
|
||||
ep2 = mk_node(en_cast, ep2, NIL_ENODE);
|
||||
ep2->etype = tp2->type;
|
||||
ep2->esize = tp2->size;
|
||||
|
||||
ep1 = mk_node(en_ref, ep1, NIL_ENODE);
|
||||
ep1->etype = tp2->type;
|
||||
ep1->esize = tp2->size;
|
||||
|
||||
ep1 = mk_node(en_assign, ep1, ep2);
|
||||
ep1->etype = tp2->type;
|
||||
ep1->esize = tp2->size;
|
||||
|
||||
if (init_node == 0)
|
||||
init_node = ep1;
|
||||
else
|
||||
init_node = mk_node(en_void, init_node, ep1);
|
||||
}
|
||||
// vim:ts=4:sw=4
|
||||
352
gtc/src/gen.h
Normal file
352
gtc/src/gen.h
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* code generator
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifndef GEN_H
|
||||
#define GEN_H
|
||||
|
||||
/* addressing modes */
|
||||
|
||||
#ifdef MC680X0
|
||||
#define F_DREG 1 /* data register direct mode allowed */
|
||||
#define F_AREG 2 /* address register direct mode allowed */
|
||||
#define F_MEM 4 /* memory alterable modes allowed */
|
||||
#define F_IMMED 8 /* immediate mode allowed */
|
||||
#define F_ALT 7 /* alterable modes */
|
||||
#define F_DALT 5 /* data-alterable modes */
|
||||
#define F_ALL 15 /* all modes allowed */
|
||||
#define F_VOL 16 /* need volatile operand */
|
||||
#define F_NOVALUE 32 /* dont need result value */
|
||||
#define F_USES 64 /* need result value more than once */
|
||||
/* (this forbids autoincrement modes) */
|
||||
#define F_DEREF 128 /* for derefenced use only (eg allow #L1) */
|
||||
#define F_SRCOP 256 /* for source operand only (eg allow L1(pc)) */
|
||||
#endif /* MC680X0 */
|
||||
|
||||
#ifdef INTEL_386
|
||||
#define F_REG 1 /* a register, like %eax, %edi etc. */
|
||||
#define F_MEM 2 /* direct, indirect, indexed */
|
||||
#define F_IMMED 4 /* immedate */
|
||||
#define F_FPSTACK 8 /* top of floating-point stack */
|
||||
#define F_NOVALUE 16 /* dont need result value */
|
||||
#define F_VOL 32 /* need scratch register */
|
||||
#define F_ALL 15 /* any mode */
|
||||
#define F_NOEDI 64 /* do not use %edi and %esi */
|
||||
#endif /* INTEL_386 */
|
||||
|
||||
/* The instructions */
|
||||
|
||||
#ifdef MC680X0
|
||||
/*
|
||||
* The order of the branch instructions must not be changed
|
||||
* since array revcond[] in the peephole optimizer and
|
||||
* truejp/falsejp in the code generator rely on them.
|
||||
* Beware of OUT_AS too.
|
||||
* In addition, peep::SPEED_OPT assumes that (op_jmp,op_rts)<op_bra<_op_cond
|
||||
*/
|
||||
enum e_op {
|
||||
// 0x00
|
||||
op_move, op_moveq, op_clr, op_lea, /* destructive instructions */
|
||||
op_add, op_addi, op_addq, op_sub, op_subi,
|
||||
op_subq, op_muls, op_mulu, op_divs, op_divu, op_and, op_andi,
|
||||
// 0x10
|
||||
op_or, op_ori, op_eor, op_eori, op_lsl, op_lsr, op_jmp, op_jsr, op_movem,
|
||||
op_rts, op_bra, op_bsr, op_beq, op_bne,
|
||||
// 0x1E
|
||||
op_bhs, op_bge, op_bhi, op_bgt, op_bls, op_ble, op_blo, op_blt, /* unsigned, signed */
|
||||
op_tst, op_ext, op_swap,
|
||||
// 0x29
|
||||
op_neg, op_not, op_cmp, op_link, op_unlk, op_label,
|
||||
op_pea, op_cmpi, op_dbra, op_asr, op_bset, op_bclr, op_bchg, _op_asm, _op_adj,
|
||||
#ifdef INFINITE_REGISTERS
|
||||
_op_cleanup_for_external_call,
|
||||
#endif
|
||||
// 0x38
|
||||
#ifdef ASM
|
||||
/* ASM-only */
|
||||
op_asl, op_rol, op_ror, op_roxl, op_roxr, op_btst, op_exg, op_dc, op_ds, op_dcb,
|
||||
// 0x42
|
||||
op_bvs, op_bvc, op_bpl, op_bmi, op_trap, op_negx, op_addx, op_subx,
|
||||
// 0x4A
|
||||
op_chk, op_even,
|
||||
/*op_dbt,*/ /*op_dbf,*/ op_dbeq, op_dbne,
|
||||
#ifndef LIGHT_DBXX_AND_SXX
|
||||
op_dbhs, op_dbge, op_dbhi, op_dbgt, op_dbls, op_dble, op_dblo, op_dblt,/* unsigned, signed */
|
||||
op_dbvs, op_dbvc, op_dbpl, op_dbmi,
|
||||
op_st, op_sf, op_seq, op_sne,
|
||||
op_shs, op_sge, op_shi, op_sgt, op_sls, op_sle, op_slo, op_slt, /* unsigned, signed */
|
||||
op_svs, op_svc, op_spl, op_smi,
|
||||
op_tas,
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
#define op_destroy(__op) (__op<=op_lea)
|
||||
#define _op_bxx_min op_bra
|
||||
#define _op_bcond_min op_beq
|
||||
#define _op_bxx_max op_blt
|
||||
#ifdef ASM
|
||||
#define op_bxx op_bra: case op_bsr: case op_beq: case op_bne: case op_bhs: case op_bge: case op_bhi: case op_bgt: case op_bls: case op_ble: case op_blo: case op_blt: case op_bpl: case op_bmi: case op_bvc: case op_bvs
|
||||
#else
|
||||
#define op_bxx op_bra: case op_bsr: case op_beq: case op_bne: case op_bhs: case op_bge: case op_bhi: case op_bgt: case op_bls: case op_ble: case op_blo: case op_blt
|
||||
#endif
|
||||
#define op_bcond op_beq: case op_bne: case op_bhs: case op_bge: case op_bhi: case op_bgt: case op_bls: case op_ble: case op_blo: case op_blt
|
||||
#define op_dbxx op_dbra: case op_dbeq: case op_dbne
|
||||
#ifdef ASM
|
||||
#ifndef LIGHT_DBXX_AND_SXX
|
||||
#define _op_max op_tas
|
||||
#else
|
||||
#define _op_max op_dbne
|
||||
#endif
|
||||
#else
|
||||
#define _op_max _op_adj
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef INTEL_386
|
||||
enum e_op {
|
||||
op_movsbl, op_movzbl, op_movswl, op_movzwl,
|
||||
op_movsbw, op_movzbw,
|
||||
op_cltd,
|
||||
op_mov, op_lea,
|
||||
op_not, op_neg,
|
||||
op_add, op_sub, op_imul, op_idiv,
|
||||
op_and, op_or, op_xor,
|
||||
op_inc, op_dec,
|
||||
op_cmp,
|
||||
op_push, op_pop,
|
||||
op_jmp, op_bra, op_call, op_leave, op_ret,
|
||||
op_test,
|
||||
op_je, op_jne,
|
||||
op_jl, op_jle, op_jg, op_jge,
|
||||
op_ja, op_jae, op_jb, op_jbe,
|
||||
op_rep, op_smov,
|
||||
op_shl, op_shr, op_asr,
|
||||
op_fadd, op_fsub, op_fdiv, op_fmul,
|
||||
op_fsubr, op_fdivr,
|
||||
op_fld, op_fst, op_fstp, op_fpop,
|
||||
op_fild, op_ftst,
|
||||
op_fchs, op_fcompp, op_fnstsw, op_sahf,
|
||||
op_label
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef MC680X0
|
||||
/* CAUTION : changing this order requires changing sz_table, */
|
||||
/* modifying out68k_as::Pass1() */
|
||||
/* and requires am_immed to be right before am_direct and */
|
||||
/* am_areg right before am_ind */
|
||||
/* - in addition, changing am_dreg is not recommended... - */
|
||||
enum e_am {
|
||||
am_dreg, am_areg, am_ind, am_ainc, am_adec, am_indx, am_indx2,
|
||||
am_indx3, am_immed, am_direct, am_mask1, am_mask2,
|
||||
/* AS-only (subcases of am_direct) : */
|
||||
am_pcrel, am_dirw, am_dirl,
|
||||
/* ASM-only */
|
||||
am_sr, am_ccr, am_usp,
|
||||
};
|
||||
#define am_deref(x) ((x)+1)
|
||||
#define am_doderef(x) (++(x))
|
||||
#define am_is_increment(x) ((x)==am_ainc || (x)==am_adec)
|
||||
#endif
|
||||
|
||||
#ifdef INTEL_386
|
||||
enum e_am {
|
||||
am_reg, am_indx, am_indx2, am_direct, am_immed, am_star, am_fpstack
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef INFINITE_REGISTERS
|
||||
#if 0
|
||||
typedef struct {
|
||||
int n;
|
||||
} reg_t;
|
||||
#define init_reg_t(x) {x}
|
||||
#define nil_reg_t {-1}
|
||||
#else
|
||||
typedef int reg_t;
|
||||
#define init_reg_t(x) (x)
|
||||
#define nil_reg_t (-1)
|
||||
#endif
|
||||
#define FIRSTREG 1000
|
||||
#define MAX_ADDR 100000
|
||||
#define MAX_DATA 100000
|
||||
#define AREGBASE 400000
|
||||
#define TDREGBASE 300000
|
||||
#define TAREGBASE 700000
|
||||
#define reg_t_to_regexp(x) ((x)>=AREGBASE?2*((x)-AREGBASE-MAX_ADDR)+1:2*((x)-MAX_DATA))
|
||||
#define REGEXP_SIZE 20000
|
||||
#else
|
||||
#define reg_t char
|
||||
#define init_reg_t(x) (x)
|
||||
#define nil_reg_t 0
|
||||
#define AREGBASE 8
|
||||
#define FIRSTREG 0
|
||||
#define reg_t_to_regexp(x) (x)
|
||||
#define REGEXP_SIZE 16
|
||||
#define TDREGBASE 0
|
||||
#endif
|
||||
#define CONVENTION_MAX_DATA 2
|
||||
#define CONVENTION_MAX_ADDR 1
|
||||
|
||||
/* addressing mode structure */
|
||||
|
||||
struct amode {
|
||||
enum(e_am) mode;
|
||||
struct enode *offset;
|
||||
/*
|
||||
* these chars may be unsigned...
|
||||
*/
|
||||
reg_t preg, sreg;
|
||||
char deep, slen;
|
||||
};
|
||||
|
||||
#define NIL_AMODE ( (struct amode *) 0)
|
||||
|
||||
/* output code structure */
|
||||
|
||||
struct ocode {
|
||||
enum(e_op) opcode;
|
||||
struct ocode *fwd, *back;
|
||||
struct amode *oper1, *oper2;
|
||||
int length;
|
||||
#ifdef DB_POSSIBLE
|
||||
int line;
|
||||
#endif
|
||||
#ifdef AS
|
||||
char sz,opt;
|
||||
#endif
|
||||
};
|
||||
struct lbls {
|
||||
enum(e_op) opcode;
|
||||
struct ocode *fwd, *back;
|
||||
int lab;
|
||||
};
|
||||
|
||||
/* register naming, special registers */
|
||||
|
||||
#ifdef MC680X0
|
||||
#ifdef INFINITE_REGISTERS
|
||||
#define RESULT (TDREGBASE+0) /* register returning function results */
|
||||
#define PRESULT (TAREGBASE+0) /* register returning pointer function results */
|
||||
#ifdef USE_LINK
|
||||
#define FRAMEPTR (TAREGBASE+6) /* frame pointer register */
|
||||
#else
|
||||
#define TRUE_FRAMEPTR (TAREGBASE+6)
|
||||
#define FRAMEPTR (TAREGBASE+8) /* frame pointer pseudo-register */
|
||||
#endif
|
||||
#define STACKPTR (TAREGBASE+7) /* system stack pointer register */
|
||||
#else
|
||||
#define RESULT 0 /* register returning function results */
|
||||
#define PRESULT 8 /* register returning pointer function results */
|
||||
#ifdef USE_LINK
|
||||
#define FRAMEPTR 14 /* frame pointer register */
|
||||
#else
|
||||
#define TRUE_FRAMEPTR 14
|
||||
#define FRAMEPTR 16 /* frame pointer pseudo-register */
|
||||
#endif
|
||||
#define STACKPTR 15 /* system stack pointer register */
|
||||
#endif
|
||||
#endif /* MC680X0 */
|
||||
|
||||
#ifdef INTEL_386
|
||||
#define RESULT 0 /* reg ret. integer-type function results */
|
||||
#define EAX 0
|
||||
#define EDX 1
|
||||
#define EBX 2
|
||||
#define ECX 3
|
||||
#define ESI 4
|
||||
#define EDI 5
|
||||
#define ESP 6
|
||||
#define STACKPTR 6 /* system stack pointer */
|
||||
#define EBP 7 /* frame pointer */
|
||||
#define FRAMEPTR 7
|
||||
/* attention: same order as above */
|
||||
#define AX 8
|
||||
#define DX 9
|
||||
#define BX 10
|
||||
#define CX 11
|
||||
#define SI 12
|
||||
#define DI 13
|
||||
/* attention: same order as above */
|
||||
#define AL 14
|
||||
#define DL 15
|
||||
#define BL 16
|
||||
#define CL 17
|
||||
|
||||
#define NUMREG REG8(EBP)
|
||||
|
||||
/*
|
||||
* The code generator does not distinguish between %eax, %ax, %al
|
||||
* because some assemblers want it strict, the real register names
|
||||
* are determined when the assembly instruction is PRINTED, e.g.
|
||||
* code generator produces movb junk,%eax,
|
||||
* assembly code printer prints movb junk,%al
|
||||
* The conversion is done by the following macros
|
||||
*/
|
||||
#define REG16(X) ((X)-EAX+AX)
|
||||
#define REG8(X) ((X)-EAX+AL)
|
||||
#endif
|
||||
|
||||
#ifdef MC680X0
|
||||
#ifndef INFINITE_REGISTERS
|
||||
#define MAX_REG_STACK 30
|
||||
|
||||
#define MAX_ADDR 1 /* max. scratch address register (A1) */
|
||||
#define MAX_DATA 2 /* max. scratch data register (D2) */
|
||||
#endif
|
||||
#endif
|
||||
#ifdef INTEL_386
|
||||
#define MAX_REG 1 /* scratch registers: %eax..%edx */
|
||||
#endif
|
||||
|
||||
struct reg_struct {
|
||||
enum(e_am) mode;
|
||||
int reg;
|
||||
int flag; /* flags if pushed or corresponding reg_alloc
|
||||
* number */
|
||||
};
|
||||
|
||||
struct amode *g_expr();
|
||||
struct amode *mk_reg();
|
||||
#ifdef MC680X0
|
||||
struct amode *temp_data();
|
||||
struct amode *temp_addr();
|
||||
#endif
|
||||
#ifdef INTEL_386
|
||||
struct amode *get_register();
|
||||
#endif
|
||||
struct amode *mk_offset();
|
||||
struct amode *g_cast();
|
||||
struct amode *g_fcall();
|
||||
struct amode *func_result();
|
||||
struct amode *as_fcall();
|
||||
#ifdef MC68000
|
||||
struct amode *mk_rmask();
|
||||
struct amode *mk_smask();
|
||||
#endif
|
||||
struct amode *mk_label();
|
||||
struct amode *mk_strlab();
|
||||
struct amode *mk_immed(long i);
|
||||
struct amode *g_offset();
|
||||
struct amode *mk_legal();
|
||||
struct amode *copy_addr();
|
||||
#endif
|
||||
void truejp();
|
||||
void falsejp();
|
||||
|
||||
void g_code(enum(e_op) op, int len, struct amode *ap1, struct amode *ap2);
|
||||
|
||||
void initstack();
|
||||
void freeop(struct amode *ap);
|
||||
// vim:ts=4:sw=4
|
||||
3536
gtc/src/gen68k.c
Normal file
3536
gtc/src/gen68k.c
Normal file
File diff suppressed because it is too large
Load Diff
174
gtc/src/genffp.c
Normal file
174
gtc/src/genffp.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* Fast Floating-Point generator
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following floating-point operations are needed in this module:
|
||||
*
|
||||
* - comparision with 0.0, 0.5 and 1.0 - division by 2.0 - multiplication with
|
||||
* 2.0 (performed as addition here) - subtraction of 1.0
|
||||
*/
|
||||
|
||||
#ifndef NOFLOAT
|
||||
#ifdef PC
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#ifndef BCDFLT
|
||||
unsigned long double2ffp(double d) {
|
||||
unsigned long mantissa;
|
||||
int sign = 0, exponent = 64, i;
|
||||
|
||||
if (d < 0.0) {
|
||||
sign = 128;
|
||||
d = -d;
|
||||
}
|
||||
while (d < 0.5) {
|
||||
d += d;
|
||||
--exponent;
|
||||
if (exponent == 0)
|
||||
return sign; /* zero fp number */
|
||||
}
|
||||
|
||||
while (d >= 1.0) {
|
||||
d /= 2.0;
|
||||
++exponent;
|
||||
if (exponent >= 127)
|
||||
return 127 + sign; /* +/- infinity */
|
||||
}
|
||||
|
||||
/* 0.5 <=d <1.0 now: construct the mantissa */
|
||||
|
||||
mantissa = 0;
|
||||
for (i = 0; i < 24; i++) {
|
||||
/* 24 mantissa bits */
|
||||
d += d;
|
||||
mantissa = mantissa + mantissa;
|
||||
if (d >= 1.0) {
|
||||
++mantissa;
|
||||
d -= 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
/* round up, if the next bit would be 1 */
|
||||
if (d >= 0.5)
|
||||
++mantissa;
|
||||
/* check on mantissa overflow */
|
||||
if (mantissa > 0xFFFFFF) {
|
||||
++exponent;
|
||||
/* exponent overflow? */
|
||||
if (exponent >= 127)
|
||||
return (127 + sign);
|
||||
mantissa >>= 1;
|
||||
}
|
||||
/* put the parts together and return the value */
|
||||
|
||||
return (mantissa << 8) + sign + exponent;
|
||||
}
|
||||
#else
|
||||
void double2bcd(double d,struct bcd *bcd) {
|
||||
unsigned char *mantptr=bcd->mantissa;
|
||||
int bias = 16384, exponent = 0, i;
|
||||
|
||||
if (d < 0.0) {
|
||||
bias += 32768;
|
||||
d = -d;
|
||||
}
|
||||
if (d != 0.0) {
|
||||
while (d < 1.0) {
|
||||
d *= 10.0;
|
||||
--exponent;
|
||||
if (exponent < -999) {
|
||||
d = 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (d >= 10.0) {
|
||||
d /= 10.0;
|
||||
++exponent;
|
||||
}
|
||||
|
||||
if (d==0.0) {
|
||||
bcd->exponent=16384;
|
||||
memset(bcd->mantissa,0,BCDLEN);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 1.0 <= d < 10.0 now: construct the mantissa */
|
||||
|
||||
d += 5e-16; /* round up now */
|
||||
for (i = 0; i < BCDLEN; i++) {
|
||||
unsigned char digit,buffer;
|
||||
/* 8 mantissa groups of 2 digits */
|
||||
if (d>=5.0) {
|
||||
if (d>=7.0) {
|
||||
if (d>=8.0) {
|
||||
if (d>=9.0)
|
||||
digit=9;
|
||||
else digit=8;
|
||||
} else digit=7;
|
||||
} else if (d>=6.0)
|
||||
digit=6;
|
||||
else digit=5;
|
||||
} else {
|
||||
if (d>=2.0) {
|
||||
if (d>=3.0) {
|
||||
if (d>=4.0)
|
||||
digit=4;
|
||||
else digit=3;
|
||||
} else digit=2;
|
||||
} else if (d>=1.0)
|
||||
digit=1;
|
||||
else digit=0;
|
||||
}
|
||||
d -= digit;
|
||||
d *= 10.0;
|
||||
buffer = digit<<4;
|
||||
if (d>=5.0) {
|
||||
if (d>=7.0) {
|
||||
if (d>=8.0) {
|
||||
if (d>=9.0)
|
||||
digit=9;
|
||||
else digit=8;
|
||||
} else digit=7;
|
||||
} else if (d>=6.0)
|
||||
digit=6;
|
||||
else digit=5;
|
||||
} else {
|
||||
if (d>=2.0) {
|
||||
if (d>=3.0) {
|
||||
if (d>=4.0)
|
||||
digit=4;
|
||||
else digit=3;
|
||||
} else digit=2;
|
||||
} else if (d>=1.0)
|
||||
digit=1;
|
||||
else digit=0;
|
||||
}
|
||||
d -= digit;
|
||||
d *= 10.0;
|
||||
*mantptr++ = buffer | digit;
|
||||
}
|
||||
|
||||
/* put the parts together and return the value */
|
||||
bcd->exponent = exponent+bias;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* !defined(BCDFLT) */
|
||||
#endif /* defined(PC) */
|
||||
#endif /* !defined(NOFLOAT) */
|
||||
// vim:ts=4:sw=4
|
||||
1248
gtc/src/genstmt.c
Normal file
1248
gtc/src/genstmt.c
Normal file
File diff suppressed because it is too large
Load Diff
718
gtc/src/getasm.c
Normal file
718
gtc/src/getasm.c
Normal file
@ -0,0 +1,718 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* inline assembly extraction routines
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifdef ASM
|
||||
#define DECLARE
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
#ifdef PC
|
||||
#ifdef SHORT_INT
|
||||
#undef int
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#ifdef SHORT_INT
|
||||
#define int short
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define newline semicolon
|
||||
|
||||
#ifndef AS
|
||||
#define label(__l) 12345
|
||||
#endif
|
||||
|
||||
xstatic char * readonly asmreservedlist[] = {
|
||||
"a0",
|
||||
"a1",
|
||||
"a2",
|
||||
"a3",
|
||||
"a4",
|
||||
"a5",
|
||||
"a6",
|
||||
"a7",
|
||||
"b",
|
||||
"ccr",
|
||||
"d0",
|
||||
"d1",
|
||||
"d2",
|
||||
"d3",
|
||||
"d4",
|
||||
"d5",
|
||||
"d6",
|
||||
"d7",
|
||||
"l",
|
||||
"s",
|
||||
"sp",
|
||||
"sr",
|
||||
"usp",
|
||||
"w",
|
||||
};
|
||||
|
||||
xstatic readonly struct oplst_elem {
|
||||
char *s;
|
||||
enum(e_op) ov;
|
||||
short val;
|
||||
} oplist[] =
|
||||
|
||||
{{
|
||||
"add", op_add
|
||||
}, {
|
||||
"adda", op_add
|
||||
}, {
|
||||
"addi", op_addi
|
||||
}, {
|
||||
"addq", op_addq
|
||||
}, {
|
||||
"addx", op_addx
|
||||
}, {
|
||||
"and", op_and
|
||||
}, {
|
||||
"andi", op_andi
|
||||
}, {
|
||||
"asl", op_asl
|
||||
}, {
|
||||
"asr", op_asr
|
||||
}, {
|
||||
"bcc", op_bhs
|
||||
}, {
|
||||
"bchg", op_bchg
|
||||
}, {
|
||||
"bclr", op_bclr
|
||||
}, {
|
||||
"bcs", op_blo
|
||||
}, {
|
||||
"beq", op_beq
|
||||
}, {
|
||||
"bge", op_bge
|
||||
}, {
|
||||
"bgt", op_bgt
|
||||
}, {
|
||||
"bhi", op_bhi
|
||||
}, {
|
||||
"bhs", op_bhs
|
||||
}, {
|
||||
"ble", op_ble
|
||||
}, {
|
||||
"blo", op_blo
|
||||
}, {
|
||||
"bls", op_bls
|
||||
}, {
|
||||
"blt", op_blt
|
||||
}, {
|
||||
"bmi", op_bmi
|
||||
}, {
|
||||
"bne", op_bne
|
||||
}, {
|
||||
"bpl", op_bpl
|
||||
}, {
|
||||
"bra", op_bra
|
||||
}, {
|
||||
"bset", op_bset
|
||||
}, {
|
||||
"bsr", op_bsr
|
||||
}, {
|
||||
"btst", op_btst
|
||||
}, {
|
||||
"bvs", op_bvs
|
||||
}, {
|
||||
"bvc", op_bvc
|
||||
}, {
|
||||
"chk", op_chk
|
||||
}, {
|
||||
"clr", op_clr
|
||||
}, {
|
||||
"cmp", op_cmp
|
||||
}, {
|
||||
"cmpi", op_cmpi
|
||||
}, {
|
||||
#ifndef LIGHT_DBXX_AND_SXX
|
||||
"dbcc", op_dbhs
|
||||
}, {
|
||||
"dbcs", op_dblo
|
||||
}, {
|
||||
#endif
|
||||
"dbeq", op_dbeq
|
||||
}, {
|
||||
"dbf", op_dbra
|
||||
}, {
|
||||
#ifndef LIGHT_DBXX_AND_SXX
|
||||
"dbge", op_dbge
|
||||
}, {
|
||||
"dbgt", op_dbgt
|
||||
}, {
|
||||
"dbhi", op_dbhi
|
||||
}, {
|
||||
"dbhs", op_dbhs
|
||||
}, {
|
||||
"dble", op_dble
|
||||
}, {
|
||||
"dblo", op_dblo
|
||||
}, {
|
||||
"dbls", op_dbls
|
||||
}, {
|
||||
"dblt", op_dblt
|
||||
}, {
|
||||
"dbmi", op_dbmi
|
||||
}, {
|
||||
#endif
|
||||
"dbne", op_dbne
|
||||
}, {
|
||||
#ifndef LIGHT_DBXX_AND_SXX
|
||||
"dbpl", op_dbpl
|
||||
}, {
|
||||
#endif
|
||||
"dbra", op_dbra
|
||||
}, {
|
||||
#ifndef LIGHT_DBXX_AND_SXX
|
||||
"dbvs", op_dbvs
|
||||
}, {
|
||||
"dbvc", op_dbvc
|
||||
}, {
|
||||
#endif
|
||||
"dc", op_dc
|
||||
}, {
|
||||
"dcb", op_dcb
|
||||
}, {
|
||||
"divs", op_divs
|
||||
}, {
|
||||
"divu", op_divu
|
||||
}, {
|
||||
"ds", op_ds
|
||||
}, {
|
||||
"eor", op_eor
|
||||
}, {
|
||||
"eori", op_eori
|
||||
}, {
|
||||
"even", op_even
|
||||
}, {
|
||||
"exg", op_exg
|
||||
}, {
|
||||
"ext", op_ext
|
||||
}, {
|
||||
"jmp", op_jmp
|
||||
}, {
|
||||
"jsr", op_jsr
|
||||
}, {
|
||||
"lea", op_lea
|
||||
}, {
|
||||
"link", op_link
|
||||
}, {
|
||||
"lsl", op_lsl
|
||||
}, {
|
||||
"lsr", op_lsr
|
||||
}, {
|
||||
"move", op_move
|
||||
}, {
|
||||
"movea", op_move
|
||||
}, {
|
||||
"movem", op_movem
|
||||
}, {
|
||||
"moveq", op_moveq
|
||||
}, {
|
||||
"muls", op_muls
|
||||
}, {
|
||||
"mulu", op_mulu
|
||||
}, {
|
||||
"neg", op_neg
|
||||
}, {
|
||||
"negx", op_negx
|
||||
}, {
|
||||
"nop", op_dc, 0x4e71
|
||||
}, {
|
||||
"not", op_not
|
||||
}, {
|
||||
"or", op_or
|
||||
}, {
|
||||
"ori", op_ori
|
||||
}, {
|
||||
"pea", op_pea
|
||||
}, {
|
||||
"rol", op_rol
|
||||
}, {
|
||||
"ror", op_ror
|
||||
}, {
|
||||
"roxl", op_roxl
|
||||
}, {
|
||||
"roxr", op_roxr
|
||||
}, {
|
||||
"rte", op_dc, 0x4e73
|
||||
}, {
|
||||
"rtr", op_dc, 0x4e77
|
||||
}, {
|
||||
"rts", op_rts
|
||||
}, {
|
||||
#ifndef LIGHT_DBXX_AND_SXX
|
||||
"scc", op_shs
|
||||
}, {
|
||||
"scs", op_slo
|
||||
}, {
|
||||
"seq", op_seq
|
||||
}, {
|
||||
"sf", op_sf
|
||||
}, {
|
||||
"sge", op_sge
|
||||
}, {
|
||||
"sgt", op_sgt
|
||||
}, {
|
||||
"shi", op_shi
|
||||
}, {
|
||||
"shs", op_shs
|
||||
}, {
|
||||
"sle", op_sle
|
||||
}, {
|
||||
"slo", op_slo
|
||||
}, {
|
||||
"sls", op_sls
|
||||
}, {
|
||||
"slt", op_slt
|
||||
}, {
|
||||
"smi", op_smi
|
||||
}, {
|
||||
"sne", op_sne
|
||||
}, {
|
||||
"spl", op_spl
|
||||
}, {
|
||||
"st", op_st
|
||||
}, {
|
||||
#endif
|
||||
"sub", op_sub
|
||||
}, {
|
||||
"suba", op_sub
|
||||
}, {
|
||||
"subi", op_subi
|
||||
}, {
|
||||
"subq", op_subq
|
||||
}, {
|
||||
"subx", op_subx
|
||||
}, {
|
||||
#ifndef LIGHT_DBXX_AND_SXX
|
||||
"svs", op_svs
|
||||
}, {
|
||||
"svc", op_svc
|
||||
}, {
|
||||
#endif
|
||||
"swap", op_swap
|
||||
}, {
|
||||
"tas", op_tas
|
||||
}, {
|
||||
"trap", op_trap
|
||||
}, {
|
||||
"trapv", op_dc, 0x4e76
|
||||
}, {
|
||||
"tst", op_tst
|
||||
}, {
|
||||
"unlk", op_unlk
|
||||
}};
|
||||
#ifndef LIGHT_DBXX_AND_SXX
|
||||
#define asm_N 118
|
||||
#else
|
||||
#define asm_N 85
|
||||
#endif
|
||||
|
||||
int lastreg CGLOB;
|
||||
|
||||
void asm_getsym() {
|
||||
int l=lineid;
|
||||
getsym();
|
||||
if (lineid!=l)
|
||||
cached_sym=lastst, cached_lineid = lineid, lastst=newline;
|
||||
}
|
||||
|
||||
struct ocode *asm_head CGLOB;
|
||||
xstatic struct ocode *asm_tail CGLOB;
|
||||
struct ocode *new_code(int s) {
|
||||
struct ocode *new_ocode;
|
||||
new_ocode = (struct ocode *) xalloc(s, OCODE);
|
||||
#ifdef NO_CALLOC
|
||||
new_ocode->fwd = 0;
|
||||
#endif
|
||||
if (!asm_head) {
|
||||
asm_head = new_ocode;
|
||||
#ifdef NO_CALLOC
|
||||
new_ocode->back = 0;
|
||||
#endif
|
||||
} else {
|
||||
new_ocode->back = asm_tail;
|
||||
asm_tail->fwd = new_ocode;
|
||||
}
|
||||
return asm_tail = new_ocode;
|
||||
}
|
||||
|
||||
void add_code(enum(e_op) op, int len, struct amode *ap1, struct amode *ap2, int line) {
|
||||
/*
|
||||
* generate a code sequence into the asm list.
|
||||
*/
|
||||
struct ocode *new_ocode = new_code(sizeof(struct ocode));
|
||||
new_ocode->opcode = op;
|
||||
new_ocode->length = len;
|
||||
if ((unsigned int)len>4 || len==3)
|
||||
ierr(ADD_CODE,1);
|
||||
new_ocode->oper1 = ap1;
|
||||
new_ocode->oper2 = ap2;
|
||||
#ifdef DB_POSSIBLE
|
||||
new_ocode->line=line;
|
||||
#endif
|
||||
#ifdef AS
|
||||
new_ocode->opt = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void add_label(int lab) {
|
||||
struct lbls *new_ocode = (struct lbls *)new_code(sizeof(struct lbls));
|
||||
new_ocode->opcode = op_label;
|
||||
new_ocode->lab = lab;
|
||||
}
|
||||
|
||||
int has_autocon(struct enode *ep) {
|
||||
switch (ep->nodetype) {
|
||||
case en_icon:
|
||||
#ifndef NOFLOAT
|
||||
case en_fcon:
|
||||
#endif
|
||||
case en_labcon:
|
||||
case en_nacon:
|
||||
return 0;
|
||||
case en_autocon:
|
||||
return 1;
|
||||
case en_add:
|
||||
return has_autocon(ep->v.p[0]) + has_autocon(ep->v.p[1]);
|
||||
case en_sub:
|
||||
return has_autocon(ep->v.p[0]) - has_autocon(ep->v.p[1]);
|
||||
case en_uminus:
|
||||
return - has_autocon(ep->v.p[0]);
|
||||
default:
|
||||
uerrc("invalid expression");
|
||||
return 0; // avoid compiler warning
|
||||
}
|
||||
}
|
||||
void get_offset(struct amode *ap) {
|
||||
asm_xflag++;
|
||||
asm_zflag++;
|
||||
/* if (!strcmp(lastid,"__Int5_body__"))
|
||||
printf("fgio");*/
|
||||
if (!exprnc(&ap->offset))
|
||||
error(ERR_INTEXPR);
|
||||
else {
|
||||
opt4(&ap->offset);
|
||||
if (ap->offset->nodetype==en_deref)
|
||||
ap->offset=ap->offset->v.p[0];
|
||||
#ifdef OLD_AMODE_INPUT
|
||||
if (lastst==kw_offs_end) {
|
||||
#else
|
||||
if (lastst==openpa) {
|
||||
#endif
|
||||
asm_getsym();
|
||||
if (lastst==kw_areg) {
|
||||
ap->preg=lastreg;
|
||||
asm_getsym();
|
||||
if (lastst==comma) {
|
||||
asm_getsym();
|
||||
ap->sreg=lastreg;
|
||||
if (lastst==kw_dreg)
|
||||
ap->mode=am_indx2;
|
||||
else if (lastst==kw_areg)
|
||||
ap->mode=am_indx3;
|
||||
else error(ERR_SYNTAX);
|
||||
asm_getsym();
|
||||
if (lastst==dot) {
|
||||
#ifdef EXT_AS_ID
|
||||
asm_getsym();
|
||||
#else
|
||||
char c=lastch;
|
||||
#endif
|
||||
ap->slen=0;
|
||||
#ifdef EXT_AS_ID
|
||||
if (lastst==id && lastid[1]==0) {
|
||||
char c=lastid[0];
|
||||
#endif
|
||||
if (c=='b' || c=='s') ap->slen=1;
|
||||
else if (c=='w') ap->slen=2;
|
||||
else if (c=='l') ap->slen=4;
|
||||
#ifdef EXT_AS_ID
|
||||
asm_getsym();
|
||||
}
|
||||
#else
|
||||
getch();
|
||||
asm_getsym();
|
||||
#endif
|
||||
if (!ap->slen)
|
||||
error(ERR_SYNTAX);
|
||||
} else ap->slen=2;
|
||||
} else ap->mode=am_indx;
|
||||
needpunc(closepa);
|
||||
} else if (lastst==id && !strcmp("pc",lastid))
|
||||
ap->mode=am_pcrel, asm_getsym()/* 'pc' */, asm_getsym()/* ')' */;
|
||||
} else
|
||||
ap->mode=am_direct;
|
||||
if (has_autocon(ap->offset)) {
|
||||
if (ap->mode!=am_direct && (ap->mode!=am_indx || ap->preg<TRUE_FRAMEPTR-AREGBASE))
|
||||
error(ERR_INTEXPR);
|
||||
ap->mode=am_indx, ap->preg=FRAMEPTR-AREGBASE;
|
||||
}
|
||||
}
|
||||
asm_zflag--;
|
||||
asm_xflag--;
|
||||
}
|
||||
|
||||
xstatic enum(e_op) lastop CGLOB;
|
||||
xstatic int lastval CGLOB,second_parm CGLOB;
|
||||
struct amode *get_asmparam() {
|
||||
struct amode *ap = (struct amode *) xalloc((int) sizeof(struct amode), AMODE);
|
||||
ap->preg=lastreg;
|
||||
/* if ((long)&ap->offset==0x7D53CC)
|
||||
printf("gio");*/
|
||||
if (lastop==op_movem && (lastst==kw_dreg || lastst==kw_areg)) {
|
||||
unsigned int mask=0; int n,d,x;
|
||||
if (second_parm) ap->mode=am_mask2,x=0;
|
||||
else ap->mode=am_mask1,x=15;
|
||||
/* Format : d0=0x8000 in mask1, 0x0001 in mask2 */
|
||||
while (lastst==kw_dreg || lastst==kw_areg) {
|
||||
d=n=lastreg+((lastst-kw_dreg)<<3);
|
||||
asm_getsym();
|
||||
if (lastst==minus) {
|
||||
asm_getsym();
|
||||
if (lastst==kw_dreg || lastst==kw_areg)
|
||||
d=lastreg+((lastst-kw_dreg)<<3);
|
||||
else error(ERR_SYNTAX);
|
||||
asm_getsym();
|
||||
}
|
||||
if (n>d)
|
||||
error(ERR_SYNTAX);
|
||||
while (n<=d) {
|
||||
mask |= 1<<(n^x);
|
||||
n++;
|
||||
}
|
||||
if (lastst==divide)
|
||||
asm_getsym();
|
||||
}
|
||||
ap->offset=mk_icon(mask);
|
||||
} else if (lastst==kw_dreg)
|
||||
ap->mode=am_dreg, asm_getsym();
|
||||
else if (lastst==kw_areg)
|
||||
ap->mode=am_areg, asm_getsym();
|
||||
else if (lastst==openpa) {
|
||||
asm_getsym();
|
||||
if (lastst==kw_areg) {
|
||||
ap->preg=lastreg;
|
||||
asm_getsym();
|
||||
needpunc(closepa);
|
||||
if (lastst==plus)
|
||||
asm_getsym(), ap->mode=am_ainc;
|
||||
else ap->mode=am_ind;
|
||||
} else {
|
||||
cached_sym=lastst;
|
||||
cached_lineid=lineid;
|
||||
lastst=openpa;
|
||||
get_offset(ap);
|
||||
}
|
||||
} else if (lastst==minus) {
|
||||
if (lastch=='(') { // a bit dirty, but doesn't matter since you never type '- (an)'
|
||||
asm_getsym(); // remove '-'
|
||||
asm_getsym(); // remove '('
|
||||
if (lastst==kw_areg) {
|
||||
ap->preg=lastreg;
|
||||
asm_getsym();
|
||||
needpunc(closepa);
|
||||
ap->mode=am_adec;
|
||||
} else {
|
||||
get_offset(ap);
|
||||
needpunc(closepa);
|
||||
ap->offset=mk_node(en_uminus,ap->offset,NIL_ENODE);
|
||||
opt4(&ap->offset);
|
||||
}
|
||||
} else get_offset(ap);
|
||||
} else if (lastst==sharp) {
|
||||
asm_getsym();
|
||||
get_offset(ap);
|
||||
if (ap->mode!=am_direct)
|
||||
error(ERR_SYNTAX);
|
||||
else ap->mode=am_immed;
|
||||
} else if (lastst==id && ((!lastid[2] && lastid[1]=='r' && lastid[0]=='s') ||
|
||||
(!lastid[3] && ((lastid[2]=='r' && lastid[1]=='c' && lastid[0]=='c') ||
|
||||
(lastid[2]=='p' && lastid[0]=='u' && lastid[1]=='s'))))) {
|
||||
ap->mode=lastid[2]?(lastid[0]=='u'?am_usp:am_ccr):am_sr;
|
||||
getsym();
|
||||
} else get_offset(ap);
|
||||
return ap;
|
||||
}
|
||||
|
||||
/* dichotomic keyword search */
|
||||
void asm_searchkw() {
|
||||
char *s1,*s2,c;
|
||||
const struct oplst_elem *op_ptr;
|
||||
int a=0,b=asm_N-1,m;
|
||||
#ifdef PC
|
||||
if (sizeof(oplist)/sizeof(struct oplst_elem)!=asm_N)
|
||||
fatal("BUILD ERROR, WRONG ASM KEYWORDS #");
|
||||
#endif
|
||||
/* if (!strcmp("addq",lastid))
|
||||
printf("");*/
|
||||
while (a<=b) {
|
||||
m=(a+b)>>1;
|
||||
op_ptr=&oplist[m];
|
||||
s1=lastid;
|
||||
s2=op_ptr->s;
|
||||
do {
|
||||
if (!(c=*s2++)) {
|
||||
if (!*s1) {
|
||||
lastst=kw_instr;
|
||||
lastop=op_ptr->ov;
|
||||
lastval=op_ptr->val;
|
||||
return;
|
||||
}
|
||||
/* otherwise continue ( < 'addi' doesn't match 'add' but yet exists) */
|
||||
}
|
||||
} while (*s1++==c);
|
||||
if (s1[-1]<c) // il faut aller plus haut
|
||||
b=m-1;
|
||||
else a=m+1;
|
||||
}
|
||||
}
|
||||
int asm_isreserved() {
|
||||
char *s1,*s2,c;
|
||||
int a=0,b=sizeof(asmreservedlist)/sizeof(char*)-1,m;
|
||||
while (a<=b) {
|
||||
m=(a+b)>>1;
|
||||
s1=lastid;
|
||||
s2=asmreservedlist[m];
|
||||
do {
|
||||
if (!(c=*s2++)) {
|
||||
if (!*s1)
|
||||
return 1;
|
||||
/* otherwise continue ( < 'addi' doesn't match 'add' but yet exists) */
|
||||
}
|
||||
} while (*s1++==c);
|
||||
if (s1[-1]<c) // il faut aller plus haut
|
||||
b=m-1;
|
||||
else a=m+1;
|
||||
}
|
||||
asm_searchkw();
|
||||
return (lastst==kw_instr);
|
||||
}
|
||||
|
||||
|
||||
int getasm_main() {
|
||||
int has_lab=0;
|
||||
restart:
|
||||
if (lastst==newline) {
|
||||
has_lab=0;
|
||||
asm_getsym();
|
||||
goto restart;
|
||||
} else if (lastst==kw_instr) {
|
||||
int line=lineid,l=0,v=lastval; struct amode *ap1=0,*ap2=0;
|
||||
enum(e_op) op=lastop;
|
||||
int cont=1;
|
||||
asm_getsym();
|
||||
if (lastst!=newline) {
|
||||
if (lastst==dot) {
|
||||
#ifndef EXT_AS_ID
|
||||
char c=lastch;
|
||||
if (c=='b' || c=='s') l=1;
|
||||
else if (c=='w') l=2;
|
||||
else if (c=='l') l=4;
|
||||
getch();
|
||||
asm_getsym();
|
||||
#else
|
||||
asm_getsym();
|
||||
if (lastst==id && lastid[1]==0) {
|
||||
char c=lastid[0];
|
||||
if (c=='b' || c=='s') l=1;
|
||||
else if (c=='w') l=2;
|
||||
else if (c=='l') l=4;
|
||||
asm_getsym();
|
||||
}
|
||||
#endif
|
||||
if (!l) {
|
||||
error(ERR_SYNTAX);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
if (lastst!=newline && lastst!=end) {
|
||||
second_parm=0;
|
||||
ap1=get_asmparam();
|
||||
if (lineid==line && lastst!=newline && lastst!=end) {
|
||||
// since exprnc calls getsym, not asm_getsym
|
||||
if (lastst!=comma)
|
||||
cont=0;/*error(ERR_PUNCT);*/
|
||||
else if (op!=op_dc) {
|
||||
asm_getsym();
|
||||
if (lastst!=newline)
|
||||
second_parm=1,ap2=get_asmparam();
|
||||
} else {
|
||||
while (lineid==line && lastst==comma) {
|
||||
asm_getsym();
|
||||
add_code(op,l,ap1,0,line);
|
||||
ap1=get_asmparam();
|
||||
}
|
||||
}
|
||||
} else if ((int)cached_sym IS_INVALID) // otherwise it's because last getsym was
|
||||
cached_sym=lastst, // an asm_getsym, and we already know the 'NL'
|
||||
cached_lineid=lineid,
|
||||
lastst=newline;
|
||||
}
|
||||
}
|
||||
if (v) {
|
||||
if (ap1)
|
||||
uerrc("too many arguments");
|
||||
ap1=mk_offset(mk_icon(v)), ap2=0;
|
||||
l=2; // always 16-bit declaration
|
||||
}
|
||||
add_code(op,l,ap1,ap2,line);
|
||||
return cont;
|
||||
} else if (lastst==id) { /* it's a label */
|
||||
if (has_lab) // forbid multiple labels on one single line
|
||||
error(ERR_SYNTAX);
|
||||
has_lab=1;
|
||||
add_label(label(lastid));
|
||||
asm_getsym();
|
||||
if (lastst==colon)
|
||||
asm_getsym();
|
||||
goto restart;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
struct snode *asmstmt(void) {
|
||||
/*
|
||||
* asmstmt parses the gtc c asm statement.
|
||||
*/
|
||||
struct snode *snp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_asm;
|
||||
snp->count = 1;
|
||||
asm_flag++;
|
||||
asm_head = 0;
|
||||
getsym();
|
||||
if (lastst == kw_volatile)
|
||||
getsym();
|
||||
if (lastst != begin)
|
||||
error(ERR_EXPREXPECT);
|
||||
asm_getsym();
|
||||
while (getasm_main());
|
||||
snp->v1.i=(long)asm_head;
|
||||
asm_flag--;
|
||||
needpunc(end);
|
||||
needpunc(semicolon);
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=lineid;
|
||||
#endif
|
||||
return snp;
|
||||
}
|
||||
#undef newline
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
2293
gtc/src/getsym.c
Normal file
2293
gtc/src/getsym.c
Normal file
File diff suppressed because it is too large
Load Diff
43
gtc/src/gtdevcomm.c
Normal file
43
gtc/src/gtdevcomm.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* (on-calc) communication with the GT-Dev IDE
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "GtDevComm.h"
|
||||
|
||||
extern int has_error;
|
||||
|
||||
char *in_file CGLOB,*out_file CGLOB;
|
||||
Msg_Callback_t msg_process CGLOB;
|
||||
Progr_Callback_t progr_process CGLOB;
|
||||
#include "identity.h"
|
||||
void _gtdevmain(void);
|
||||
int Compile(char *in,char *out,Msg_Callback_t _msg_process,Progr_Callback_t _progr_process) {
|
||||
void *old_a5=bssdata;
|
||||
int res;
|
||||
bssdata=malloc(BSS_SIZE);
|
||||
if (!bssdata) return;
|
||||
memset(bssdata,0,BSS_SIZE);
|
||||
in_file=in; out_file=out;
|
||||
msg_process=_msg_process;
|
||||
progr_process=_progr_process;
|
||||
_gtdevmain();
|
||||
bssdata=identity(bssdata);
|
||||
if (!bssdata)
|
||||
return 2;
|
||||
res=has_error;
|
||||
free(bssdata);
|
||||
bssdata=old_a5;
|
||||
return res;
|
||||
}
|
||||
// vim:ts=4:sw=4
|
||||
44
gtc/src/gtdevcomm.h
Normal file
44
gtc/src/gtdevcomm.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* (on-calc) communication with the GT-Dev IDE
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifndef __GTDEVCOMM_H
|
||||
#define __GTDEVCOMM_H
|
||||
|
||||
//#include "E:\Paul\89\Ti-GCC\Projects\GT-Dev\SecureCommDef.h"
|
||||
#include "securecommdef.h"
|
||||
|
||||
#define ET_FATAL -2
|
||||
#define ET_WARNING -1
|
||||
#define ET_ERROR 0
|
||||
#define ET_INTERNAL_WARNING 1
|
||||
#define ET_INTERNAL_FAILURE 2
|
||||
#define et_isinternal(x) ((x)>0)
|
||||
#define et_iserror(x) !((x)&1)
|
||||
#if __TIGCC_BETA__*100+__TIGCC_MINOR__>=94
|
||||
#define CALLBACK __ATTR_TIOS_CALLBACK__
|
||||
#else
|
||||
#define CALLBACK
|
||||
#endif
|
||||
typedef void (CALLBACK*Msg_Callback_t)(char *message,int err_type,char *func,char *file,int line,int chr);
|
||||
//typedef _Msg_Callback_t *Msg_Callback_t;
|
||||
#define MAX_PROGRESS 65535
|
||||
typedef void (CALLBACK*Progr_Callback_t)(char *func,char *file,unsigned int fprogress);
|
||||
//typedef _Progr_Callback_t *Progr_Callback_t;
|
||||
|
||||
extern char *in_file,*out_file;
|
||||
extern Msg_Callback_t msg_process;
|
||||
extern Progr_Callback_t progr_process;
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
2259
gtc/src/gtpack/gtpack.c
Normal file
2259
gtc/src/gtpack/gtpack.c
Normal file
File diff suppressed because it is too large
Load Diff
99
gtc/src/gtpack/packhead.h
Normal file
99
gtc/src/gtpack/packhead.h
Normal file
@ -0,0 +1,99 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* original project name: TIGCC Tools Suite
|
||||
* file name: packhead.h
|
||||
* initial date: 14/08/2000
|
||||
* authors: thomas.nussbaumer@gmx.net
|
||||
* Paul Froissart
|
||||
* description: header definition of compressed data
|
||||
*
|
||||
* $Id: packhead.h,v 1.3 2000/08/20 15:24:28 Thomas Nussbaumer Exp $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __PACKHEAD_H__
|
||||
#define __PACKHEAD_H__
|
||||
|
||||
#ifndef EVEN_LZ
|
||||
#define MAGIC_CHAR1 'P'
|
||||
#define MAGIC_CHAR2 'k'
|
||||
#else
|
||||
#define MAGIC_CHAR1 'P'
|
||||
#define MAGIC_CHAR2 'x'
|
||||
#endif
|
||||
|
||||
#define MAX_RLE_ENTRIES 31
|
||||
|
||||
#define COMPACT
|
||||
//#define OLD_HDR
|
||||
|
||||
#ifdef OLD_HDR
|
||||
// size = 8 bytes
|
||||
typedef struct {
|
||||
unsigned char origsize_hi; // original size lowbyte
|
||||
unsigned char origsize_lo; // original size highbyte
|
||||
// unsigned char magic1; // must be equal to MAGIC_CHAR1
|
||||
// unsigned char magic2; // must be equal to MAGIC_CHAR2
|
||||
// unsigned char compsize_lo; // compressed size lowbyte
|
||||
// unsigned char compsize_hi; // compressed size lowbyte
|
||||
unsigned char esc1; // escape >> (8-escBits)
|
||||
// unsigned char notused3;
|
||||
// unsigned char notused4;
|
||||
unsigned char esc2; // escBits
|
||||
unsigned char gamma1; // maxGamma + 1
|
||||
unsigned char gamma2; // (1<<maxGamma)
|
||||
unsigned char extralz; // extraLZPosBits
|
||||
// unsigned char notused1;
|
||||
// unsigned char notused2;
|
||||
unsigned char rleentries; // rleUsed
|
||||
} PackedHeader;
|
||||
#else
|
||||
// size = 12 bytes
|
||||
typedef struct {
|
||||
char magic[4];
|
||||
unsigned char origsize_hi; // original size lowbyte
|
||||
unsigned char origsize_lo; // original size highbyte
|
||||
unsigned char compsize_hi; // compressed size lowbyte
|
||||
unsigned char compsize_lo; // compressed size highbyte
|
||||
unsigned char esc2; // escBits
|
||||
unsigned char esc1; // escape >> (8-escBits)
|
||||
unsigned char extralz; // extraLZPosBits
|
||||
unsigned char rleentries; // rleUsed
|
||||
} PackedHeader;
|
||||
#endif
|
||||
|
||||
|
||||
#define GetUnPackedSize(p) (unsigned int)((p)->origsize_lo | ((p)->origsize_hi << 8))
|
||||
#define IsPacked(p) ((p)->magic1 == MAGIC_CHAR1 && (p)->magic2 == MAGIC_CHAR2)
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned char value[MAX_RLE_ENTRIES];
|
||||
} RLEEntries;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//#############################################################################
|
||||
//###################### NO MORE FAKES BEYOND THIS LINE #######################
|
||||
//#############################################################################
|
||||
//
|
||||
//=============================================================================
|
||||
// Revision History
|
||||
//=============================================================================
|
||||
//
|
||||
// $Log: packhead.h,v $
|
||||
// Revision 1.4 2005/08/04 21:27:43 Paul Froissart
|
||||
// adapted for XPak
|
||||
//
|
||||
// Revision 1.3 2000/08/20 15:24:28 Thomas Nussbaumer
|
||||
// macros to get unpacked size and to check if packed added
|
||||
//
|
||||
// Revision 1.2 2000/08/16 23:08:55 Thomas Nussbaumer
|
||||
// magic characters changed to TP ... t(igcc tools) p(acked file)
|
||||
//
|
||||
// Revision 1.1 2000/08/14 22:49:57 Thomas Nussbaumer
|
||||
// initial version
|
||||
//
|
||||
//
|
||||
108
gtc/src/gtpack/revtools.h
Normal file
108
gtc/src/gtpack/revtools.h
Normal file
@ -0,0 +1,108 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* project name: TIGCC Tools Suite
|
||||
* file name: revtools.h
|
||||
* initial date: 23/08/2000
|
||||
* author: thomas.nussbaumer@gmx.net
|
||||
* description: macros for automatic handling of version number output
|
||||
* which is in sync with the CVS version number
|
||||
*
|
||||
* examine one of the pctools source codes to see how it works ;-)
|
||||
*
|
||||
* [NO CVS ID HERE BY INTENTION]
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [Usage]
|
||||
//
|
||||
// (1) include this file into your tool
|
||||
//
|
||||
//
|
||||
// (2) AFTER (!!) all includes put the following lines into your source code:
|
||||
//
|
||||
// #ifdef CVS_FILE_REVISION
|
||||
// #undef CVS_FILE_REVISION
|
||||
// #endif
|
||||
// ----------------------------------------------------------------------------
|
||||
// DON'T EDIT THE NEXT REVISION BY HAND! THIS IS DONE AUTOMATICALLY BY THE
|
||||
// CVS SYSTEM !!!
|
||||
// ----------------------------------------------------------------------------
|
||||
// #define CVS_FILE_REVISION "$Revision$"
|
||||
//
|
||||
// It must be placed AFTER (!!) all includes otherwise the macros may be
|
||||
// expanded wrong where you use them. For example: if you have added the above
|
||||
// lines at the top of your file and include afterwards a file which does
|
||||
// the same, the version of the included file will be used further due to the
|
||||
// #undef CVS_FILE_REVISION. Everything clear?
|
||||
//
|
||||
//
|
||||
// (3) to output the cvs revision number you can now to a simple:
|
||||
//
|
||||
// printf(CVSREV_PRINTPARAMS)
|
||||
//
|
||||
// if your file has, for example, the revision 1.3 the following string will
|
||||
// be printed: v1.03
|
||||
//
|
||||
// the prefix before the subversion is used to get equal-sized output strings
|
||||
// for mainversions between 1 ... 9 and subversion between 1 .. 99
|
||||
//
|
||||
// if your program leaves that range and you need to have equal-sized output
|
||||
// strings you have to implement it by your own by using the
|
||||
// CVSREV_MAIN and CVSREV_SUB macros which returns the main and sub versions
|
||||
// as plain integers. if there is something wrong with your revision string
|
||||
// CVSREV_MAIN and/or CVSREV_SUB will deliver 0, which is no valid CVS main
|
||||
// or subversion number.
|
||||
//
|
||||
// i will suggest that you use the CVS system. its simple to handle, keeps
|
||||
// track of your revisions and their history and with the smart macros below
|
||||
// you haven't to worry anymore about the version output strings of your
|
||||
// program. if you want a special version number you can force CVS at every
|
||||
// time to give this version number to your program (0 is not allowed as
|
||||
// main and subversion number - thats the only pity)
|
||||
//
|
||||
// within this tools suite every tool will use the automatic version handling
|
||||
// but the tool suite version number itself will be handled "by hand".
|
||||
// this number shouldn't change that quickly as with the tools.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifndef __REV_TOOLS_H__
|
||||
#define __REV_TOOLS_H__
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// just used internally
|
||||
//-----------------------------------------------------------------------------
|
||||
#define CVS_TRUNC_PREFIX ((strlen((CVS_FILE_REVISION))<=11) ? 0 : (CVS_FILE_REVISION+11))
|
||||
#define CVS_FIND_COMMA (strchr(CVS_TRUNC_PREFIX,'.'))
|
||||
#define CVSREV_MAIN (int)(!(CVS_TRUNC_PREFIX) ? 0 : atoi(CVS_TRUNC_PREFIX))
|
||||
#define CVSREV_SUB (int)(!(CVS_TRUNC_PREFIX) ? 0 : (!(CVS_FIND_COMMA) ? 0 : atoi(CVS_FIND_COMMA+1)))
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NOTE: THE FOLLOWING MACRO WILL ONLY HANDLE MAIN VERSION < 10 AT CONSTANT
|
||||
// LENGTH !!!
|
||||
// (subversions from 1 .. 99 are mapped to 01 .. 99)
|
||||
//
|
||||
// the following macro may be used to setup a printf(),sprintf() or fprintf()
|
||||
// call
|
||||
//-----------------------------------------------------------------------------
|
||||
#define CVSREV_PRINTPARAMS "v%d.%02d",CVSREV_MAIN,CVSREV_SUB
|
||||
|
||||
|
||||
#define PRINT_ID(name) fprintf(stderr,"\n");fprintf(stderr, name" ");\
|
||||
fprintf(stderr,CVSREV_PRINTPARAMS);\
|
||||
fprintf(stderr," - TIGCC Tools Suite v"TTV_MAIN TTV_SUB"\n" \
|
||||
"(c) thomas.nussbaumer@gmx.net " TTV_DATE"\n\n");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//#############################################################################
|
||||
//###################### NO MORE FAKES BEYOND THIS LINE #######################
|
||||
//#############################################################################
|
||||
48
gtc/src/gtpack/tt.h
Normal file
48
gtc/src/gtpack/tt.h
Normal file
@ -0,0 +1,48 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* project name: TIGCC Tools Suite
|
||||
* file name: tt.h
|
||||
* initial date: 13/08/2000
|
||||
* author: thomas.nussbaumer@gmx.net
|
||||
* description: generic definitions for TIGCC Tools Suite
|
||||
*
|
||||
* $Id: tt.h,v 1.3 2000/08/23 20:29:43 Thomas Nussbaumer Exp $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __TT_H__
|
||||
#define __TT_H__
|
||||
|
||||
#define CALC_TI89 0
|
||||
#define CALC_TI92P 1
|
||||
|
||||
#define SIGNATURE_TI89 "**TI89**"
|
||||
#define SIGNATURE_TI92P "**TI92P*"
|
||||
|
||||
#define DEFAULT_FOLDER "main"
|
||||
|
||||
#define DEFAULT_ITEMS_PER_LINE 10
|
||||
|
||||
#endif
|
||||
|
||||
//#############################################################################
|
||||
//###################### NO MORE FAKES BEYOND THIS LINE #######################
|
||||
//#############################################################################
|
||||
//
|
||||
//=============================================================================
|
||||
// Revision History
|
||||
//=============================================================================
|
||||
//
|
||||
// $Log: tt.h,v $
|
||||
// Revision 1.3 2000/08/23 20:29:43 Thomas Nussbaumer
|
||||
// added a 'P' to the TI92p definitions
|
||||
//
|
||||
// Revision 1.2 2000/08/23 01:04:41 Thomas Nussbaumer
|
||||
// corrected signature of TI92p
|
||||
//
|
||||
// Revision 1.1 2000/08/13 20:24:16 Thomas Nussbaumer
|
||||
// initial version
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
49
gtc/src/gtpack/ttunpack.h
Normal file
49
gtc/src/gtpack/ttunpack.h
Normal file
@ -0,0 +1,49 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* project name: TIGCC Tools Suite
|
||||
* file name: ttunpack.h
|
||||
* initial date: 14/08/2000
|
||||
* author: thomas.nussbaumer@gmx.net
|
||||
* description: defines of errorcodes of decompression routine and its
|
||||
* declaration
|
||||
* $Id: ttunpack.h,v 1.2 2000/08/20 15:26:21 Thomas Nussbaumer Exp $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __TTUNPACK_H__
|
||||
#define __TTUNPACK_H__
|
||||
|
||||
#define K_GAMMA 1
|
||||
#define M_GAMMA 0
|
||||
|
||||
#define ERRPCK_OKAY 0
|
||||
#define ERRPCK_NOESCFOUND 248
|
||||
#define ERRPCK_ESCBITS 249
|
||||
#define ERRPCK_MAXGAMMA 250
|
||||
#define ERRPCK_EXTRALZP 251
|
||||
#define ERRPCK_NOMAGIC 252
|
||||
#define ERRPCK_OUTBUFOVERRUN 253
|
||||
#define ERRPCK_LZPOSUNDERRUN 254
|
||||
|
||||
int _tt_Decompress(unsigned char *src, unsigned char *dest);
|
||||
#define UnPack _tt_Decompress
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//#############################################################################
|
||||
//###################### NO MORE FAKES BEYOND THIS LINE #######################
|
||||
//#############################################################################
|
||||
//
|
||||
//=============================================================================
|
||||
// Revision History
|
||||
//=============================================================================
|
||||
//
|
||||
// $Log: ttunpack.h,v $
|
||||
// Revision 1.2 2000/08/20 15:26:21 Thomas Nussbaumer
|
||||
// prefix of unpack routine (_tt_) corrected
|
||||
//
|
||||
// Revision 1.1 2000/08/14 22:49:57 Thomas Nussbaumer
|
||||
// initial version
|
||||
//
|
||||
//
|
||||
53
gtc/src/gtpack/ttversion.h
Normal file
53
gtc/src/gtpack/ttversion.h
Normal file
@ -0,0 +1,53 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* project name: TIGCC Tools Suite
|
||||
* file name: ttversion.h
|
||||
* initial date: 13/08/2000
|
||||
* author: thomas.nussbaumer@gmx.net
|
||||
* description: TIGCC Tools Suite version definitions
|
||||
*
|
||||
* $Id: ttversion.h,v 1.7 2000/10/01 14:59:22 Thomas Nussbaumer Exp $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __TTVERSION_H__
|
||||
#define __TTVERSION_H__
|
||||
|
||||
#define TTV_MAIN "0.95"
|
||||
#define TTV_SUB ""
|
||||
#define TTV_DATE "01/10/2000"
|
||||
|
||||
#endif
|
||||
|
||||
//#############################################################################
|
||||
//###################### NO MORE FAKES BEYOND THIS LINE #######################
|
||||
//#############################################################################
|
||||
//
|
||||
//=============================================================================
|
||||
// Revision History
|
||||
//=============================================================================
|
||||
//
|
||||
// $Log: ttversion.h,v $
|
||||
// Revision 1.7 2000/10/01 14:59:22 Thomas Nussbaumer
|
||||
// generic commit
|
||||
//
|
||||
// Revision 1.6 2000/08/27 23:52:39 Thomas Nussbaumer
|
||||
// forcing version to 0.41
|
||||
//
|
||||
// Revision 1.5 2000/08/23 20:31:37 Thomas Nussbaumer
|
||||
// next version step
|
||||
//
|
||||
// Revision 1.4 2000/08/23 01:05:59 Thomas Nussbaumer
|
||||
// next version step
|
||||
//
|
||||
// Revision 1.3 2000/08/16 23:09:15 Thomas Nussbaumer
|
||||
// version actualized to 0.15
|
||||
//
|
||||
// Revision 1.2 2000/08/13 20:26:12 Thomas Nussbaumer
|
||||
// version now 0.10 (preview release)
|
||||
//
|
||||
// Revision 1.1 2000/08/13 16:02:13 Thomas Nussbaumer
|
||||
// initial version
|
||||
//
|
||||
//
|
||||
//
|
||||
22
gtc/src/identity.h
Normal file
22
gtc/src/identity.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* (on-calc) volatilizing a value
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifndef __IDENTITY
|
||||
#define __IDENTITY
|
||||
void *identity(void *x) {
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
434
gtc/src/init.c
Normal file
434
gtc/src/init.c
Normal file
@ -0,0 +1,434 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* initialisations
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#define USE_MEMMGT
|
||||
#include "cglbdec.h"
|
||||
|
||||
long inittype(TYP *,TYP **);
|
||||
static long initstruct(TYP *,TYP **), initarray(TYP *,TYP **), initunion(TYP *,TYP **);
|
||||
static int initchar(), initshort(), initlong(), initpointer();
|
||||
#ifndef NOFLOAT
|
||||
static int initfloat();
|
||||
#ifdef DOUBLE
|
||||
static int initdouble();
|
||||
#endif
|
||||
#endif
|
||||
static struct enode *constexpr();
|
||||
extern TYP *copy_type(TYP *s);
|
||||
|
||||
TYP *copy_type_global(TYP *tp) {
|
||||
TYP *tp2;
|
||||
temp_local++;
|
||||
global_flag++;
|
||||
tp2=copy_type(tp);
|
||||
global_flag--;
|
||||
temp_local--;
|
||||
return tp2;
|
||||
}
|
||||
|
||||
void doinit(struct sym *sp, int align) {
|
||||
nl();
|
||||
if (lastst != assign)
|
||||
genstorage(sp, align);
|
||||
else {
|
||||
struct slit *strtab_old=strtab;
|
||||
int glob = global_flag;
|
||||
int no_locblk = !locblk;
|
||||
/* if (lineid>=0x100)
|
||||
bkpt();*/
|
||||
strtab = 0;
|
||||
global_flag = 0;
|
||||
tmp_use();
|
||||
temp_local++;
|
||||
global_strings++;
|
||||
dseg(); /* select data segment */
|
||||
put_align(align);
|
||||
#ifndef AS
|
||||
if (sp->storage_class == sc_static)
|
||||
put_label((unsigned int) sp->value.i);
|
||||
else
|
||||
g_strlab(sp->name);
|
||||
#else
|
||||
#ifdef PC
|
||||
#define gnu_hook(x,y) ((x)?(x):(y))
|
||||
#else
|
||||
#define gnu_hook(x,y) ((x)?:(y))
|
||||
#endif
|
||||
if (sp->storage_class == sc_static) {
|
||||
extern int glblabel;
|
||||
put_label(gnu_hook(sp->value.splab,sp->value.splab=nxtglabel()));
|
||||
} else
|
||||
put_label(splbl(sp));
|
||||
#endif
|
||||
getsym();
|
||||
(void) inittype(sp->tp,&sp->tp);
|
||||
/* if (strtab)
|
||||
bkpt();*/
|
||||
if (strtab)
|
||||
dumplits();
|
||||
global_strings--;
|
||||
temp_local--;
|
||||
tmp_free(); /* just in case, but shouldn't get used because of temp_local */
|
||||
if (no_locblk && locblk)
|
||||
rel_local();
|
||||
global_flag = glob;
|
||||
strtab = strtab_old;
|
||||
}
|
||||
}
|
||||
|
||||
long inittype(TYP *tp,TYP **tpp) {
|
||||
int brace_seen = 0;
|
||||
long nbytes;
|
||||
if (lastst == begin) {
|
||||
brace_seen = 1;
|
||||
getsym();
|
||||
}
|
||||
switch (tp->type) {
|
||||
case bt_char:
|
||||
case bt_uchar:
|
||||
nbytes = initchar();
|
||||
break;
|
||||
case bt_short:
|
||||
case bt_ushort:
|
||||
nbytes = initshort();
|
||||
break;
|
||||
case bt_pointer:
|
||||
if (tp->val_flag)
|
||||
nbytes = initarray(tp,tpp);
|
||||
else {
|
||||
nbytes = initpointer();
|
||||
}
|
||||
break;
|
||||
case bt_ulong:
|
||||
case bt_long:
|
||||
nbytes = initlong();
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case bt_float:
|
||||
nbytes = initfloat();
|
||||
break;
|
||||
#ifdef DOUBLE
|
||||
case bt_double:
|
||||
nbytes = initdouble();
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
case bt_struct:
|
||||
nbytes = initstruct(tp,tpp);
|
||||
break;
|
||||
case bt_union:
|
||||
nbytes = initunion(tp,tpp);
|
||||
break;
|
||||
default:
|
||||
error(ERR_NOINIT);
|
||||
nbytes = 0;
|
||||
}
|
||||
if (brace_seen)
|
||||
needpunc(end);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/*void modf_btp(TYP *new_btp,TYP *tp) {
|
||||
tp=copy_type(tp);
|
||||
tp->btp=new_btp;
|
||||
modf(tp,modfp);
|
||||
}*/
|
||||
|
||||
extern unsigned int pos;
|
||||
static long initarray(TYP *tp,TYP **tpp) {
|
||||
long nbytes;
|
||||
char *p;
|
||||
int len;
|
||||
#ifdef AS
|
||||
unsigned int max_pos=pos;
|
||||
#endif
|
||||
// tmp_use();
|
||||
nbytes = 0;
|
||||
if (lastst == sconst && (tp->btp->type == bt_char ||
|
||||
tp->btp->type == bt_uchar)) {
|
||||
len = lstrlen;
|
||||
nbytes = len;
|
||||
p = laststr;
|
||||
while (len--)
|
||||
genbyte(*p++);
|
||||
if (!tp->size) /* if tp->size!=0, then the padding stuff takes care of it */
|
||||
genbyte(0), nbytes++;
|
||||
while (nbytes < tp->size)
|
||||
genbyte(0), nbytes++;
|
||||
getsym(); /* skip sconst */
|
||||
} else if (lastst == kw_incbin) {
|
||||
FILE *fp; int size;
|
||||
#ifndef PC
|
||||
unsigned char type;
|
||||
#endif
|
||||
/* getsym();
|
||||
if (lastst!=sconst)
|
||||
error(ERR_SYNTAX);*/
|
||||
skipspace();
|
||||
if (lastch!='"')
|
||||
error(ERR_SYNTAX);
|
||||
getch();
|
||||
getidstr();
|
||||
if (lastch!='"')
|
||||
error(ERR_SYNTAX);
|
||||
getch();
|
||||
getsym();
|
||||
fp=fopen(lastid,"rb");
|
||||
if (!fp)
|
||||
uerr(ERR_CANTOPEN,lastid);
|
||||
#ifdef PC
|
||||
p=malloc(100000);
|
||||
size=fread(p,1,100000,fp);
|
||||
#else
|
||||
p=*(char **)fp;
|
||||
size=*(unsigned short *)p;
|
||||
type=p[size+1];
|
||||
if (type==0xF3 || type==0xE0) size--;
|
||||
else if (type==0xF8) { size--; do size--; while (p[size+1]); }
|
||||
#endif
|
||||
if (tp->size && size>tp->size) size=tp->size;
|
||||
nbytes=size;
|
||||
while (size--) genbyte(*p++);
|
||||
while (nbytes<tp->size) {
|
||||
genbyte(0);
|
||||
nbytes++;
|
||||
}
|
||||
} else if (lastst == end)
|
||||
goto pad;
|
||||
else {
|
||||
int i,additional,size;
|
||||
for (i=0;;) {
|
||||
additional=0;
|
||||
if (lastst == openbr) {
|
||||
getsym(); {
|
||||
int j=intexpr();
|
||||
long diff=tp->btp->size*(j-i);
|
||||
if (lastst == dots) {
|
||||
getsym();
|
||||
additional=intexpr()-j;
|
||||
}
|
||||
if (lastst != closebr) error(ERR_SYNTAX);
|
||||
else {
|
||||
getsym();
|
||||
if (lastst == assign) getsym();
|
||||
if (i<j) {
|
||||
nbytes += diff;
|
||||
while (diff--)
|
||||
genbyte(0);
|
||||
i=j;
|
||||
} else if (j<i) {
|
||||
#ifdef AS
|
||||
move_pos(diff); nbytes+=diff; i=j;
|
||||
#else
|
||||
// uwarn("brackets not supported in non-AS mode");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}}
|
||||
if (additional>=0) {
|
||||
nbytes += (size=inittype(tp->btp,NULL)); i++;
|
||||
#ifdef AS
|
||||
while (additional--) rewrite(size), nbytes+=size, i++;
|
||||
#endif
|
||||
}
|
||||
#ifdef AS
|
||||
if (pos>max_pos) max_pos=pos;
|
||||
#endif
|
||||
if (lastst == comma)
|
||||
getsym();
|
||||
if (lastst == end || lastst == semicolon) {
|
||||
pad:
|
||||
#ifdef AS
|
||||
if (pos<max_pos) move_pos(max_pos-pos), nbytes+=max_pos-pos;
|
||||
#endif
|
||||
while (nbytes < tp->size) {
|
||||
genbyte(0);
|
||||
nbytes++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (tp->size > 0 && nbytes >= tp->size)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if (tp->size == 0)
|
||||
tp->size = nbytes;
|
||||
if (nbytes > tp->size)
|
||||
error(ERR_INITSIZE);
|
||||
#else
|
||||
if (tp->size && nbytes > tp->size)
|
||||
error(ERR_INITSIZE);
|
||||
if (tp->size != nbytes && tpp)
|
||||
/* fix the symbol's size, unless tpp=0 (item of a struct/union or array) */
|
||||
tp = copy_type_global(tp),
|
||||
*tpp = tp,
|
||||
tp->size = nbytes; // we need this for the 'sizeof' operator...
|
||||
#endif
|
||||
// tmp_free();
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static long initunion(TYP *tp,TYP **tpp) {
|
||||
struct sym *sp;
|
||||
long nbytes;
|
||||
|
||||
int brace_seen = 0;
|
||||
if (lastst == begin) {
|
||||
brace_seen = 1;
|
||||
getsym();
|
||||
}
|
||||
|
||||
sp = tp->lst.head;
|
||||
/*
|
||||
* Initialize the first branch
|
||||
*/
|
||||
if (sp == 0)
|
||||
return 0;
|
||||
nbytes = inittype(sp->tp,NULL);
|
||||
while (nbytes < tp->size) {
|
||||
genbyte(0);
|
||||
nbytes++;
|
||||
}
|
||||
|
||||
if (tp->size != nbytes && tpp)
|
||||
tp = copy_type_global(tp),
|
||||
*tpp = tp,
|
||||
tp->size = nbytes; // we need this for the 'sizeof' operator...
|
||||
|
||||
if (brace_seen)
|
||||
needpunc(end);
|
||||
}
|
||||
|
||||
static long initstruct(TYP *tp,TYP **tpp) {
|
||||
struct sym *sp;
|
||||
long nbytes;
|
||||
nbytes = 0;
|
||||
sp = tp->lst.head; /* start at top of symbol table */
|
||||
if (lastst != end)
|
||||
while (sp != 0) {
|
||||
while (nbytes < sp->value.i) { /* align properly */
|
||||
nbytes++;
|
||||
genbyte(0);
|
||||
}
|
||||
nbytes += inittype(sp->tp,NULL);
|
||||
if (lastst == comma)
|
||||
getsym();
|
||||
if (lastst == end || lastst == semicolon)
|
||||
break;
|
||||
sp = sp->next;
|
||||
}
|
||||
while (nbytes < tp->size) {
|
||||
genbyte(0);
|
||||
nbytes++;
|
||||
}
|
||||
if (tp->size != nbytes && tpp)
|
||||
tp = copy_type_global(tp),
|
||||
*tpp = tp,
|
||||
tp->size = nbytes; // we need this for the 'sizeof' operator...
|
||||
|
||||
return tp->size;
|
||||
}
|
||||
|
||||
static int initchar() {
|
||||
genbyte((int) intexpr());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int initshort() {
|
||||
genword((int) intexpr());
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int initlong() {
|
||||
/*
|
||||
* We allow longs to be initialized with pointers now.
|
||||
* Thus, we call constexpr() instead of intexpr.
|
||||
*/
|
||||
#if 0
|
||||
/*
|
||||
* This is more strict
|
||||
*/
|
||||
genlong(intexpr());
|
||||
return 4;
|
||||
#endif
|
||||
genptr(constexpr());
|
||||
return 4;
|
||||
}
|
||||
|
||||
#ifndef NOFLOAT
|
||||
static int initfloat() {
|
||||
#ifndef NOFLOAT
|
||||
double floatexpr();
|
||||
#ifdef PC
|
||||
genfloat(floatexpr());
|
||||
#else
|
||||
#ifndef BCDFLT
|
||||
genptr(floatexpr());
|
||||
#else
|
||||
genfloat(floatexpr());
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#ifdef NOFLOAT
|
||||
genptr(0l);
|
||||
#endif
|
||||
return 4;
|
||||
}
|
||||
|
||||
#ifdef DOUBLE
|
||||
static int initdouble() {
|
||||
#ifdef NOFLOAT
|
||||
int i;
|
||||
for (i=0; i< tp_double.size; i++)
|
||||
genbyte(0);
|
||||
#endif
|
||||
#ifndef NOFLOAT
|
||||
double floatexpr();
|
||||
gendouble(floatexpr());
|
||||
#endif
|
||||
return tp_double.size;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int initpointer() {
|
||||
genptr(constexpr());
|
||||
return 4;
|
||||
}
|
||||
|
||||
static struct enode *constexpr() {
|
||||
struct enode *ep;
|
||||
struct typ *tp;
|
||||
/* if (lineid==0x1e0)
|
||||
bkpt();*/
|
||||
tp=exprnc(&ep);
|
||||
if (tp == 0) {
|
||||
error(ERR_EXPREXPECT);
|
||||
return 0;
|
||||
}
|
||||
opt0(&ep);
|
||||
if (!tst_const(ep)) {
|
||||
error(ERR_CONSTEXPECT);
|
||||
return 0;
|
||||
}
|
||||
return ep;
|
||||
}
|
||||
// vim:ts=4:sw=4
|
||||
96
gtc/src/intexpr.c
Normal file
96
gtc/src/intexpr.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* integer expression routines
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
#ifndef NOFLOAT
|
||||
#include "ffplib.h"
|
||||
#endif
|
||||
|
||||
#ifndef NOFLOAT
|
||||
double floatexpr() {
|
||||
/* floating point expression */
|
||||
struct enode *ep;
|
||||
struct typ *tp;
|
||||
|
||||
tp = exprnc(&ep);
|
||||
if (tp == 0) {
|
||||
error(ERR_FPCON);
|
||||
return (double) 0;
|
||||
}
|
||||
|
||||
opt0(&ep);
|
||||
|
||||
if (ep->nodetype == en_icon)
|
||||
#ifdef PC
|
||||
return (double) ep->v.i;
|
||||
#else
|
||||
return ffpltof(ep->v.i);
|
||||
#endif
|
||||
|
||||
if (ep->nodetype == en_fcon)
|
||||
return ep->v.f;
|
||||
|
||||
error (ERR_SYNTAX);
|
||||
return (double) 0;
|
||||
}
|
||||
#endif /* !NOFLOAT */
|
||||
|
||||
long intexpr() {
|
||||
struct enode *ep;
|
||||
struct typ *tp;
|
||||
long val;
|
||||
|
||||
tmp_use();
|
||||
tp = exprnc(&ep);
|
||||
if (tp == 0) {
|
||||
error(ERR_INTEXPR);
|
||||
return 0;
|
||||
}
|
||||
opt0(&ep);
|
||||
|
||||
if (ep->nodetype != en_icon) {
|
||||
error(ERR_SYNTAX);
|
||||
return 0;
|
||||
}
|
||||
val=ep->v.i;
|
||||
tmp_free();
|
||||
return val;
|
||||
}
|
||||
|
||||
#if 0
|
||||
long intexpr_notemp() {
|
||||
struct enode *ep;
|
||||
struct typ *tp;
|
||||
|
||||
tp = exprnc(&ep);
|
||||
if (tp == 0) {
|
||||
error(ERR_INTEXPR);
|
||||
return 0;
|
||||
}
|
||||
opt0(&ep);
|
||||
|
||||
if (ep->nodetype != en_icon) {
|
||||
error(ERR_SYNTAX);
|
||||
return 0;
|
||||
}
|
||||
return ep->v.i;
|
||||
}
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
532
gtc/src/memmgt.c
Normal file
532
gtc/src/memmgt.c
Normal file
@ -0,0 +1,532 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* memory management
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#define USE_MEMMGT
|
||||
#include "cglbdec.h"
|
||||
|
||||
int glbsize CGLOB, /* size left in current global block */
|
||||
locsize CGLOB, /* size left in current local block */
|
||||
tmpsize CGLOB, /* size left in current temp block */
|
||||
glbindx CGLOB, /* global index */
|
||||
locindx CGLOB, /* local index */
|
||||
tmpindx CGLOB; /* temp index */
|
||||
|
||||
int temp_mem CGLOB,temp_local CGLOB;
|
||||
#ifdef MIN_TEMP_MEM
|
||||
int min_temp_mem CGLOB;
|
||||
#endif
|
||||
|
||||
#ifdef PC
|
||||
int glbmem CGLOB,locmem CGLOB;
|
||||
#endif
|
||||
|
||||
int max_mem CGLOB, /* statistics... */
|
||||
glo_mem CGLOB;
|
||||
|
||||
struct blk *locblk CGLOB, /* pointer to local block list */
|
||||
*glbblk CGLOB, /* pointer to global block list */
|
||||
*tmpblk CGLOB; /* pointer to temporary block list */
|
||||
|
||||
#ifdef PC
|
||||
//void *calloc();
|
||||
#endif
|
||||
static void _err_attr error_memory() {
|
||||
uerrc2("not enough memory to compile function '%s'",func_sp->name);
|
||||
}
|
||||
int *_xalloc(int siz) {
|
||||
struct blk *bp;
|
||||
char *rv;
|
||||
if (temp_local) /* this is NOT perfect, but it's close to being so :) */
|
||||
goto glb_xalloc;
|
||||
/* if (locmem>=50000)
|
||||
bkpt();*/
|
||||
/* if (siz>=1000)
|
||||
bkpt();*/
|
||||
#ifdef MIN_TEMP_MEM
|
||||
if (temp_mem<=min_temp_mem) {
|
||||
#else
|
||||
if (!temp_mem) {
|
||||
#endif
|
||||
glb_xalloc:
|
||||
if (global_flag) {
|
||||
#ifdef PC
|
||||
glbmem += siz;
|
||||
#endif
|
||||
if (glbsize >= siz) {
|
||||
rv = &(glbblk->m[glbindx]);
|
||||
glbsize -= siz;
|
||||
glbindx += siz;
|
||||
/* if ((long)rv==0x789388)
|
||||
bkpt();*/
|
||||
return (int *) rv;
|
||||
} else {
|
||||
// bp = (struct blk *) calloc(1, (int) sizeof(struct blk));
|
||||
bp = (struct blk *) malloc(sizeof(struct blk));
|
||||
if (!bp) {
|
||||
#ifdef PC
|
||||
msg("not enough memory.\n");
|
||||
_exit(1);
|
||||
#else
|
||||
error_memory();
|
||||
fatal("Not enough global memory");
|
||||
#endif
|
||||
}
|
||||
memset(bp, 0, sizeof(struct blk));
|
||||
glo_mem++;
|
||||
bp->next = glbblk;
|
||||
glbblk = bp;
|
||||
glbsize = BLKLEN - siz;
|
||||
glbindx = siz;
|
||||
return (int *) glbblk->m;
|
||||
}
|
||||
} else { /* not global */
|
||||
#ifdef PC
|
||||
locmem += siz;
|
||||
#endif
|
||||
if (locsize >= siz) {
|
||||
rv = &(locblk->m[locindx]);
|
||||
locsize -= siz;
|
||||
/*if ((long)rv==0x7f86bc)
|
||||
bkpt();*/
|
||||
locindx += siz;
|
||||
#ifdef PC
|
||||
if (0x80000000&(long)rv)
|
||||
fatal("A DIRTY HACK FAILED ON YOUR CONFIG. "
|
||||
"LOOK AT OUT68K_AS.C TO SOLVE THE PROBLEM");
|
||||
#endif
|
||||
/* if (func_sp) infunc("chk_curword")
|
||||
if ((long)rv==0x7b4bf8)
|
||||
bkpt();*/
|
||||
/* if ((long)rv==0x7e5cd0)
|
||||
bkpt();*/
|
||||
return (int *) rv;
|
||||
} else {
|
||||
// bp = (struct blk *) calloc(1, (int) sizeof(struct blk));
|
||||
bp = (struct blk *) malloc(sizeof(struct blk));
|
||||
if (!bp) {
|
||||
#ifdef PC
|
||||
msg("not enough local memory.\n");
|
||||
_exit(1);
|
||||
#else
|
||||
error_memory();
|
||||
fatal("Not enough local memory");
|
||||
#endif
|
||||
}
|
||||
memset(bp, 0, sizeof(struct blk));
|
||||
bp->next = locblk;
|
||||
locblk = bp;
|
||||
locsize = BLKLEN - siz;
|
||||
locindx = siz;
|
||||
return (int *) locblk->m;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (tmpsize >= siz) {
|
||||
rv = &(tmpblk->m[tmpindx]);
|
||||
tmpsize -= siz;
|
||||
tmpindx += siz;
|
||||
return (int *) rv;
|
||||
} else {
|
||||
// bp = (struct blk *) calloc(1, (int) sizeof(struct blk));
|
||||
bp = (struct blk *) malloc(sizeof(struct blk));
|
||||
if (!bp) {
|
||||
#ifdef PC
|
||||
msg("not enough temporary memory.\n");
|
||||
_exit(1);
|
||||
#else
|
||||
error_memory();
|
||||
fatal("Not enough temporary memory");
|
||||
#endif
|
||||
}
|
||||
/* if (bp==0x789364)
|
||||
bkpt();*/
|
||||
memset(bp, 0, sizeof(struct blk));
|
||||
bp->next = tmpblk;
|
||||
tmpblk = bp;
|
||||
tmpsize = BLKLEN - siz;
|
||||
tmpindx = siz;
|
||||
return (int *) tmpblk->m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int blk_free(struct blk *bp1) {
|
||||
int blkcnt = 0;
|
||||
struct blk *bp2;
|
||||
while (bp1) {
|
||||
bp2 = bp1->next;
|
||||
(void) free((char *) bp1);
|
||||
blkcnt++;
|
||||
bp1 = bp2;
|
||||
}
|
||||
return blkcnt;
|
||||
}
|
||||
|
||||
#ifdef DUAL_STACK
|
||||
typedef struct _ds_block {
|
||||
void *lo,*hi;
|
||||
struct _ds_block *pop;
|
||||
void *popstackptr;
|
||||
} DS_BLOCK;
|
||||
static DS_BLOCK *ds_current CGLOB;
|
||||
void *dualstack CGLOB;
|
||||
void *ds_currentlo CGLOB,*ds_currenthi CGLOB;
|
||||
|
||||
#ifdef PC
|
||||
int n_ds_allocations CGLOB;
|
||||
#endif
|
||||
void ds_allocatleast(unsigned int size) {
|
||||
size+=DS_BSIZE;
|
||||
DS_BLOCK *ds_new = malloc(sizeof(DS_BLOCK)+size);
|
||||
ds_new->lo = (void *)(ds_new+1);
|
||||
ds_new->hi = (void *)((char *)ds_new->lo+size);
|
||||
ds_new->pop = ds_current;
|
||||
ds_new->popstackptr = dualstack;
|
||||
ds_current = ds_new;
|
||||
ds_currentlo = ds_current->lo;
|
||||
ds_currenthi = ds_current->hi;
|
||||
dualstack = ds_currentlo;
|
||||
#ifdef PC
|
||||
n_ds_allocations++;
|
||||
#endif
|
||||
}
|
||||
void ds_free(void) {
|
||||
DS_BLOCK *ds_old = ds_current;
|
||||
ds_current = ds_old->pop;
|
||||
ds_currentlo = ds_current ? ds_current->lo : 0;
|
||||
ds_currenthi = ds_current ? ds_current->hi : 0;
|
||||
dualstack = ds_old->popstackptr;
|
||||
free(ds_old);
|
||||
}
|
||||
void rel_dualstack(void) {
|
||||
while (ds_current)
|
||||
ds_free();
|
||||
#ifdef PC
|
||||
//msg2(" performed %d dual-stack-related allocations\n",n_ds_allocations);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#define VERBOSE
|
||||
#ifdef GARBAGE_COLLECT
|
||||
void d_enode(struct enode **node) {
|
||||
struct enode *dest,*ep=*node;
|
||||
if (!ep) return;
|
||||
if (ep->nodetype==en_icon) { *node=mk_icon(ep->v.i); return; }
|
||||
dest=xalloc((int)sizeof(struct enode), ENODE);
|
||||
memcpy(dest,ep,sizeof(struct enode));
|
||||
*node=dest;
|
||||
switch (ep->nodetype) {
|
||||
case en_land: case en_lor:
|
||||
case en_asand: case en_asor: case en_asxor:
|
||||
case en_aslsh: case en_asrsh:
|
||||
case en_asmul: case en_asmod: case en_asdiv:
|
||||
case en_asadd: case en_assub:
|
||||
case en_gt: case en_ge:
|
||||
case en_lt: case en_le:
|
||||
case en_eq: case en_ne:
|
||||
case en_cond: case en_assign:
|
||||
case en_and: case en_or: case en_xor:
|
||||
case en_lsh: case en_rsh:
|
||||
case en_mul: case en_mod: case en_div:
|
||||
case en_add: case en_sub:
|
||||
case en_fcall: case en_void:
|
||||
d_enode(&ep->v.p[1]);
|
||||
case en_deref:
|
||||
case en_ainc: case en_adec:
|
||||
case en_uminus: case en_not: case en_compl:
|
||||
case en_ref:
|
||||
case en_cast: /* hum hum */
|
||||
case en_fieldref:
|
||||
d_enode(&ep->v.p[0]);
|
||||
case en_tempref:
|
||||
case en_autocon:
|
||||
case en_labcon:
|
||||
case en_nacon:
|
||||
case en_fcon:
|
||||
return;
|
||||
case en_compound:
|
||||
d_snode(&ep->v.st);
|
||||
return;
|
||||
default:
|
||||
ierr(D_ENODE,1);
|
||||
}
|
||||
}
|
||||
|
||||
void d_snode(struct snode **node) {
|
||||
struct snode *dest,*block=*node;
|
||||
if (!block) return;
|
||||
dest=xalloc((int)sizeof(struct snode), SNODE);
|
||||
memcpy(dest,block,sizeof(struct snode));
|
||||
*node=dest;
|
||||
while (block != 0) {
|
||||
switch (block->stype) {
|
||||
case st_return:
|
||||
case st_expr:
|
||||
d_enode(&block->exp);
|
||||
break;
|
||||
case st_loop:
|
||||
d_enode(&block->exp);
|
||||
d_snode(&block->s1);
|
||||
d_enode(&block->v2.e);
|
||||
break;
|
||||
case st_while:
|
||||
case st_do:
|
||||
d_enode(&block->exp);
|
||||
d_snode(&block->s1);
|
||||
break;
|
||||
case st_for:
|
||||
d_enode(&block->exp);
|
||||
d_enode(&block->v1.e);
|
||||
d_snode(&block->s1);
|
||||
d_enode(&block->v2.e);
|
||||
break;
|
||||
case st_if:
|
||||
d_enode(&block->exp);
|
||||
d_snode(&block->s1);
|
||||
d_snode(&block->v1.s);
|
||||
break;
|
||||
case st_switch:
|
||||
d_enode(&block->exp);
|
||||
d_snode(&block->v1.s);
|
||||
break;
|
||||
case st_case:
|
||||
case st_default:
|
||||
d_snode(&block->v1.s);
|
||||
break;
|
||||
case st_compound:
|
||||
case st_label:
|
||||
d_snode(&block->s1);
|
||||
case st_goto:
|
||||
case st_break:
|
||||
case st_continue:
|
||||
break;
|
||||
case st_asm:
|
||||
d_amode(&(struct amode *)block->v1.i);
|
||||
break;
|
||||
default:
|
||||
ierr(D_SNODE,1);
|
||||
}
|
||||
block = block->next;
|
||||
}
|
||||
}
|
||||
|
||||
void d_amode(struct amode **node) {
|
||||
struct amode *dest,*mode=*node;
|
||||
if (!mode) return;
|
||||
dest=xalloc((int)sizeof(struct amode), AMODE);
|
||||
memcpy(dest,mode,sizeof(struct amode));
|
||||
*node=dest;
|
||||
d_enode(&dest->offset);
|
||||
}
|
||||
extern struct ocode *_peep_head;
|
||||
void d_ocodes(void) {
|
||||
struct ocode *dest=NULL,**node=&_peep_head,*instr;
|
||||
while ((instr=*node)) {
|
||||
instr->back=dest;
|
||||
dest=xalloc((int)sizeof(struct ocode), OCODE);
|
||||
memcpy(dest,instr,sizeof(struct ocode));
|
||||
*node=dest;
|
||||
d_amode(&dest->oper1);
|
||||
d_amode(&dest->oper2);
|
||||
node=&dest->fwd;
|
||||
}
|
||||
*node=NULL;
|
||||
}
|
||||
|
||||
extern struct snode *dump_stmt;
|
||||
void collect(int g) {
|
||||
struct blk *blk=glbblk;
|
||||
glbsize=glbindx=0;
|
||||
glbblk=NIL_BLK;
|
||||
alloc_dump(g);
|
||||
// dump snodes & most enodes
|
||||
// d_snode(&dump_stmt);
|
||||
// dump ocodes & amodes & the rest of enodes
|
||||
// d_ocodes();
|
||||
// dump most syms & most strs & typs & tables & the rest of syms & a few strs
|
||||
d_table(&gsyms); d_table(>ags); d_table(&defsyms);
|
||||
// dump slits & the rest of strs
|
||||
//
|
||||
// no dump is needed for cse's since it is a cooperative garbage-collection
|
||||
}
|
||||
#endif
|
||||
|
||||
int _k_=0;
|
||||
void tmp_use() {
|
||||
temp_mem++;
|
||||
_k_++;
|
||||
}
|
||||
void tmp_free() {
|
||||
if (!--temp_mem && tmpblk) {
|
||||
#ifdef PC
|
||||
int n=0;
|
||||
#endif
|
||||
#ifndef LIFO_TMP_FREE
|
||||
/* Maybe I'm wrong, but I think that this solution
|
||||
* is quite bad for the TIOS heap manager... */
|
||||
struct blk *nxt;
|
||||
while ((nxt=tmpblk->next))
|
||||
#ifdef PC
|
||||
n++,
|
||||
#endif
|
||||
free(tmpblk),tmpblk=nxt;
|
||||
#else
|
||||
struct blk *nxt=tmpblk->next,*tofree;
|
||||
while (nxt)
|
||||
#ifdef PC
|
||||
n++,
|
||||
#endif
|
||||
tofree=nxt, nxt=nxt->next, free(tofree);
|
||||
#endif
|
||||
#ifdef _DBG_SHOW_TEMPMEM
|
||||
printf("*");
|
||||
#ifdef PC
|
||||
printf("(%dk)",n*BLKLEN/1024);
|
||||
// getchar();
|
||||
#endif
|
||||
#endif
|
||||
tmpsize = BLKLEN;
|
||||
tmpindx = 0;
|
||||
memset(tmpblk,0,BLKLEN);
|
||||
/*blk_free(tmpblk);
|
||||
tmpblk = 0;
|
||||
tmpsize = 0;*/
|
||||
}
|
||||
}
|
||||
|
||||
void rel_local() {
|
||||
unsigned int mem;
|
||||
#ifndef AS
|
||||
#define pos 0
|
||||
#else
|
||||
extern unsigned int pos;
|
||||
#endif
|
||||
#ifdef PC
|
||||
#ifdef GARBAGE_COLLECT
|
||||
collect(0);
|
||||
#endif
|
||||
#ifdef LISTING
|
||||
alloc_dump(0);
|
||||
#endif
|
||||
#endif
|
||||
if ((mem=blk_free(locblk))+glo_mem+(2*pos)/BLKLEN > (unsigned int)max_mem) {
|
||||
max_mem = mem+glo_mem+(2*pos)/BLKLEN;
|
||||
/*if (max_mem>330/4)
|
||||
bkpt();*/
|
||||
}
|
||||
#ifndef AS
|
||||
#undef pos
|
||||
#endif
|
||||
#ifdef PC
|
||||
locmem = 0;
|
||||
#endif
|
||||
locblk = 0;
|
||||
locsize = 0;
|
||||
//#ifndef PC
|
||||
#ifndef GTDEV
|
||||
#ifdef PC
|
||||
if (verbose)
|
||||
#endif
|
||||
msg2("%d kb\n", (int)(mem * BLKLEN/1024));
|
||||
#endif
|
||||
//#endif
|
||||
#ifdef VERBOSE
|
||||
#ifdef LISTING
|
||||
#if 0
|
||||
if (list_option)
|
||||
msg2(" releasing %2d kb local tables.\n",
|
||||
mem * BLKLEN/1024);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void rel_global() {
|
||||
int mem;
|
||||
if ((mem=blk_free(glbblk)) > max_mem)
|
||||
max_mem = mem;
|
||||
#ifdef PC
|
||||
glbmem = 0;
|
||||
#endif
|
||||
glo_mem = 0;
|
||||
glbblk = 0;
|
||||
glbsize = 0;
|
||||
blk_free(tmpblk);
|
||||
tmpblk = 0;
|
||||
tmpsize = 0;
|
||||
#ifdef PC
|
||||
#ifdef LISTING
|
||||
alloc_dump(1);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef VERBOSE
|
||||
#ifdef LISTING
|
||||
if (list_option)
|
||||
msg2(" releasing %2d kb global tables.\n",
|
||||
mem * BLKLEN/1024);
|
||||
#endif
|
||||
#ifdef DUAL_STACK
|
||||
//if (ds_current)
|
||||
// msg("oops, a dual stack remains\n");
|
||||
rel_dualstack();
|
||||
#endif
|
||||
#ifndef GTDEV
|
||||
#ifdef PC
|
||||
if (verbose) {
|
||||
msg2("Max memory request : %d kb\n",
|
||||
(int)(max_mem * BLKLEN/1024));
|
||||
msg("\n");
|
||||
if (max_mem * BLKLEN/1024<150)
|
||||
msg("On-calc portability : very good\n");
|
||||
else if (max_mem * BLKLEN/1024<230)
|
||||
msg("On-calc portability : good\n");
|
||||
else if (max_mem * BLKLEN/1024<290)
|
||||
msg("On-calc portability : questionable\n");
|
||||
else if (max_mem * BLKLEN/1024<360)
|
||||
msg("On-calc portability : difficult without splitting\n");
|
||||
else
|
||||
msg("On-calc portabilty : impossible without splitting\n");
|
||||
msg("\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
max_mem = 0;
|
||||
}
|
||||
|
||||
void clean_up() {
|
||||
blk_free(tmpblk);
|
||||
blk_free(locblk);
|
||||
blk_free(glbblk);
|
||||
#ifdef DUAL_STACK
|
||||
//if (ds_current)
|
||||
// msg("oops, a dual stack remains\n");
|
||||
rel_dualstack();
|
||||
#endif
|
||||
temp_mem = 0;
|
||||
glbblk = locblk = tmpblk = 0;
|
||||
/*#ifdef OPTIMIZE_BSS
|
||||
free(bssdata);
|
||||
#endif*/
|
||||
}
|
||||
|
||||
#undef VERBOSE
|
||||
// vim:ts=4:sw=4
|
||||
887
gtc/src/optimize.c
Normal file
887
gtc/src/optimize.c
Normal file
@ -0,0 +1,887 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* optimization
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
|
||||
static void fold_const();
|
||||
|
||||
void dooper(struct enode **node) {
|
||||
/*
|
||||
* dooper will execute a constant operation in a node and modify the node to
|
||||
* be the result of the operation.
|
||||
*/
|
||||
struct enode *ep = *node;
|
||||
enum(e_node) type = ep->nodetype;
|
||||
|
||||
#define ep0 ep->v.p[0]
|
||||
#define ep1 ep->v.p[1]
|
||||
#define epi ep->v.i
|
||||
#define epf ep->v.f
|
||||
#define ulong unsigned long
|
||||
|
||||
ep->nodetype = ep0->nodetype;
|
||||
if (ep0->nodetype == en_fcon) {
|
||||
#ifndef NOFLOAT
|
||||
switch (type) {
|
||||
case en_uminus:
|
||||
#ifdef PC
|
||||
epf = - ep0->v.f;
|
||||
#else
|
||||
epf = ep0->v.f;
|
||||
if (epf) epf^=0x80;
|
||||
#endif
|
||||
break;
|
||||
case en_not:
|
||||
ep->nodetype = en_icon;
|
||||
epi = (ep0->v.f) ? 0 : 1;
|
||||
break;
|
||||
case en_add:
|
||||
#ifdef PC
|
||||
epf = ep0->v.f + ep1->v.f;
|
||||
#else
|
||||
epf = ffpadd(ep0->v.f, ep1->v.f);
|
||||
#endif
|
||||
break;
|
||||
case en_sub:
|
||||
#ifdef PC
|
||||
epf = ep0->v.f - ep1->v.f;
|
||||
#else
|
||||
epf = ffpsub(ep0->v.f, ep1->v.f);
|
||||
#endif
|
||||
break;
|
||||
case en_mul:
|
||||
#ifdef PC
|
||||
epf = ep0->v.f * ep1->v.f;
|
||||
#else
|
||||
epf = ffpmul(ep0->v.f, ep1->v.f);
|
||||
#endif
|
||||
break;
|
||||
case en_div:
|
||||
if (ep1->v.f == 0) {
|
||||
uwarn("division by zero");
|
||||
ep->nodetype = en_div;
|
||||
} else {
|
||||
#ifdef PC
|
||||
epf = ep0->v.f / ep1->v.f;
|
||||
#else
|
||||
epf = ffpdiv(ep0->v.f, ep1->v.f);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case en_eq:
|
||||
ep->nodetype = en_icon;
|
||||
epi = (ep0->v.f == ep1->v.f) ? 1 : 0;
|
||||
break;
|
||||
case en_ne:
|
||||
ep->nodetype = en_icon;
|
||||
epi = (ep0->v.f != ep1->v.f) ? 1 : 0;
|
||||
break;
|
||||
case en_land:
|
||||
ep->nodetype = en_icon;
|
||||
epi = (ep0->v.f && ep1->v.f) ? 1 : 0;
|
||||
break;
|
||||
case en_lor:
|
||||
ep->nodetype = en_icon;
|
||||
epi = (ep0->v.f || ep1->v.f) ? 1 : 0;
|
||||
break;
|
||||
case en_lt:
|
||||
ep->nodetype = en_icon;
|
||||
#ifdef PC
|
||||
epi = (ep0->v.f < ep1->v.f) ? 1 : 0;
|
||||
#else
|
||||
epi = (ffpcmp_c(ep0->v.f, ep1->v.f) < 0) ? 1 : 0;
|
||||
#endif
|
||||
break;
|
||||
case en_le:
|
||||
ep->nodetype = en_icon;
|
||||
#ifdef PC
|
||||
epi = (ep0->v.f <= ep1->v.f) ? 1 : 0;
|
||||
#else
|
||||
epi = (ffpcmp_c(ep0->v.f, ep1->v.f) <= 0) ? 1 : 0;
|
||||
#endif
|
||||
break;
|
||||
case en_gt:
|
||||
ep->nodetype = en_icon;
|
||||
#ifdef PC
|
||||
epi = (ep0->v.f > ep1->v.f) ? 1 : 0;
|
||||
#else
|
||||
epi = (ffpcmp_c(ep0->v.f, ep1->v.f) > 0) ? 1 : 0;
|
||||
#endif
|
||||
break;
|
||||
case en_ge:
|
||||
ep->nodetype = en_icon;
|
||||
#ifdef PC
|
||||
epi = (ep0->v.f >= ep1->v.f) ? 1 : 0;
|
||||
#else
|
||||
epi = (ffpcmp_c(ep0->v.f, ep1->v.f) >= 0) ? 1 : 0;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
ep->nodetype = type;
|
||||
iwarn(DOOPER,1);
|
||||
break;
|
||||
}
|
||||
#endif /* NOFLOAT */
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Thus, ep0->nodetype is en_icon
|
||||
* We have to distinguish unsigned long from the other cases
|
||||
*
|
||||
* Since we always store in ep->v.i, it is
|
||||
* ASSUMED THAT (long) (ulong) ep->v.i == ep->v.i always
|
||||
*/
|
||||
if (ep0->etype == bt_ulong || ep0->etype == bt_pointer) {
|
||||
switch (type) {
|
||||
case en_uminus:
|
||||
epi = - ep0->v.i;
|
||||
break;
|
||||
case en_not:
|
||||
epi = ((ulong) ep0->v.i) ? 0 : 1;
|
||||
break;
|
||||
case en_compl:
|
||||
epi = ~ (ulong) ep0->v.i;
|
||||
epi = strip_icon(epi, ep->etype);
|
||||
break;
|
||||
case en_add:
|
||||
epi = (ulong) ep0->v.i + (ulong) ep1->v.i;
|
||||
break;
|
||||
case en_sub:
|
||||
epi = (ulong) ep0->v.i - (ulong) ep1->v.i;
|
||||
break;
|
||||
case en_mul:
|
||||
epi = (ulong) ep0->v.i * (ulong) ep1->v.i;
|
||||
break;
|
||||
case en_div:
|
||||
if ((ulong) ep1->v.i == 0) {
|
||||
uwarn("division by zero");
|
||||
ep->nodetype = en_div;
|
||||
} else {
|
||||
epi = (ulong) ep0->v.i / (ulong) ep1->v.i;
|
||||
}
|
||||
break;
|
||||
case en_mod:
|
||||
if ((ulong) ep1->v.i == 0) {
|
||||
uwarn("division by zero");
|
||||
ep->nodetype = en_mod;
|
||||
} else {
|
||||
epi = (ulong) ep0->v.i % (ulong) ep1->v.i;
|
||||
}
|
||||
break;
|
||||
case en_and:
|
||||
epi = (ulong) ep0->v.i & (ulong) ep1->v.i;
|
||||
break;
|
||||
case en_or:
|
||||
epi = (ulong) ep0->v.i | (ulong) ep1->v.i;
|
||||
break;
|
||||
case en_xor:
|
||||
epi = (ulong) ep0->v.i ^ (ulong) ep1->v.i;
|
||||
break;
|
||||
case en_eq:
|
||||
epi = ((ulong) ep0->v.i == (ulong) ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_ne:
|
||||
epi = ((ulong) ep0->v.i != (ulong) ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_land:
|
||||
epi = ((ulong) ep0->v.i && (ulong) ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_lor:
|
||||
epi = ((ulong) ep0->v.i || (ulong) ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_lt:
|
||||
epi = ((ulong) ep0->v.i < (ulong) ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_le:
|
||||
epi = ((ulong) ep0->v.i <= (ulong) ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_gt:
|
||||
epi = ((ulong) ep0->v.i > (ulong) ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_ge:
|
||||
epi = ((ulong) ep0->v.i >= (ulong) ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_lsh:
|
||||
#ifdef MINIMAL_SIZES
|
||||
epi = (ulong) ep0->v.i << (char) ep1->v.i;
|
||||
#else
|
||||
epi = (ulong) ep0->v.i << (ulong) ep1->v.i;
|
||||
#endif
|
||||
break;
|
||||
case en_rsh:
|
||||
#ifdef MINIMAL_SIZES
|
||||
epi = (ulong) ep0->v.i >> (char) ep1->v.i;
|
||||
#else
|
||||
epi = (ulong) ep0->v.i >> (ulong) ep1->v.i;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
ep->nodetype = type;
|
||||
iwarn(DOOPER,2);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (type) {
|
||||
case en_uminus:
|
||||
epi = - ep0->v.i;
|
||||
break;
|
||||
case en_not:
|
||||
epi = (ep0->v.i) ? 0 : 1;
|
||||
break;
|
||||
case en_compl:
|
||||
epi = ~ ep0->v.i;
|
||||
epi = strip_icon(epi, type);
|
||||
break;
|
||||
case en_add:
|
||||
epi = ep0->v.i + ep1->v.i;
|
||||
break;
|
||||
case en_sub:
|
||||
epi = ep0->v.i - ep1->v.i;
|
||||
break;
|
||||
case en_mul:
|
||||
epi = ep0->v.i * ep1->v.i;
|
||||
break;
|
||||
case en_div:
|
||||
if (ep1->v.i == 0) {
|
||||
uwarn("division by zero");
|
||||
ep->nodetype = en_div;
|
||||
} else {
|
||||
epi = ep0->v.i / ep1->v.i;
|
||||
}
|
||||
break;
|
||||
case en_mod:
|
||||
if (ep1->v.i == 0) {
|
||||
uwarn("division by zero");
|
||||
ep->nodetype = en_mod;
|
||||
} else {
|
||||
epi = ep0->v.i % ep1->v.i;
|
||||
}
|
||||
break;
|
||||
case en_and:
|
||||
epi = ep0->v.i & ep1->v.i;
|
||||
break;
|
||||
case en_or:
|
||||
epi = ep0->v.i | ep1->v.i;
|
||||
break;
|
||||
case en_xor:
|
||||
epi = ep0->v.i ^ ep1->v.i;
|
||||
break;
|
||||
case en_eq:
|
||||
epi = (ep0->v.i == ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_ne:
|
||||
epi = (ep0->v.i != ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_land:
|
||||
epi = (ep0->v.i && ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_lor:
|
||||
epi = (ep0->v.i || ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_lt:
|
||||
epi = (ep0->v.i < ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_le:
|
||||
epi = (ep0->v.i <= ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_gt:
|
||||
epi = (ep0->v.i > ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_ge:
|
||||
epi = (ep0->v.i >= ep1->v.i) ? 1 : 0;
|
||||
break;
|
||||
case en_lsh:
|
||||
#ifdef MINIMAL_SIZES
|
||||
epi = ep0->v.i << (char)ep1->v.i;
|
||||
#else
|
||||
epi = ep0->v.i << ep1->v.i;
|
||||
#endif
|
||||
break;
|
||||
case en_rsh:
|
||||
#ifdef MINIMAL_SIZES
|
||||
epi = ep0->v.i >> (char)ep1->v.i;
|
||||
#else
|
||||
epi = ep0->v.i >> ep1->v.i;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
ep->nodetype = type;
|
||||
iwarn(DOOPER,3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#undef ep0
|
||||
#undef ep1
|
||||
#undef epi
|
||||
#undef epf
|
||||
#undef ulong
|
||||
}
|
||||
|
||||
int pwrof2(long i) {
|
||||
/*
|
||||
* return which power of two i is or -1.
|
||||
*/
|
||||
int p;
|
||||
long q;
|
||||
q = 2;
|
||||
p = 1;
|
||||
while (q > 0) {
|
||||
if (q == i)
|
||||
return p;
|
||||
q <<= 1;
|
||||
++p;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
long mod_mask(long i) {
|
||||
/*
|
||||
* make a mod mask for a power of two.
|
||||
*/
|
||||
long m;
|
||||
m = 0;
|
||||
while (i--)
|
||||
m = (m << 1) | 1;
|
||||
return m;
|
||||
}
|
||||
|
||||
void opt0(struct enode **node) {
|
||||
/*
|
||||
* opt0 - delete useless expressions and combine constants.
|
||||
*
|
||||
* opt0 will delete expressions such as x + 0,
|
||||
* x - 0,
|
||||
* x * 0,
|
||||
* x * 1,
|
||||
* 0 / x,
|
||||
* x / 1,
|
||||
* x % (1<<3),
|
||||
* etc from the tree pointed to by node and combine obvious
|
||||
* constant operations. It cannot combine name and label constants but will
|
||||
* combine icon type nodes.
|
||||
*/
|
||||
struct enode *ep;
|
||||
|
||||
#define ep0 ep->v.p[0]
|
||||
#define ep1 ep->v.p[1]
|
||||
|
||||
long val, sc;
|
||||
enum(e_node) typ;
|
||||
ep = *node;
|
||||
if (ep == 0)
|
||||
return;
|
||||
typ = ep->nodetype;
|
||||
switch (typ) {
|
||||
case en_ref:
|
||||
case en_fieldref:
|
||||
case en_ainc:
|
||||
case en_adec:
|
||||
case en_deref:
|
||||
opt0(&ep0);
|
||||
break;
|
||||
case en_uminus:
|
||||
case en_compl:
|
||||
opt0(&ep0);
|
||||
/*
|
||||
* This operation applied twice is a no-op
|
||||
*/
|
||||
if (ep0->nodetype == typ) {
|
||||
*node = ep0->v.p[0];
|
||||
break;
|
||||
}
|
||||
if (ep0->nodetype == en_icon || ep0->nodetype == en_fcon)
|
||||
dooper(node);
|
||||
break;
|
||||
case en_not:
|
||||
opt0(&ep0);
|
||||
if (ep0->nodetype == en_icon || ep0->nodetype == en_fcon)
|
||||
dooper(node);
|
||||
break;
|
||||
case en_add:
|
||||
case en_sub:
|
||||
opt0(&ep0);
|
||||
opt0(&ep1);
|
||||
/*
|
||||
* a + (-b) = a - b
|
||||
* a - (-b) = a + b
|
||||
* (-a) + b = b - a
|
||||
*/
|
||||
if (ep1->nodetype == en_uminus) {
|
||||
ep1 = ep1->v.p[0];
|
||||
ep->nodetype = typ = (typ == en_add) ? en_sub : en_add;
|
||||
}
|
||||
if (ep0->nodetype == en_uminus && typ == en_add) {
|
||||
ep0 = ep0->v.p[0];
|
||||
swap_nodes(ep);
|
||||
ep->nodetype = typ = en_sub;
|
||||
}
|
||||
/*
|
||||
* constant expressions
|
||||
*/
|
||||
if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
|
||||
(ep0->nodetype == en_fcon && ep1->nodetype == en_fcon)) {
|
||||
dooper(node);
|
||||
break;
|
||||
}
|
||||
/*infunc("DrawNumberOfClock")
|
||||
bkpt();*/
|
||||
/* the following would bug, as :
|
||||
short my_array[2]={12,570};
|
||||
int i=2;
|
||||
while (i--) printf("%d",my_array[i]);
|
||||
wouldn't print 570 correctly... */
|
||||
#ifdef BUGGY_AND_ANYWAY_NOT_COMPAT_WITH_NO_OFFSET_AUTOCON
|
||||
if (typ == en_add) {
|
||||
if (ep1->nodetype == en_autocon)
|
||||
swap_nodes(ep);
|
||||
}
|
||||
#endif
|
||||
if (ep0->nodetype == en_icon) {
|
||||
if (ep0->v.i == 0) {
|
||||
if (typ == en_sub) {
|
||||
ep0 = ep1;
|
||||
ep->nodetype = typ = en_uminus;
|
||||
} else
|
||||
*node = ep1;
|
||||
break;
|
||||
#ifdef PREFER_POS_VALUES
|
||||
} else if (ep0->nodetype==en_add && ep0->v.i<0) {
|
||||
ep0->v.i=-ep0->v.i;
|
||||
swap_nodes(ep);
|
||||
ep->nodetype=en_sub;
|
||||
#endif
|
||||
}
|
||||
} else if (ep1->nodetype == en_icon) {
|
||||
#ifdef BUGGY_AND_ANYWAY_NOT_COMPAT_WITH_NO_OFFSET_AUTOCON
|
||||
if (ep0->nodetype == en_autocon && typ == en_add) {
|
||||
ep0->v.i += ep1->v.i;
|
||||
*node = ep0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (ep1->v.i == 0) {
|
||||
*node = ep0;
|
||||
break;
|
||||
#ifdef PREFER_POS_VALUES
|
||||
} else if (ep1->v.i<0) {
|
||||
ep->nodetype^=1;
|
||||
ep1->v.i=-ep1->v.i;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
case en_mul:
|
||||
opt0(&ep0);
|
||||
opt0(&ep1);
|
||||
/*
|
||||
* constant expressions
|
||||
*/
|
||||
if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
|
||||
(ep0->nodetype == en_fcon && ep1->nodetype == en_fcon)) {
|
||||
dooper(node);
|
||||
break;
|
||||
}
|
||||
if (ep0->nodetype == en_icon) {
|
||||
val = ep0->v.i;
|
||||
if (val == 0) {
|
||||
*node = ep0;
|
||||
break;
|
||||
}
|
||||
if (val == 1) {
|
||||
*node = ep1;
|
||||
break;
|
||||
}
|
||||
sc = pwrof2(val);
|
||||
if (sc IS_VALID) {
|
||||
swap_nodes(ep);
|
||||
ep1->v.i = sc;
|
||||
ep->nodetype = en_lsh;
|
||||
}
|
||||
} else if (ep1->nodetype == en_icon) {
|
||||
val = ep1->v.i;
|
||||
if (val == 0) {
|
||||
*node = ep1;
|
||||
break;
|
||||
}
|
||||
if (val == 1) {
|
||||
*node = ep0;
|
||||
break;
|
||||
}
|
||||
sc = pwrof2(val);
|
||||
if (sc IS_VALID) {
|
||||
ep1->v.i = sc;
|
||||
ep->nodetype = en_lsh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case en_div:
|
||||
opt0(&ep0);
|
||||
opt0(&ep1);
|
||||
/*
|
||||
* constant expressions
|
||||
*/
|
||||
if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
|
||||
(ep0->nodetype == en_fcon && ep1->nodetype == en_fcon)) {
|
||||
dooper(node);
|
||||
break;
|
||||
}
|
||||
if (ep0->nodetype == en_icon) {
|
||||
if (ep0->v.i == 0) { /* 0/x */
|
||||
*node = ep0;
|
||||
break;
|
||||
}
|
||||
} else if (ep1->nodetype == en_icon) {
|
||||
val = ep1->v.i;
|
||||
if (val == 1) { /* x/1 */
|
||||
*node = ep0;
|
||||
break;
|
||||
}
|
||||
sc = pwrof2(val);
|
||||
if (sc IS_VALID) {
|
||||
ep1->v.i = sc;
|
||||
ep->nodetype = en_rsh;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case en_mod:
|
||||
opt0(&ep0);
|
||||
opt0(&ep1);
|
||||
/*
|
||||
* constant expressions
|
||||
*/
|
||||
if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
|
||||
(ep0->nodetype == en_fcon && ep1->nodetype == en_fcon)) {
|
||||
dooper(node);
|
||||
break;
|
||||
}
|
||||
if (ep1->nodetype == en_icon) {
|
||||
sc = pwrof2(ep1->v.i);
|
||||
if (sc IS_VALID) {
|
||||
ep1->v.i = mod_mask(sc);
|
||||
ep->nodetype = en_and;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case en_land:
|
||||
case en_lor:
|
||||
#if 0 /* perhaps this isn't *that* useful... and ep0/ep1 are long to access */
|
||||
opt0(&ep0);
|
||||
opt0(&ep1);
|
||||
if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
|
||||
(ep0->nodetype == en_fcon && ep1->nodetype == en_fcon))
|
||||
dooper(node);
|
||||
else {
|
||||
typ = (typ==en_lor);
|
||||
if (ep0->nodetype == en_icon) {
|
||||
if ((!ep0->v.i)!=typ) /* absorbing element */
|
||||
ep = ep0;
|
||||
else /* "neutral" element */
|
||||
//ep = ep1; -> not quite, should be !!x
|
||||
(void)0;
|
||||
} else if (ep1->nodetype == en_icon) {
|
||||
if ((!ep1->v.i)!=typ) /* absorbing element */
|
||||
ep->nodetype = en_void, ep1->v.i=typ;
|
||||
else /* "neutral" element */
|
||||
//ep = ep0; -> not quite, should be !!x
|
||||
(void)0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#else
|
||||
/* FALL THROUGH */
|
||||
#endif
|
||||
case en_and:
|
||||
case en_or:
|
||||
case en_xor:
|
||||
case en_eq:
|
||||
case en_ne:
|
||||
case en_lt:
|
||||
case en_le:
|
||||
case en_gt:
|
||||
case en_ge:
|
||||
opt0(&ep0);
|
||||
opt0(&ep1);
|
||||
/*
|
||||
* constant expressions
|
||||
*/
|
||||
if ((ep0->nodetype == en_icon && ep1->nodetype == en_icon) ||
|
||||
(ep0->nodetype == en_fcon && ep1->nodetype == en_fcon))
|
||||
dooper(node);
|
||||
break;
|
||||
case en_lsh:
|
||||
case en_rsh:
|
||||
opt0(&ep0);
|
||||
opt0(&ep1);
|
||||
if (ep0->nodetype == en_icon && ep1->nodetype == en_icon) {
|
||||
dooper(node);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* optimize a << 0 and a >> 0
|
||||
*/
|
||||
if (ep1->nodetype == en_icon && ep1->v.i == 0)
|
||||
*node = ep0;
|
||||
break;
|
||||
case en_cond:
|
||||
opt0(&ep0);
|
||||
opt0(&ep1);
|
||||
if (ep0->nodetype == en_icon) {
|
||||
if (ep0->v.i) {
|
||||
if (ep1->v.p[0]) *node=ep1->v.p[0];
|
||||
else *node=ep0;
|
||||
} else
|
||||
*node=ep1->v.p[1];
|
||||
}
|
||||
break;
|
||||
case en_asand:
|
||||
case en_asor:
|
||||
case en_asxor:
|
||||
case en_asadd:
|
||||
case en_assub:
|
||||
case en_asmul:
|
||||
case en_asdiv:
|
||||
case en_asmod:
|
||||
case en_asrsh:
|
||||
case en_aslsh:
|
||||
case en_fcall:
|
||||
case en_void:
|
||||
case en_assign:
|
||||
opt0(&ep0);
|
||||
opt0(&ep1);
|
||||
break;
|
||||
/* now handled in expr.c */
|
||||
case en_cast:
|
||||
opt0(&ep0);
|
||||
if (ep0->nodetype == en_icon) {
|
||||
#ifndef NOFLOAT
|
||||
if (ep->etype != bt_float
|
||||
#ifdef DOUBLE
|
||||
&& ep->etype != bt_double
|
||||
#endif
|
||||
) {
|
||||
#endif
|
||||
ierr(OPT0,1);
|
||||
/* ep->nodetype = en_icon;
|
||||
ep->v.i = ep0->v.i;*/
|
||||
#ifndef NOFLOAT
|
||||
} else {
|
||||
#ifdef XCON_DOESNT_SUPPORT_FLOATS
|
||||
#error Fix me now :)
|
||||
#endif
|
||||
ep->nodetype = en_fcon;
|
||||
#ifdef PC
|
||||
ep->v.f = (double)ep0->v.i;
|
||||
#else
|
||||
#ifndef BCDFLT
|
||||
ep->v.f = ffpltof(ep0->v.i);
|
||||
#else
|
||||
ep->v.f = (double)ep0->v.i;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* perhaps BUGGY */
|
||||
else if ((ep0->nodetype == en_labcon || ep0->nodetype == en_nacon)
|
||||
&& ep->esize<=ep0->esize) {
|
||||
ep0->etype = ep->etype;
|
||||
ep0->esize = ep->esize;
|
||||
ep=ep0;
|
||||
*node=ep;
|
||||
}
|
||||
#ifndef NOFLOAT
|
||||
else if (ep0->nodetype == en_fcon && bt_integral(ep->etype)) {
|
||||
ep->nodetype = en_icon;
|
||||
#ifdef PC
|
||||
ep->v.i = (long)ep0->v.f;
|
||||
#else
|
||||
ep->v.i = ffpftol(ep0->v.f);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
/*case en_icon:
|
||||
case en_fcon:
|
||||
case en_labcon:
|
||||
case en_nacon:
|
||||
case en_autocon:
|
||||
case en_tempref:
|
||||
break;
|
||||
default:
|
||||
uwarn("Didn't optimize nodetype %d. Please send me your source code.",typ);*/
|
||||
}
|
||||
|
||||
#undef ep0
|
||||
#undef ep1
|
||||
}
|
||||
|
||||
static long xfold(struct enode *node) {
|
||||
/*
|
||||
* xfold will remove constant nodes and return the values to the calling
|
||||
* routines.
|
||||
*/
|
||||
long i;
|
||||
if (node == 0)
|
||||
return 0;
|
||||
switch (node->nodetype) {
|
||||
case en_icon:
|
||||
i = node->v.i;
|
||||
node->v.i = 0;
|
||||
return i;
|
||||
case en_add:
|
||||
return xfold(node->v.p[0]) + xfold(node->v.p[1]);
|
||||
case en_sub:
|
||||
return xfold(node->v.p[0]) - xfold(node->v.p[1]);
|
||||
case en_mul:
|
||||
if (node->v.p[0]->nodetype == en_icon)
|
||||
return xfold(node->v.p[1]) * node->v.p[0]->v.i;
|
||||
else if (node->v.p[1]->nodetype == en_icon)
|
||||
return xfold(node->v.p[0]) * node->v.p[1]->v.i;
|
||||
else {
|
||||
fold_const(&node->v.p[0]);
|
||||
fold_const(&node->v.p[1]);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* CVW: This seems wrong to me... case en_lsh: if(
|
||||
* node->v.p[0]->nodetype == en_icon ) return xfold(node->v.p[1]) <<
|
||||
* node->v.p[0]->v.i; else if( node->v.p[1]->nodetype == en_icon )
|
||||
* return xfold(node->v.p[0]) << node->v.p[1]->v.i; else return 0;
|
||||
*/
|
||||
case en_uminus:
|
||||
return -xfold(node->v.p[0]);
|
||||
case en_lsh:
|
||||
case en_rsh:
|
||||
case en_div:
|
||||
case en_mod:
|
||||
case en_asadd:
|
||||
case en_assub:
|
||||
case en_asmul:
|
||||
case en_asdiv:
|
||||
case en_asmod:
|
||||
case en_and:
|
||||
case en_land:
|
||||
case en_or:
|
||||
case en_lor:
|
||||
case en_xor:
|
||||
case en_asand:
|
||||
case en_asor:
|
||||
case en_asxor:
|
||||
case en_void:
|
||||
case en_fcall:
|
||||
case en_assign:
|
||||
case en_eq:
|
||||
case en_ne:
|
||||
case en_lt:
|
||||
case en_le:
|
||||
case en_gt:
|
||||
case en_ge:
|
||||
fold_const(&node->v.p[0]);
|
||||
fold_const(&node->v.p[1]);
|
||||
return 0;
|
||||
case en_ref:
|
||||
case en_fieldref:
|
||||
case en_compl:
|
||||
case en_not:
|
||||
case en_deref:
|
||||
fold_const(&node->v.p[0]);
|
||||
return 0;
|
||||
/*
|
||||
* This is not stricly legal: (long)(x+10) * 4l might not be the same
|
||||
* as (long)(x) * 4l + 40l but it is the same as long as no overflows
|
||||
* occur
|
||||
*/
|
||||
case en_cast:
|
||||
#ifdef DONTDEF
|
||||
return xfold(node->v.p[0]);
|
||||
#endif
|
||||
/*
|
||||
* Well, sometimes I prefer purity to efficiency
|
||||
* It is a matter of taste how you decide here....
|
||||
*/
|
||||
fold_const(&node->v.p[0]);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fold_const(struct enode **node) {
|
||||
/*
|
||||
* reorganize an expression for optimal constant grouping.
|
||||
*/
|
||||
struct enode *ep;
|
||||
long i;
|
||||
ep = *node;
|
||||
if (ep == 0)
|
||||
return;
|
||||
if (ep->nodetype == en_add) {
|
||||
if (ep->v.p[0]->nodetype == en_icon) {
|
||||
ep->v.p[0]->v.i += xfold(ep->v.p[1]);
|
||||
return;
|
||||
} else if (ep->v.p[1]->nodetype == en_icon) {
|
||||
ep->v.p[1]->v.i += xfold(ep->v.p[0]);
|
||||
return;
|
||||
}
|
||||
} else if (ep->nodetype == en_sub) {
|
||||
if (ep->v.p[0]->nodetype == en_icon) {
|
||||
ep->v.p[0]->v.i -= xfold(ep->v.p[1]);
|
||||
return;
|
||||
} else if (ep->v.p[1]->nodetype == en_icon) {
|
||||
ep->v.p[1]->v.i -= xfold(ep->v.p[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
i = xfold(ep);
|
||||
if (i != 0) {
|
||||
/*
|
||||
* strip_icon is in fact harmless here since this value is
|
||||
* just added to *node
|
||||
* consider in 16-bit mode:
|
||||
*
|
||||
* int day, year;
|
||||
* day = 365 * (year - 1970);
|
||||
*
|
||||
* and look at the code, which is transformed to
|
||||
*
|
||||
* day = 365*year + 1846;
|
||||
*
|
||||
* which works if the multiplication returns the lower 16 bits of
|
||||
* the result correctly.
|
||||
*/
|
||||
i = strip_icon(i, (*node)->etype);
|
||||
ep = mk_icon(i);
|
||||
ep->etype = (*node)->etype;
|
||||
ep->esize = (*node)->esize;
|
||||
ep = mk_node(en_add, *node, ep);
|
||||
ep->etype = (*node)->etype;
|
||||
ep->esize = (*node)->esize;
|
||||
*node = ep;
|
||||
}
|
||||
}
|
||||
|
||||
void opt4(struct enode **node) {
|
||||
/*
|
||||
* apply all constant optimizations.
|
||||
*/
|
||||
/* opt0(node); */
|
||||
fold_const(node);
|
||||
opt0(node);
|
||||
}
|
||||
// vim:ts=4:sw=4
|
||||
3017
gtc/src/out68k_as.c
Normal file
3017
gtc/src/out68k_as.c
Normal file
File diff suppressed because it is too large
Load Diff
71
gtc/src/out68k_exe.h
Normal file
71
gtc/src/out68k_exe.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* EXE loader
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#define exeloadersize_bss (-1)
|
||||
readonly unsigned char exeloader_bss[1];
|
||||
#define exeloadersize_nobss sizeof(exeloader_nobss)
|
||||
readonly unsigned char exeloader_nobss[]={
|
||||
0x4f,0xef,0x00,0x30,0x4e,0x75,0x20,0x78,0x00,0xc8,0x0c,0xa0,0x54,0x8f,0x4e,0x75,
|
||||
0x66,0xf8,0x42,0x67,0x2f,0x08,0x48,0xe7,0x1f,0x3e,0x47,0xf9,0x00,0x00,0x00,0x00,
|
||||
0x7a,0xf2,0xda,0x8b,0x24,0x78,0x00,0xc8,0x76,0x00,0x36,0x2b,0x00,0x0c,0x2f,0x13,
|
||||
0x20,0x6a,0x02,0x48,0x4e,0x90,0x58,0x8f,0x3f,0x00,0x67,0xc4,0x20,0x6a,0x02,0x58,
|
||||
0x4e,0x90,0x3e,0x1f,0x28,0x48,0x22,0x4c,0xd3,0xd3,0x93,0xc3,0x2c,0x09,0x41,0xeb,
|
||||
0x00,0x08,0x4e,0xba,0x01,0x2c,0x20,0x46,0x22,0x4c,0x70,0x00,0x30,0x23,0x47,0xf3,
|
||||
0x08,0x0a,0x61,0x00,0x00,0x9e,0x3f,0x47,0x00,0x2c,0x48,0x54,0x3f,0x3c,0x00,0x0a,
|
||||
0x42,0xa7,0x20,0x6a,0x01,0xb0,0x4e,0x90,0x5c,0x8f,0x26,0x08,0x78,0x00,0x08,0x28,
|
||||
0x00,0x02,0x00,0x0a,0x67,0x10,0x3f,0x28,0x00,0x0c,0x20,0x6a,0x02,0x58,0x4e,0x90,
|
||||
0x54,0x8f,0xba,0x88,0x67,0x0a,0x20,0x6a,0x01,0xb4,0x4e,0x90,0x26,0x08,0x66,0xde,
|
||||
0x48,0xe7,0x1f,0x3e,0x48,0x7a,0x00,0x52,0x20,0x78,0x00,0xc8,0x0c,0xa0,0x00,0x00,
|
||||
0x03,0xe8,0x65,0x48,0x26,0x6f,0x00,0x2c,0x20,0x08,0xe1,0x98,0x6b,0x12,0x0c,0x57,
|
||||
0x00,0x04,0x64,0x38,0x26,0x7c,0x00,0x03,0xe0,0x00,0x58,0x57,0x58,0x6f,0x00,0x2c,
|
||||
0xef,0x98,0x72,0x70,0xc2,0x80,0x52,0x81,0x48,0x41,0xe3,0x99,0x24,0x17,0x2f,0x01,
|
||||
0x2f,0x01,0x4f,0xef,0xff,0xf4,0x4e,0x4c,0x46,0xfc,0x27,0x00,0x2f,0x02,0x42,0x67,
|
||||
0x76,0x0f,0x20,0x78,0x00,0xac,0x4e,0xd0,0x4f,0xef,0x00,0x14,0x4c,0xdf,0x7c,0xf9,
|
||||
0x4e,0x75,0x48,0xe7,0x18,0x1c,0x72,0x00,0x70,0x00,0x10,0x1b,0x67,0x00,0x00,0x6c,
|
||||
0x6a,0x06,0xd0,0x00,0xef,0x48,0x10,0x1b,0x55,0x40,0x65,0x2e,0x60,0x02,0x32,0xd8,
|
||||
0x38,0x10,0x76,0xc0,0x86,0x44,0x5c,0x43,0x67,0x0e,0xc8,0x7c,0xf0,0xff,0xb8,0x7c,
|
||||
0x60,0x00,0x57,0xc8,0xff,0xea,0x66,0x10,0x53,0x40,0x65,0x0c,0x32,0xd8,0x36,0x09,
|
||||
0x96,0x4c,0x97,0x50,0x51,0xc8,0xff,0xd8,0x32,0xd8,0x51,0xc9,0x00,0x06,0x58,0x41,
|
||||
0x14,0x1b,0x4a,0x13,0x67,0x24,0xd4,0x02,0x65,0x0e,0x42,0x59,0x32,0xd8,0x20,0x0c,
|
||||
0xd4,0x02,0xd1,0xa9,0xff,0xfc,0x60,0xa0,0xd4,0x02,0x30,0x18,0x6b,0x04,0x32,0xfc,
|
||||
0x4e,0xb9,0xe5,0x48,0x22,0xf2,0x00,0x00,0x60,0x8e,0x4c,0xdf,0x38,0x18,0x4e,0x75,
|
||||
0x48,0xe7,0x1f,0x3e,0x7a,0xff,0x42,0x05,0x47,0xfa,0x01,0x70,0x50,0x88,0x70,0x00,
|
||||
0x10,0x18,0x38,0x00,0x72,0x00,0x12,0x18,0x3c,0x41,0xd0,0x40,0x36,0x33,0x00,0x02,
|
||||
0x70,0x08,0x90,0x44,0x38,0x40,0x24,0x48,0x12,0x18,0xd2,0x41,0x4b,0xf3,0x10,0x02,
|
||||
0x70,0x00,0x10,0x18,0xd0,0xc0,0x7e,0x00,0x9e,0x44,0x6a,0x08,0x50,0x47,0x16,0x86,
|
||||
0x3c,0x13,0x1c,0x18,0x32,0x06,0xee,0x69,0xc2,0x43,0xb2,0x4e,0x67,0x14,0x9e,0x4c,
|
||||
0x6a,0x08,0x50,0x47,0x16,0x86,0x3c,0x13,0x1c,0x18,0x32,0x06,0xee,0x69,0x12,0xc1,
|
||||
0x60,0xd6,0x61,0x4e,0x4a,0x41,0x67,0x00,0x00,0x8e,0x30,0x02,0x61,0x44,0x0c,0x42,
|
||||
0x00,0xff,0x66,0x06,0x4c,0xdf,0x7c,0xf8,0x4e,0x75,0x53,0x42,0x12,0x12,0x67,0x08,
|
||||
0xe3,0x6a,0x61,0x60,0xc2,0x55,0x84,0x41,0x16,0x82,0x32,0x13,0x74,0xff,0xb3,0x42,
|
||||
0x61,0x58,0x14,0x01,0x47,0xf1,0x28,0x00,0x12,0xdb,0x51,0xc8,0xff,0xfc,0x47,0xfa,
|
||||
0x00,0xda,0x60,0x94,0x61,0x44,0x82,0x45,0x12,0xf1,0x10,0x00,0x12,0xf1,0x10,0x00,
|
||||
0x60,0x86,0x72,0xff,0x51,0xcf,0x00,0x0a,0x50,0x47,0x16,0x86,0x3c,0x13,0x1c,0x18,
|
||||
0x52,0x41,0x0f,0x06,0x57,0xcf,0xff,0xfa,0x66,0xee,0x9e,0x41,0x6a,0x08,0x50,0x47,
|
||||
0x16,0x86,0x3c,0x13,0x1c,0x18,0x34,0x06,0xee,0x6a,0x03,0xc2,0xd2,0x41,0xc4,0x73,
|
||||
0x10,0x04,0x4e,0x75,0x9e,0x41,0x6a,0x08,0x50,0x47,0x16,0x86,0x3c,0x13,0x1c,0x18,
|
||||
0x32,0x06,0xee,0x69,0x4e,0x75,0x51,0xcf,0x00,0x0a,0x50,0x47,0x16,0x86,0x3c,0x13,
|
||||
0x1c,0x18,0x0f,0x06,0x67,0x9e,0x51,0xcf,0x00,0x0a,0x50,0x47,0x16,0x86,0x3c,0x13,
|
||||
0x1c,0x18,0x0f,0x06,0x66,0x20,0x32,0x04,0x61,0xca,0xc2,0x43,0x30,0x0e,0x3c,0x41,
|
||||
0x32,0x0c,0xe3,0x68,0x61,0xbe,0x34,0x0c,0xd4,0x42,0xc2,0x73,0x20,0x02,0x80,0x41,
|
||||
0x12,0xc0,0x60,0x00,0xff,0x04,0x61,0x00,0xff,0x7a,0x30,0x02,0x0c,0x40,0x00,0x80,
|
||||
0x6d,0x10,0x72,0x01,0x61,0x9e,0x10,0x01,0x61,0x00,0xff,0x68,0x53,0x02,0xe1,0x4a,
|
||||
0x80,0x42,0x61,0x00,0xff,0x5e,0x04,0x42,0x00,0x20,0x6a,0x06,0x14,0x32,0x20,0x21,
|
||||
0x60,0x0e,0xe7,0x4a,0x72,0x03,0x61,0x00,0xff,0x7c,0x02,0x41,0x00,0x07,0x84,0x41,
|
||||
0x12,0xc2,0x51,0xc8,0xff,0xfc,0x60,0x00,0xfe,0xc0,0x00,0x00,0x00,0x00,0x00,0x01,
|
||||
0x00,0x03,0x00,0x07,0x00,0x0f,0x00,0x1f,0x00,0x3f,0x00,0x7f,0x00,0xff,0x01,0xff,
|
||||
0x03,0xff,0x07,0xff,0x0f,0xff,0x1f,0xff,0x3f,0xff,0x7f,0xff,0x00,0x00,0x00,0x0c,
|
||||
0x00,0x1c,0xf3,
|
||||
};
|
||||
53
gtc/src/pch.h
Normal file
53
gtc/src/pch.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* PCH management definitions
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
typedef struct {
|
||||
TI_LONG magic;
|
||||
TI_SHORT h_off; // offset to .H section
|
||||
TI_SHORT ext_off; // offset to .EXT table (int ext_table[nExt])
|
||||
TI_SHORT dic_off; // offset to dictionnary ((char[]) sPk_table[])
|
||||
TI_SHORT nID;
|
||||
} PCH_HEAD;
|
||||
|
||||
#define PCH_HEAD_SIZE 12
|
||||
|
||||
#define PCHID_MASK 0xFFF
|
||||
#define PCHID_MACRO 0x8000
|
||||
#define PCHID_VAMAC 0x4000
|
||||
#define PCHID_PACKED 0x2000
|
||||
|
||||
#ifndef PC
|
||||
char *__attribute__((stkparm)) sUnpack(char *in,char *out,char *dic);
|
||||
#else
|
||||
char *sUnpack(char *in,char *out,char *dic);
|
||||
#endif
|
||||
|
||||
/* GTC-only */
|
||||
extern FILE *pchfile[];
|
||||
extern char *pchdata[];
|
||||
extern char *pchtab[];
|
||||
extern char pchname[][15];
|
||||
extern char pchrequired[];
|
||||
extern int pchnum;
|
||||
#define pchhead ((PCH_HEAD **)pchdata)
|
||||
|
||||
/* PchMaker-only */
|
||||
extern int def_is_packed;
|
||||
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
1291
gtc/src/peep68k.c
Normal file
1291
gtc/src/peep68k.c
Normal file
File diff suppressed because it is too large
Load Diff
572
gtc/src/preproc.c
Normal file
572
gtc/src/preproc.c
Normal file
@ -0,0 +1,572 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* preprocessor
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#define USE_MEMMGT
|
||||
#include "cglbdec.h"
|
||||
#ifdef PCH
|
||||
#include "pch.h"
|
||||
#endif
|
||||
|
||||
extern char *curname;
|
||||
extern char *lptr;
|
||||
char *inclname[10];
|
||||
FILE *inclfile[10];
|
||||
int inclifreldepth[10];
|
||||
int incldepth CGLOB;
|
||||
#ifdef PCH
|
||||
FILE *pchfile[20];
|
||||
char *pchdata[20] CGLOBL;
|
||||
char *pchtab[20];
|
||||
#ifdef REQ_MGT
|
||||
char pchname[20][15];
|
||||
char pchrequired[20];
|
||||
#endif
|
||||
int pchnum CGLOB;
|
||||
#endif
|
||||
int inclline[10];
|
||||
int lineno CGLOB;
|
||||
int lineid CGLOB;
|
||||
int prevlineid CGLOB;
|
||||
int flags CGLOB;
|
||||
#ifdef PC
|
||||
int verbose CGLOB;
|
||||
#endif
|
||||
#ifdef PC
|
||||
int verbosity CGLOB;
|
||||
#endif
|
||||
int ifdepth CGLOB;
|
||||
int ifreldepth CGLOB;
|
||||
int ifcount[MAX_IF_DEPTH];
|
||||
int ifval[MAX_IF_DEPTH];
|
||||
int ifhas[MAX_IF_DEPTH];
|
||||
int ifskip CGLOB, ifsd CGLOB;
|
||||
|
||||
HTABLE defsyms CGLOBL;
|
||||
|
||||
extern int getline(int f);
|
||||
|
||||
extern TYP *expression();
|
||||
extern unsigned char id_are_zero;
|
||||
|
||||
int doinclude(
|
||||
#ifdef PCH
|
||||
int pch
|
||||
#endif
|
||||
);
|
||||
|
||||
extern enum(e_sym) forbid;
|
||||
xstatic int pp_old_forbid CGLOB;
|
||||
xstatic int pp_old_crc CGLOB;
|
||||
xstatic char pp_old_id[MAX_ID_LEN+1];
|
||||
|
||||
/*static int mem_if=0,mem_def=0;
|
||||
#define MEM_USE(x,s) mem_##x-=glbmem; s mem_##x+=glbmem;*/
|
||||
|
||||
int ppquit() {
|
||||
if (pp_old_forbid IS_VALID) {
|
||||
forbid=pp_old_forbid;
|
||||
if (pp_old_forbid==id) memcpy(lastid,pp_old_id,MAX_ID_LEN+1), lastcrc=pp_old_crc;
|
||||
}
|
||||
#ifdef MACRO_PPDIR
|
||||
if (*lptr) lptr=strchr(lptr,'\n')+1;
|
||||
if (!*lptr) return getline(incldepth == 0);
|
||||
else return 0;
|
||||
#else
|
||||
return getline(incldepth == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
char *strend(char *s) {
|
||||
while (*s++);
|
||||
return s-1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int preprocess() {
|
||||
if ((pp_old_forbid=forbid)==id) memcpy(pp_old_id,lastid,MAX_ID_LEN+1), pp_old_crc=lastcrc,
|
||||
forbid=-1;
|
||||
++lptr; // skip '#'
|
||||
lastch = ' ';
|
||||
getch();
|
||||
getsym(); /* get first word on line */
|
||||
if(lastst != id && lastst != kw_if && lastst != kw_else) {
|
||||
uerrc("preprocessor command expected");
|
||||
return ppquit();
|
||||
}
|
||||
/* if (!strcmp(curname,"compat.h") && lineno>=23)
|
||||
bkpt();*/
|
||||
/* if (!strcmp(curname,"messages.c") && lineno>=0)
|
||||
bkpt();*/
|
||||
if (lastst == kw_if /*!strcmp(lastid,"if")*/ || !strcmp(lastid,"elif")) {
|
||||
struct enode *ep; TYP *tp; enum(e_bt) typ;
|
||||
int v=lastst==kw_if;
|
||||
if (!v) ifskip=ifhas[ifdepth];
|
||||
if (ifskip) return doif(-1,v);
|
||||
#ifndef MACRO_PPDIR
|
||||
strcpy(lptr," ] "); // so that getsym() in the new expression will
|
||||
getsym(); // not read any new line
|
||||
#else
|
||||
{
|
||||
char *q=strchr(lptr,'\n');
|
||||
memmove(q+3,q,strlen(q)+1);
|
||||
memcpy(q," ] ",3);
|
||||
getsym();
|
||||
}
|
||||
#endif
|
||||
tmp_use();
|
||||
id_are_zero++;
|
||||
tp=expression(&ep);
|
||||
id_are_zero--;
|
||||
if (!tp || lastst!=closebr) error(ERR_EXPREXPECT);
|
||||
else if ((typ=tp->type)==bt_void || typ==bt_pointer) error(ERR_INTEGER);
|
||||
else {
|
||||
opt0(&ep);
|
||||
if (ep->nodetype!=en_icon) error(ERR_CONSTEXPECT);
|
||||
else { int w=doif(ep->v.i!=0,v); tmp_free(); return w; }
|
||||
}
|
||||
tmp_free();
|
||||
return ppquit();
|
||||
} else if (!strcmp(lastid,"ifdef") || !strcmp(lastid,"ifndef")) {
|
||||
int v=lastid[2]!='d';
|
||||
if (ifskip) return doif(-1,1);
|
||||
skipspace();
|
||||
if ((lastch>='A'&&lastch<='Z') || (lastch>='a'&&lastch<='z')
|
||||
|| lastch=='_' || lastch=='$') {
|
||||
getidstr();
|
||||
return doif(v ^ !!search(lastid,lastcrc,&defsyms),1);
|
||||
} else error(ERR_IDEXPECT);
|
||||
return ppquit();
|
||||
} else if (lastst == kw_else/*!strcmp(lastid,"else")*/) {
|
||||
if (!ifreldepth) uerrc("'#else' unexpected");
|
||||
else if (!ifskip || ifdepth<=ifsd) {
|
||||
if (--ifcount[ifdepth]!=0) uerrc("'#else' unexpected");
|
||||
else ifskip = ifval[ifdepth];
|
||||
}
|
||||
return ppquit();
|
||||
} else if (!strcmp(lastid,"endif")) {
|
||||
if (!ifreldepth) uerrc("'#endif' unexpected");
|
||||
else {
|
||||
ifdepth--, ifreldepth--;
|
||||
if (ifdepth<ifsd) ifskip=0;
|
||||
if (!ifskip) ifskip = ifcount[ifdepth] - ifval[ifdepth];
|
||||
}
|
||||
return ppquit();
|
||||
} else if (ifskip)
|
||||
return ppquit(); // ignore all other preproc directives
|
||||
else if (!strcmp(lastid,"include"))
|
||||
#ifdef PCH
|
||||
return doinclude(0);
|
||||
#else
|
||||
return doinclude();
|
||||
#endif
|
||||
#ifdef PCH
|
||||
else if (!strcmp(lastid,"header") || !strcmp(lastid,"headeropt"))
|
||||
return doinclude(lastid[sizeof("header")-1]?-1:1);
|
||||
#endif
|
||||
else if (!strcmp(lastid,"define"))
|
||||
return dodefine(1);
|
||||
#ifdef MACRO_PPDIR
|
||||
else if (!strcmp(lastid,"macro"))
|
||||
return dodefine(-1);
|
||||
#endif
|
||||
else if (!strcmp(lastid,"undef"))
|
||||
return dodefine(0);
|
||||
else if (!strcmp(lastid,"pragma")) {
|
||||
getsym();
|
||||
if (lastst==id && !strcmp(lastid,"lang")) {
|
||||
int not_flag=0;
|
||||
getsym();
|
||||
needpunc(openpa);
|
||||
while (lastst==id || lastst==not) {
|
||||
if (lastst==not) not_flag^=1;
|
||||
else {
|
||||
if (!strcmp(lastid,"ansi")) {
|
||||
if (not_flag) uwarn("'!' ignored"); flags=flags_ansi;
|
||||
} else if (!strcmp(lastid,"gtc")) {
|
||||
if (not_flag) uwarn("'!' ignored"); flags=flags_fullgtc;
|
||||
} else {
|
||||
int opt;
|
||||
if (!strcmp(lastid,"mid_decl")) opt=X_MID_DECL;
|
||||
else if (!strcmp(lastid,"comp_string")) opt=X_COMP_STRING;
|
||||
else if (!strcmp(lastid,"lang_ext")) opt=X_LANG_EXT;
|
||||
else { uwarn("invalid '#pragma'"); break; }
|
||||
if (not_flag) flags &= ~opt;
|
||||
else flags |= opt;
|
||||
}
|
||||
not_flag = 0;
|
||||
}
|
||||
getsym();
|
||||
}
|
||||
if (lastst!=closepa) uerr(ERR_PUNCT,')');
|
||||
/* } else if (!strcmp(lastid,"poison")) {
|
||||
while (1) {
|
||||
getsym();
|
||||
if (*/
|
||||
} else if (lastst==id && !strcmp(lastid,"opt")) {
|
||||
getsym();
|
||||
needpunc(openpa);
|
||||
while (lastst==id) {
|
||||
#ifdef SPEED_OPT
|
||||
if (!strcmp(lastid,"speed"))
|
||||
speed_opt_value = 1;
|
||||
else if (!strcmp(lastid,"normal"))
|
||||
speed_opt_value = 0;
|
||||
else if (!strcmp(lastid,"size"))
|
||||
speed_opt_value = -1;
|
||||
else if (!strcmp(lastid,"uberspeed"))
|
||||
speed_opt_value = 3;
|
||||
else
|
||||
uwarn("invalid '#pragma'");
|
||||
#endif
|
||||
getsym();
|
||||
}
|
||||
if (lastst!=closepa) uerr(ERR_PUNCT,')');
|
||||
} else uwarn("unknown '#pragma' type");
|
||||
return ppquit();
|
||||
} else if (!strcmp(lastid,"warning")) {
|
||||
uwarn("#warning: %.*s",strlen(lptr)-1,lptr); return ppquit();
|
||||
} else if (!strcmp(lastid,"error")) {
|
||||
uerr(ERR_CUSTOM,lptr); return ppquit();
|
||||
} else {
|
||||
uerrc("preprocessor command expected");
|
||||
return ppquit();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PC
|
||||
extern char *incfolders[10];
|
||||
extern int incfoldernum;
|
||||
#endif
|
||||
|
||||
#ifdef PC
|
||||
#ifdef _WIN32
|
||||
#define DIR_SEPARATOR_STRING "\\"
|
||||
#else
|
||||
#ifdef UNIXOID
|
||||
#define DIR_SEPARATOR_STRING "/"
|
||||
#else
|
||||
#error Please define a directory separator for your platform.
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PC
|
||||
void verbose_print_searchdirs() {
|
||||
int n=incfoldernum;
|
||||
while (n--)
|
||||
fprintf(stderr,"search directory: '%s'\n",incfolders[n]);
|
||||
}
|
||||
void verbose_print_include(char *filename) {
|
||||
int i;
|
||||
for (i=0; i<incldepth; i++)
|
||||
fprintf(stderr," ");
|
||||
fprintf(stderr,"include file '%s'\n",filename);
|
||||
}
|
||||
#endif
|
||||
FILE *xfopen(char *f,char *m,int sys) {
|
||||
FILE *fp;
|
||||
#ifdef PC
|
||||
char b[300];
|
||||
int n=incfoldernum;
|
||||
#define xfopen_try(z) do { if ((fp=fopen(z,m))) { if (verbosity&VERBOSITY_PRINT_INCLUDES) verbose_print_include(z); return fp; } } while (0)
|
||||
#else
|
||||
char b[50];
|
||||
#define xfopen_try(z) do { if ((fp=fopen(z,m))) return fp; } while (0)
|
||||
#endif
|
||||
if (!sys) xfopen_try(f);
|
||||
#ifdef PC
|
||||
while (n--) {
|
||||
sprintf(b,"%s"DIR_SEPARATOR_STRING"%s",incfolders[n],f);
|
||||
xfopen_try(b);
|
||||
}
|
||||
#else
|
||||
sprintf(b,"gtchdr\\%s",f);
|
||||
xfopen_try(b);
|
||||
sprintf(b,"gtc\\%s",f);
|
||||
xfopen_try(b);
|
||||
#endif
|
||||
xfopen_try(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef GTDEV
|
||||
void progr_initforcurfile() {
|
||||
#if 0
|
||||
long pos=ftell(input);
|
||||
fseek(input,0,SEEK_END);
|
||||
progr_coeff=(100l<<16)/(int)ftell(input);
|
||||
fseek(input,pos,SEEK_SET);
|
||||
#else
|
||||
progr_coeff=(100l<<16)/peek_w(input->base);
|
||||
#endif
|
||||
progr_readtonow=0;
|
||||
}
|
||||
#endif
|
||||
int doinclude(
|
||||
#ifdef PCH
|
||||
int pch
|
||||
#endif
|
||||
) {
|
||||
int rv; char c;
|
||||
strcat(lptr," ");
|
||||
skipspace();
|
||||
if ((c=lastch-'"') && c!='<'-'"')
|
||||
goto incl_err;
|
||||
getch();
|
||||
if (!((lastch>='A'&&lastch<='Z') || (lastch>='a'&&lastch<='z')
|
||||
|| lastch=='_' || lastch=='$' || lastch=='\\'))
|
||||
goto incl_err;
|
||||
getidstr(); /* get file to include, without extension */
|
||||
#ifdef PCH
|
||||
if (!pch) {
|
||||
#endif
|
||||
inclline[incldepth] = lineno;
|
||||
inclifreldepth[incldepth] = ifreldepth;
|
||||
#ifdef GTDEV
|
||||
inclread[incldepth] = progr_readtonow;
|
||||
inclcoeff[incldepth] = progr_coeff;
|
||||
#endif
|
||||
inclname[incldepth] = curname;
|
||||
inclfile[incldepth++] = input; /* push current input file */
|
||||
restart_h:
|
||||
input = xfopen(lastid,"r",c);
|
||||
if (!input) {
|
||||
char *tigcclib_aliases = "all\0alloc\0args\0asmtypes\0assert\0bascmd\0basfunc\0basop\0cert\0compat\0ctype\0default\0dialogs\0dll\0error\0estack\0events\0files\0flash\0float\0gdraw\0graph\0graphing\0gray\0homescr\0intr\0kbd\0limits\0link\0math\0mem\0menus\0nostub\0peekpoke\0printf\0romsymb\0rsa\0setjmp\0sprites\0statline\0stdarg\0stddef\0stdio\0stdlib\0string\0system\0textedit\0timath\0unknown\0values\0vat\0version\0wingraph\0";
|
||||
while (*tigcclib_aliases)
|
||||
if (
|
||||
#ifdef PC
|
||||
!strncmp(lastid,tigcclib_aliases,strlen(tigcclib_aliases)) && !strcmp(lastid+strlen(tigcclib_aliases),".h")
|
||||
#else
|
||||
!strcmp(lastid,tigcclib_aliases)
|
||||
#endif
|
||||
) {
|
||||
#ifdef PC
|
||||
strcpy(lastid,"tigcclib.h");
|
||||
#else
|
||||
strcpy(lastid,"tigcclib");
|
||||
#endif
|
||||
goto restart_h;
|
||||
} else {
|
||||
while (*tigcclib_aliases++);
|
||||
}
|
||||
// input = inclfile[--incldepth];
|
||||
uerr(ERR_CANTOPEN,lastid);
|
||||
// _exit(18);
|
||||
}
|
||||
ifreldepth = 0;
|
||||
#ifdef GTDEV
|
||||
progr_initforcurfile();
|
||||
#endif
|
||||
global_flag++;
|
||||
curname = strsave(lastid);
|
||||
global_flag--;
|
||||
#ifdef PCH
|
||||
} else {
|
||||
char b[30];
|
||||
#ifdef REQ_MGT
|
||||
int i=pchnum;
|
||||
while (i--)
|
||||
if (!strcmp(lastid,pchname[i]))
|
||||
goto done;
|
||||
#endif
|
||||
#ifdef PC
|
||||
sprintf(b,"%s.pch",lastid);
|
||||
#else
|
||||
sprintf(b,"zheader\\%s",lastid);
|
||||
#endif
|
||||
if (!(pchfile[pchnum] = xfopen(b, "rb", c))) {
|
||||
if (pch<0)
|
||||
goto done;
|
||||
uerr(ERR_CANTOPEN,b);
|
||||
// _exit(18);
|
||||
}
|
||||
#ifdef REQ_MGT
|
||||
strcpy(pchname[pchnum],lastid);
|
||||
pchrequired[pchnum]=0;
|
||||
#endif
|
||||
#ifdef PC
|
||||
pchdata[pchnum] = malloc(150000);
|
||||
fread(pchdata[pchnum],1,150000,pchfile[pchnum]);
|
||||
if (w2ul(pchhead[pchnum]->magic)!=
|
||||
((long)'P'<<24)+((long)'C'<<16)+((long)'H'<<8)
|
||||
|| !(pchtab[pchnum] = malloc(w2us(pchhead[pchnum]->nID)))) {
|
||||
fclose(pchfile[pchnum]);
|
||||
goto incl_err;
|
||||
}
|
||||
#define w2s(x) ((short)w2us(x))
|
||||
#else
|
||||
if (w2ul(((PCH_HEAD *)(pchdata[pchnum] = *(char **)(pchfile[pchnum])))->magic)!=
|
||||
((long)'P'<<24)+((long)'C'<<16)+((long)'H'<<8)
|
||||
|| !(pchtab[pchnum] = malloc((short)pchhead[pchnum]->nID))) {
|
||||
fclose(pchfile[pchnum]);
|
||||
goto incl_err;
|
||||
}
|
||||
#define w2s(x) ((short)(x))
|
||||
#endif
|
||||
memset(pchtab[pchnum],0,w2s(pchhead[pchnum]->nID));
|
||||
pchnum++;
|
||||
}
|
||||
#endif
|
||||
done:
|
||||
if (lastch=='.') getch(),getidstr();
|
||||
c=c?'>':'"';
|
||||
if (lastch!=c)
|
||||
uerr(ERR_PUNCT,c);
|
||||
rv = getline(incldepth == 1);
|
||||
#ifdef PCH
|
||||
if (!pch)
|
||||
#endif
|
||||
lineno = 1; /* dont list include files */
|
||||
return rv;
|
||||
incl_err:
|
||||
error(ERR_INCLFILE);
|
||||
return ppquit();
|
||||
}
|
||||
|
||||
char *litlate(char *s);
|
||||
extern int getch_noppdir;
|
||||
int dodefine(int mode) { // 1: #define, -1 : #macro, 0 : #undef
|
||||
SYM *sp,*ds;
|
||||
int n=0,flags=0;
|
||||
/* getsym();*/
|
||||
skipspace();
|
||||
if ((lastch>='A'&&lastch<='Z') || (lastch>='a'&&lastch<='z')
|
||||
|| lastch=='_' || lastch=='$') {
|
||||
getidstr(); /* get past #define */
|
||||
} else {
|
||||
error(ERR_DEFINE);
|
||||
return ppquit();
|
||||
}
|
||||
if (!mode) {
|
||||
if (!symremove(lastid,&defsyms)) /* if we didn't unload anything, let's */
|
||||
pchsearch(lastid,PCHS_UNLOAD); /* try and unload the symbol */
|
||||
return ppquit();
|
||||
}
|
||||
#ifdef AS
|
||||
if (!strcmp(lastid,"NOSTUB"))
|
||||
nostub_mode=1;
|
||||
#endif
|
||||
#ifdef ASM
|
||||
if (asm_isreserved())
|
||||
flags|=PPSYM_ASM_KEYWORD;
|
||||
if (asm_flag)
|
||||
flags|=PPSYM_DEFINED_IN_ASM;
|
||||
#endif
|
||||
++global_flag; /* always do #define as globals */
|
||||
sp = (SYM *)xalloc((int)sizeof(SYM), _SYM+DODEFINE);
|
||||
sp->name = strsave(lastid);
|
||||
sp->storage_class = sc_define;
|
||||
if (lastch=='(') {
|
||||
TABLE *tp;
|
||||
/* if (lineid==0x1A)
|
||||
bkpt();*/
|
||||
sp->tp=(TYP *)(tp=(TABLE *)xalloc((int)sizeof(TABLE), _TABLE+DODEFINE));
|
||||
#ifdef NO_CALLOC
|
||||
tp->hash=0;
|
||||
tp->head=tp->tail=NULL;
|
||||
#endif
|
||||
getsym();
|
||||
getsym();
|
||||
if (lastst!=closepa) {
|
||||
while (1) {
|
||||
SYM *arg;
|
||||
n++;
|
||||
if (lastst!=id) error(ERR_IDEXPECT);
|
||||
else {
|
||||
arg=(SYM *)xalloc((int)sizeof(SYM), _SYM+DODEFINE);
|
||||
arg->name=strsave(lastid);
|
||||
#ifdef NO_CALLOC
|
||||
arg->tp=NULL;
|
||||
#endif
|
||||
insert(arg,(HTABLE *)tp);
|
||||
}
|
||||
getsym();
|
||||
if (lastst!=comma) break;
|
||||
getsym();
|
||||
}
|
||||
if (lastst==dots) { sp->storage_class = sc_vamac; getsym(); }
|
||||
if (lastst!=closepa) needpunc(closepa);
|
||||
}
|
||||
if (!isspace(lastch)) // undo last getch()...
|
||||
lptr--;
|
||||
#ifdef NO_CALLOC
|
||||
} else {
|
||||
sp->tp=NULL;
|
||||
#endif
|
||||
}
|
||||
#ifdef MACRO_PPDIR
|
||||
if (mode<0) {
|
||||
char *s=(char *)alloca(500),*p=s;
|
||||
int n=499;
|
||||
getch_noppdir++;
|
||||
do {
|
||||
if (getch()<0) error(ERR_DEFINE);
|
||||
*p++=(/*lastch=='\n'?'\r':*/lastch);
|
||||
} while (n-- && (lastch!='#' || *lptr!='e' || strncmp(lptr+1,"ndm",3)));
|
||||
getch_noppdir--;
|
||||
if (n<=0) error(ERR_DEFINE);
|
||||
p-=2; // remove '\n' '#'
|
||||
*p++=0;
|
||||
n = p-s;
|
||||
p = (char *)xalloc(n, STR);
|
||||
memcpy(p,s,n);
|
||||
sp->value.s=p;
|
||||
} else
|
||||
#endif
|
||||
if (strlen(lptr)>1500)
|
||||
uerrsys("definition too long (1500 characters max)");
|
||||
if (!(sp->value.s = litlate(lptr)))
|
||||
uerrc("unbalanced quotes in #define");
|
||||
#ifdef FLINE_RC
|
||||
if (!strcmp(sp->name,"USE_FLINE_ROM_CALLS"))
|
||||
fline_rc=1;
|
||||
#endif
|
||||
if ((ds=search(sp->name,-1,&defsyms))) {
|
||||
if (strcmp(sp->value.s,ds->value.s))
|
||||
uwarn("redefinition of macro '%s'",sp->name);
|
||||
symremove(sp->name,&defsyms);
|
||||
}
|
||||
insert(sp,&defsyms);
|
||||
sp->used=n+flags;
|
||||
--global_flag;
|
||||
return ppquit();
|
||||
}
|
||||
|
||||
// x = result of the test (1 : true, 0 : false, -1 : ignore all branches)
|
||||
// c = is it a #if ? (rather than a #elif)
|
||||
int doif(int x,int c) {
|
||||
if ((ifreldepth+=c,ifdepth+=c)>MAX_IF_DEPTH) uerrc("too many imbricated '#if's");
|
||||
else if (!ifreldepth) uerrc("'#elif' unexpected");
|
||||
else if (!ifskip || ifdepth<=ifsd) {
|
||||
ifsd=ifdepth;
|
||||
if (c)
|
||||
ifhas[ifdepth] = x;
|
||||
else
|
||||
ifhas[ifdepth] |= x;
|
||||
ifskip = (ifval[ifdepth] = x) - (ifcount[ifdepth] = 1);
|
||||
}
|
||||
if (x<0) {
|
||||
ifhas[ifdepth] = x;
|
||||
ifskip = x;
|
||||
}
|
||||
return ppquit();
|
||||
}
|
||||
// vim:ts=4:sw=4
|
||||
329
gtc/src/protos.h
Normal file
329
gtc/src/protos.h
Normal file
@ -0,0 +1,329 @@
|
||||
// Auto-generated file, do not edit!
|
||||
|
||||
#ifndef PROTOS_H_
|
||||
#define PROTOS_H_
|
||||
|
||||
enum OptionModes;
|
||||
enum e_am;
|
||||
enum e_bt;
|
||||
enum e_node;
|
||||
enum e_op;
|
||||
enum e_sc;
|
||||
enum e_sym;
|
||||
struct _regsimg;
|
||||
struct _stackimg;
|
||||
struct amode;
|
||||
struct bcd;
|
||||
struct blk;
|
||||
struct cse;
|
||||
struct enode;
|
||||
struct hstab;
|
||||
struct ocode;
|
||||
struct snode;
|
||||
struct stab;
|
||||
struct sym;
|
||||
struct typ;
|
||||
|
||||
struct typ *shiftop(struct enode **node);
|
||||
void local_clean(void); /* remove local symbols from alsyms -- to be called just before rel_local */
|
||||
void g_label(unsigned int labno);
|
||||
struct snode *casestmt(void);
|
||||
void compile(void);
|
||||
void dump_endnode();
|
||||
int blk_free(struct blk *bp1);
|
||||
int complexity(struct enode *ep);
|
||||
void check_table(struct hstab *table);
|
||||
struct typ *nameref(struct enode **node);
|
||||
int en_dir_cost(struct enode *ep);
|
||||
void extscan(unsigned char *ext);
|
||||
void genstorage(struct sym *sp, int align);
|
||||
void freeregs(struct _regsimg *img); /* used by g_fcall */
|
||||
struct amode *mk_immed(long i);
|
||||
char *litlate(char *s);
|
||||
struct snode *forstmt(void);
|
||||
struct amode *g_xmul(struct enode *node, int flags, enum(e_op) op);
|
||||
struct enode *mk_icon(long i);
|
||||
void getsym();
|
||||
struct typ *equalops(struct enode **node);
|
||||
void genfunc(struct snode *stmt);
|
||||
struct typ *copy_type(struct typ *s);
|
||||
void repcse(struct snode *block);
|
||||
int internal(char *s);
|
||||
void genbyte(int val);
|
||||
struct typ *bitor(struct enode **node);
|
||||
void fill(int n);
|
||||
void scan(struct snode *block);
|
||||
struct snode *retstmt(void);
|
||||
void out_init();
|
||||
void _scr_main();
|
||||
void add_code(enum(e_op) op, int len, struct amode *ap1, struct amode *ap2, int line);
|
||||
char *create_ti_file(int calc,int tigl_type,char *name,char *folder,char *content,unsigned long content_size,unsigned long *ti_file_size);
|
||||
long intexpr();
|
||||
int bitwise_reduction(unsigned long x,int *size);
|
||||
void double2bcd(double d,struct bcd *bcd);
|
||||
struct amode *g_aslogic(struct enode *node, int flags, enum(e_op) op);
|
||||
long auto_init(long offs,struct typ *typ,struct typ **tpp,int brace_level,int offmod,int stroff);
|
||||
void initstack();
|
||||
void falsejp(struct enode *node, unsigned int lab);
|
||||
int getch();
|
||||
int doif(int x,int c);
|
||||
void temp_inv(void);
|
||||
long inittype(struct typ *tp,struct typ **tpp);
|
||||
void do_warning(char *s, ...);
|
||||
struct typ *forcefit(struct enode **node1, struct typ *tp1, struct enode **node2, struct typ *tp2);
|
||||
void collect(int g);
|
||||
int movem(short x);
|
||||
void g_code(enum(e_op) op, int len, struct amode *ap1, struct amode *ap2);
|
||||
struct enode *parmlist(struct sym *f);
|
||||
int isbyte(struct enode *node);
|
||||
void clean_up();
|
||||
void getrawid();
|
||||
struct typ *deref(struct enode **node, struct typ *tp);
|
||||
long strip_icon(long i, enum(e_bt) type);
|
||||
void genword(int val);
|
||||
int getid(int c);
|
||||
void d_snode(struct snode **node);
|
||||
struct snode *exprstmt(void);
|
||||
struct typ *relation(struct enode **node);
|
||||
int integral(struct typ *tp);
|
||||
void g_bitmancode(enum(e_op) op,int size,struct amode *ap1,struct amode *ap2);
|
||||
struct amode *g_offset(struct amode *ap, int off);
|
||||
struct amode *as_fcall(struct enode *node, int flags, char *libname);
|
||||
struct snode *contstmt(void);
|
||||
int vcg_init();
|
||||
long push_param(struct enode *ep);
|
||||
int label(char *s);
|
||||
struct amode *get_asmparam();
|
||||
struct amode *g_fderef(struct enode *node, struct amode *ap0, int flags);
|
||||
int req_all_aregs(struct enode *plist,int rp_dn,int rp_an);
|
||||
void genstmt(struct snode *stmt);
|
||||
int vcg_cost();
|
||||
void useregs(struct _regsimg *img); /* used by g_fcall */
|
||||
char *strend(char *s);
|
||||
TI_SHORT process_attr();
|
||||
void dump_genfunc(struct snode *stmt);
|
||||
void getidstr();
|
||||
int stringlit(char *s, int len);
|
||||
void ds_free(void);
|
||||
void scope_init(void);
|
||||
void verbose_print_include(char *filename);
|
||||
void tmp_use();
|
||||
struct sym *symremove(char *na, struct hstab *tab);
|
||||
struct sym *search(char *na, int crc, struct hstab *tab);
|
||||
void add_label(int lab);
|
||||
void dump_startline();
|
||||
struct typ *cond_deref(struct enode **node, struct typ *tp);
|
||||
struct amode *temp_addr(void);
|
||||
struct amode *g_cast2(struct enode *ep, enum(e_bt) typ2, int flags);
|
||||
void get_offset(struct amode *ap);
|
||||
void scanexpr(struct enode *node, int duse);
|
||||
void progr_initforcurfile();
|
||||
void move_pos(long diff); /* caution : only works in overwrite mode */
|
||||
void dump_newnode(char *name);
|
||||
void fatal(char *message);
|
||||
int arsearch(int r,struct ocode *ip);
|
||||
void usestack(struct _stackimg *img); /* used by g_expr::en_compound */
|
||||
struct typ *bitand(struct enode **node);
|
||||
FILE *xfopen(char *f,char *m,int sys);
|
||||
int tst_const(struct enode *node);
|
||||
long mod_mask(long i);
|
||||
struct amode *mk_strlab(char *s);
|
||||
void concat(struct stab *dest,struct stab *src);
|
||||
struct amode *temp_data(void);
|
||||
void rel_dualstack(void);
|
||||
int pwrof2(long i);
|
||||
void hashinit(struct hstab *t);
|
||||
int eq_type(struct typ *tp1, struct typ *tp2);
|
||||
void dodecl(enum(e_sc) defclass);
|
||||
struct snode *gotostmt(void);
|
||||
void g_coder(enum(e_op) op, int len, struct amode *ap1, struct amode *ap2);
|
||||
struct typ *expression(struct enode **node);
|
||||
struct snode *breakstmt(void);
|
||||
int has_autocon(struct enode *ep);
|
||||
struct snode *dostmt(void);
|
||||
char *strsave(char *s);
|
||||
void opt_compare(struct enode *node);
|
||||
struct amode *g_asmod(struct enode *node, int flags);
|
||||
int hexatoi(char *s);
|
||||
struct ocode *new_code(int s);
|
||||
void d_amode(struct amode **node);
|
||||
int getline(int listflag);
|
||||
void call_library(char *lib_name);
|
||||
unsigned long _w2ul(TI_LONG *x);
|
||||
int asm_isreserved();
|
||||
void dooper(struct enode **node);
|
||||
short count_dn_an(struct enode *plist,int rp_dn,int rp_an);
|
||||
struct amode *g_compound(struct snode *st, int flags);
|
||||
void repexpr(struct enode *node);
|
||||
void initpch();
|
||||
void genfloat(double val);
|
||||
void asm_searchkw();
|
||||
struct amode *g_deref(struct enode *node, enum(e_bt) type, int flags, long size);
|
||||
int free_data(void);
|
||||
int indir_num(struct typ *tp);
|
||||
int _getline(int listflag,char *base);
|
||||
struct typ *asnop(struct enode **node);
|
||||
struct amode *g_fcall(struct enode *node, int flags);
|
||||
void warn_usr(char *s,...);
|
||||
int tst_ushort(struct enode *node);
|
||||
void scope_flush(void);
|
||||
void rewrite(long size);
|
||||
struct amode *g_aincdec(struct enode *node, int flags, enum(e_op) op);
|
||||
void funcbottom(void);
|
||||
struct typ *bitxor(struct enode **node);
|
||||
struct amode *g_addsub(struct enode *node, int flags, enum(e_op) op);
|
||||
struct snode *statement(void);
|
||||
void searchkw(void);
|
||||
void opt0(struct enode **node);
|
||||
void decl(struct hstab *table); /* table is used only for enum members */
|
||||
struct amode *g_index(struct enode *node);
|
||||
void g_strlab(char *s);
|
||||
struct enode *copynode(struct enode *node);
|
||||
void expand_do(char *q,int len,char *in,char *inbound,int need_ds_update);
|
||||
unsigned int getconst(enum(e_sym) s,enum(e_sym) e);
|
||||
void opt1(struct snode *block);
|
||||
long intexpr_notemp();
|
||||
int getasm_main();
|
||||
unsigned short _w2us(TI_SHORT *x);
|
||||
struct amode *g_div(struct enode *node, int flags);
|
||||
struct amode *mk_offset(struct enode *node);
|
||||
unsigned long desire(struct cse *csp);
|
||||
int equalnode(struct enode *node1, struct enode *node2);
|
||||
void funcbody(struct sym *sp, char *names[], int nparms);
|
||||
struct amode *g_commute(void *func,struct enode *node,int flags,enum(e_op) op,int dummy/*void *reversal*/);
|
||||
void add_peep(struct ocode *new_ocode);
|
||||
struct snode *ifstmt(void);
|
||||
void locate(void);
|
||||
void allocate(void);
|
||||
size_t option_parse(size_t listc,char **listv,enum(OptionModes) ex_mode);
|
||||
void opt3(void);
|
||||
long auto_pad(long offs,int len,int offmod);
|
||||
struct amode *g_asxor(struct enode *node, int flags);
|
||||
void truejp(struct enode *node, unsigned int lab);
|
||||
void opt4(struct enode **node);
|
||||
void macro_expansion(char *in,char *inbound,int need_ds_update);
|
||||
void insert(struct sym *sp,struct hstab *table);
|
||||
void dumplits();
|
||||
struct amode *g_asdiv(struct enode *node, int flags);
|
||||
struct amode *g_mod(struct enode *node, int flags);
|
||||
struct amode *copy_addr(struct amode *ap);
|
||||
int equal_address(struct amode *ap1, struct amode *ap2);
|
||||
void gendouble(double val);
|
||||
struct typ *commaop(struct enode **node);
|
||||
void swap_nodes(struct enode *node);
|
||||
int preprocess();
|
||||
void dump_addstr(char *name,char *v);
|
||||
struct amode *g_alloca(struct enode *node);
|
||||
struct snode *whilestmt(void);
|
||||
struct amode *mk_rmask(unsigned int mask);
|
||||
struct amode *mk_reg(int r);
|
||||
void do_compile();
|
||||
void bitwise_optimize(struct enode *ep,long mode);
|
||||
void out_close();
|
||||
unsigned int getconst2(enum(e_sym) e);
|
||||
struct amode *func_result(int flags, long bytes);
|
||||
struct amode *g_cast(struct amode *ap, enum(e_bt) typ1, enum(e_bt) typ2, int flags);
|
||||
struct amode *g_asmul(struct enode *node, int flags);
|
||||
int start_block(int m); // used in block() (func.c)
|
||||
void error(int n);
|
||||
void ds_allocatleast(unsigned int size);
|
||||
struct typ *forceft2(struct enode **node1, struct typ *tp1, struct enode **node2, struct typ *tp2);
|
||||
char *type_str(struct typ *tp);
|
||||
struct amode *mk_label(unsigned int lab);
|
||||
struct snode *loopstmt(void);
|
||||
void asm_getsym();
|
||||
void d_ocodes(void);
|
||||
void extload(unsigned char *ext);
|
||||
void initsym();
|
||||
struct amode *g_shift(struct enode *node, int flags, enum(e_op) op);
|
||||
void block(struct sym *sp); /* CAUTION : always requires a compound_done() after call */
|
||||
struct amode *g_ybin(struct enode *node, int flags, enum(e_op) op);
|
||||
struct sym *gsearch(char *na,int crc);
|
||||
int cast_ok(struct typ *tp1, struct typ *tp2, int need_physically_compatible);
|
||||
void needpunc(enum(e_sym) p);
|
||||
struct amode *mk_scratch(long size);
|
||||
void dump_genstmt(struct snode *stmt);
|
||||
void d_enode(struct enode **node);
|
||||
int ap_hasbeenpushed(struct amode *ap);
|
||||
struct amode *g_unary(struct enode *node, int flags, enum(e_op) op);
|
||||
void append(struct sym **ptr_sp, struct hstab *table);
|
||||
void checkstack(void);
|
||||
void rel_global();
|
||||
void option_parse_all(enum(OptionModes) ex_mode);
|
||||
int pchload(char *name,char *data,unsigned int flags,unsigned char *tabp, unsigned char *p0,TI_SHORT *extTab);
|
||||
void my_fclose(FILE *f);
|
||||
struct typ *andop(struct enode **node);
|
||||
struct amode *g_expr(struct enode *node, int flags);
|
||||
struct amode *g_assign(struct enode *node, int flags);
|
||||
void rel_local();
|
||||
struct sym *mk_int(char *name);
|
||||
struct snode *asmstmt(void);
|
||||
unsigned long double2ffp(double d);
|
||||
void decl1(void);
|
||||
struct typ *orop(struct enode **node);
|
||||
int alignment(struct typ *tp);
|
||||
struct amode *g_asshift(struct enode *node, int flags, enum(e_op) op);
|
||||
void closepch();
|
||||
void castback(long offset, struct typ *tp1, struct typ *tp2);
|
||||
void dump_addreg(char *name,int v);
|
||||
double floatexpr();
|
||||
void freeop(struct amode *ap);
|
||||
void err_usr(int m,...);
|
||||
struct typ *cast_op(struct enode **ep, struct typ *tp1, struct typ *tp2);
|
||||
struct amode *g_asadd(struct enode *node, int flags, enum(e_op) op);
|
||||
int tst_short(struct enode *node);
|
||||
struct typ *mk_type(enum(e_bt) bt, int siz);
|
||||
struct enode *mk_node(enum(e_node) nt, struct enode *v1, struct enode *v2);
|
||||
void _repexpr(struct enode **ep);
|
||||
struct typ *binlog(struct enode **node, struct typ *(*xfunc)(), enum(e_node) nt, enum(e_sym) sy);
|
||||
struct amode *func_result2(int flags, long bytes, int reg);
|
||||
struct typ *force_cast_op(struct enode **ep, struct typ *tp1, struct typ *tp2);
|
||||
void _exit(int code);
|
||||
struct amode *g_mul(struct enode *node, int flags);
|
||||
void tmp_free();
|
||||
struct snode *switchstmt(void);
|
||||
void g_pop(int reg, enum(e_am) rmode, int number);
|
||||
struct snode *compound(int no_init);
|
||||
int isshort(struct enode *node);
|
||||
void flush_peep();
|
||||
void put_label(int lab);
|
||||
int not_lvalue(struct enode *node);
|
||||
struct amode *mk_smask(unsigned int mask);
|
||||
int datalit(char *s, int len);
|
||||
void verbose_print_searchdirs();
|
||||
void structassign(struct amode *ap1, struct amode *ap2, long size, int mode);
|
||||
int pchsearch(char *id,int mode); /* returns 0 if not PCH, 1 if PCH/def, -1 if PCH/init */
|
||||
struct snode *labelstmt(void);
|
||||
int getsch(int flag);
|
||||
struct amode *g_xbin(struct enode *node, int flags, enum(e_op) op);
|
||||
void genfuncbegin(void);
|
||||
int crcN(char *na);
|
||||
struct typ *binop(struct enode **node, struct typ *(*xfunc)(), enum(e_node) nt, enum (e_sym) sy);
|
||||
void bsort(struct cse **list);
|
||||
int macro_expand(char *id,int crc/* may equal -1 */,char *in,char *oldin,char *inbound,int need_ds_update);
|
||||
void g_push(int reg, enum(e_am) rmode, int number);
|
||||
int checkcases(struct snode *head);
|
||||
struct amode *g_hook(struct enode *node, int flags);
|
||||
void insert_macros(char *p);
|
||||
struct typ *exprnc(struct enode **node);
|
||||
void genptr(struct enode *node);
|
||||
int *_xalloc(int siz);
|
||||
int castbegin(enum(e_sym) st);
|
||||
void skipspace();
|
||||
int ppquit();
|
||||
void dump_addint(char *name,int v);
|
||||
void validate(struct amode *ap);
|
||||
int radix36(char c);
|
||||
struct amode *mk_legal(struct amode *ap, int flags, long size);
|
||||
struct typ *copy_type_global(struct typ *tp);
|
||||
void freestack(struct _stackimg *img); /* used by g_expr::en_compound */
|
||||
char *fill_calcvar(char *buffer, char *input);
|
||||
int getcache(enum(e_sym) f);
|
||||
int vcg_done();
|
||||
void put_align2(void);
|
||||
int dodefine(int mode); // 1: #define, -1 : #macro, 0 : #undef
|
||||
int drsearch(int r,struct ocode *ip);
|
||||
struct typ *conditional(struct enode **node);
|
||||
void doinit(struct sym *sp, int align);
|
||||
|
||||
#endif
|
||||
446
gtc/src/reg68k.c
Normal file
446
gtc/src/reg68k.c
Normal file
@ -0,0 +1,446 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* register allocation
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
|
||||
/*
|
||||
* Register allocation (for the expression evaluation)
|
||||
* This modules handles the management of scratch registers.
|
||||
* It keeps track of the allocated registers and of the stack
|
||||
*/
|
||||
|
||||
#ifdef MC680X0
|
||||
|
||||
xstatic int next_data CGLOB, next_addr CGLOB;
|
||||
|
||||
#ifndef INFINITE_REGISTERS
|
||||
xstatic char dreg_in_use[MAX_DATA + 1] CGLOBL;
|
||||
xstatic char areg_in_use[MAX_ADDR + 1] CGLOBL;
|
||||
|
||||
xstatic struct reg_struct reg_stack[MAX_REG_STACK + 1] CGLOBL,
|
||||
reg_alloc[MAX_REG_STACK + 1] CGLOBL;
|
||||
|
||||
xstatic int reg_stack_ptr CGLOB;
|
||||
xstatic int reg_alloc_ptr CGLOB;
|
||||
#endif
|
||||
|
||||
void g_push(int reg, enum(e_am) rmode, int number) {
|
||||
#ifndef INFINITE_REGISTERS
|
||||
/*
|
||||
* this routine generates code to push a register onto the stack
|
||||
*/
|
||||
struct amode *ap;
|
||||
ap = (struct amode *) xalloc((int) sizeof(struct amode), AMODE+G_PUSH);
|
||||
ap->preg = reg;
|
||||
ap->mode = rmode;
|
||||
g_code(op_move, 4, ap, push_am);
|
||||
reg_stack[reg_stack_ptr].mode = rmode;
|
||||
reg_stack[reg_stack_ptr].reg = reg;
|
||||
reg_stack[reg_stack_ptr].flag = number;
|
||||
if (reg_alloc[number].flag)
|
||||
ierr(G_PUSH,1);
|
||||
reg_alloc[number].flag = 1;
|
||||
/* check on stack overflow */
|
||||
if (++reg_stack_ptr > MAX_REG_STACK)
|
||||
ierr(G_PUSH,2);
|
||||
#else
|
||||
fatal("GPUSH/infinite");
|
||||
#endif
|
||||
}
|
||||
|
||||
void g_pop(int reg, enum(e_am) rmode, int number) {
|
||||
#ifndef INFINITE_REGISTERS
|
||||
/*
|
||||
* generate code to pop a register from the stack.
|
||||
*/
|
||||
struct amode *ap;
|
||||
|
||||
/* check on stack underflow */
|
||||
if (reg_stack_ptr-- == 0)
|
||||
ierr(G_POP,1);
|
||||
/* check if the desired register really is on stack */
|
||||
if (reg_stack[reg_stack_ptr].flag != number)
|
||||
ierr(G_POP,2);
|
||||
/* check if the register which is restored is really void */
|
||||
if (rmode == am_dreg) {
|
||||
if (dreg_in_use[reg] >= 0)
|
||||
ierr(G_POP,3);
|
||||
dreg_in_use[reg] = number;
|
||||
} else {
|
||||
if (areg_in_use[reg] >= 0)
|
||||
ierr(G_POP,4);
|
||||
areg_in_use[reg] = number;
|
||||
}
|
||||
ap = (struct amode *) xalloc((int) sizeof(struct amode), AMODE+G_PUSH);
|
||||
ap->mode = rmode;
|
||||
ap->preg = reg;
|
||||
g_code(op_move, 4, pop_am, ap);
|
||||
/* clear the push_flag */
|
||||
reg_alloc[number].flag = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void initstack() {
|
||||
/*
|
||||
* this routine should be called before each expression is evaluated to make
|
||||
* sure the stack is balanced and all of the registers are marked free.
|
||||
* This is also a good place to free all 'pseudo' registers in the
|
||||
* stack frame by setting act_scratch to zero
|
||||
*/
|
||||
#ifndef INFINITE_REGISTERS
|
||||
int i;
|
||||
next_data = 0;
|
||||
next_addr = 0;
|
||||
for (i = 0; i <= MAX_DATA; i++)
|
||||
dreg_in_use[i] = -1;
|
||||
for (i = 0; i <= MAX_ADDR; i++)
|
||||
areg_in_use[i] = -1;
|
||||
reg_stack_ptr = 0;
|
||||
reg_alloc_ptr = 0;
|
||||
#else
|
||||
next_data = FIRSTREG;
|
||||
next_addr = FIRSTREG;
|
||||
#endif
|
||||
act_scratch = 0;
|
||||
}
|
||||
|
||||
//#if 0
|
||||
#ifndef __HAVE_STACK_IMAGE
|
||||
#define __HAVE_STACK_IMAGE
|
||||
typedef struct _stackimg {
|
||||
int next_data,next_addr;
|
||||
#ifndef INFINITE_REGISTERS
|
||||
int reg_alloc_ptr,reg_stack_ptr;
|
||||
char dreg_in_use[MAX_DATA+1];
|
||||
char areg_in_use[MAX_ADDR+1];
|
||||
struct reg_struct reg_stack[MAX_REG_STACK+1],reg_alloc[MAX_REG_STACK+1];
|
||||
int act_scratch;
|
||||
#endif
|
||||
} STACK_IMAGE;
|
||||
#endif
|
||||
void usestack(STACK_IMAGE *img) { /* used by g_expr::en_compound */
|
||||
img->next_data = next_data;
|
||||
img->next_addr = next_addr;
|
||||
#ifndef INFINITE_REGISTERS
|
||||
img->act_scratch = act_scratch;
|
||||
img->reg_alloc_ptr = reg_alloc_ptr;
|
||||
img->reg_stack_ptr = reg_stack_ptr;
|
||||
memcpy(img->dreg_in_use, dreg_in_use, MAX_DATA+1);
|
||||
memcpy(img->areg_in_use, areg_in_use, MAX_ADDR+1);
|
||||
memcpy(img->reg_stack, reg_stack, sizeof(struct reg_struct)*(MAX_REG_STACK+1));
|
||||
memcpy(img->reg_alloc, reg_alloc, sizeof(struct reg_struct)*(MAX_REG_STACK+1));
|
||||
#endif
|
||||
}
|
||||
void freestack(STACK_IMAGE *img) { /* used by g_expr::en_compound */
|
||||
next_data = img->next_data;
|
||||
next_addr = img->next_addr;
|
||||
#ifndef INFINITE_REGISTERS
|
||||
act_scratch = img->act_scratch;
|
||||
reg_alloc_ptr = img->reg_alloc_ptr;
|
||||
reg_stack_ptr = img->reg_stack_ptr;
|
||||
memcpy(dreg_in_use, img->dreg_in_use, MAX_DATA+1);
|
||||
memcpy(areg_in_use, img->areg_in_use, MAX_ADDR+1);
|
||||
memcpy(reg_stack, img->reg_stack, sizeof(struct reg_struct)*(MAX_REG_STACK+1));
|
||||
memcpy(reg_alloc, img->reg_alloc, sizeof(struct reg_struct)*(MAX_REG_STACK+1));
|
||||
#endif
|
||||
}
|
||||
//#endif
|
||||
|
||||
#ifdef REGPARM
|
||||
#ifndef __HAVE_REGS_IMAGE
|
||||
#define __HAVE_REGS_IMAGE
|
||||
typedef struct _regsimg {
|
||||
#ifndef INFINITE_REGISTERS
|
||||
int reg_alloc_ptr,reg_stack_ptr;
|
||||
int next_data,next_addr;
|
||||
#endif
|
||||
} REGS_IMAGE;
|
||||
#endif
|
||||
void useregs(REGS_IMAGE *img) { /* used by g_fcall */
|
||||
#ifndef INFINITE_REGISTERS
|
||||
img->reg_alloc_ptr = reg_alloc_ptr;
|
||||
img->reg_stack_ptr = reg_stack_ptr;
|
||||
img->next_data = next_data;
|
||||
img->next_addr = next_addr;
|
||||
next_data = 0;
|
||||
next_addr = 0;
|
||||
#endif
|
||||
}
|
||||
void freeregs(REGS_IMAGE *img) { /* used by g_fcall */
|
||||
#ifndef INFINITE_REGISTERS
|
||||
int i;
|
||||
for (i = 0; i <= MAX_DATA; i++)
|
||||
dreg_in_use[i] = -1;
|
||||
for (i = 0; i <= MAX_ADDR; i++)
|
||||
areg_in_use[i] = -1;
|
||||
reg_alloc_ptr = img->reg_alloc_ptr;
|
||||
reg_stack_ptr = img->reg_stack_ptr;
|
||||
next_data = img->next_data;
|
||||
next_addr = img->next_addr;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PC
|
||||
void checkstack(void) {
|
||||
#ifndef INFINITE_REGISTERS
|
||||
/*
|
||||
* this routines checks if all allocated registers were freed
|
||||
*/
|
||||
int i;
|
||||
for (i=0; i<= MAX_DATA; i++)
|
||||
if (dreg_in_use[i] != -1)
|
||||
ierr(CHECKSTACK,1);
|
||||
for (i=0; i<= MAX_ADDR; i++)
|
||||
if (areg_in_use[i] != -1)
|
||||
ierr(CHECKSTACK,2);
|
||||
if (reg_stack_ptr != 0)
|
||||
ierr(CHECKSTACK,5);
|
||||
if (reg_alloc_ptr != 0)
|
||||
ierr(CHECKSTACK,6);
|
||||
#endif
|
||||
if (next_data != FIRSTREG)
|
||||
ierr(CHECKSTACK,3);
|
||||
if (next_addr != FIRSTREG)
|
||||
ierr(CHECKSTACK,4);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ap_hasbeenpushed(struct amode *ap) {
|
||||
#ifndef INFINITE_REGISTERS
|
||||
return reg_alloc[(int)(ap)->deep].flag;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void validate(struct amode *ap) {
|
||||
#ifndef INFINITE_REGISTERS
|
||||
/*
|
||||
* validate will make sure that if a register within an address mode has been
|
||||
* pushed onto the stack that it is popped back at this time.
|
||||
*/
|
||||
switch (ap->mode) {
|
||||
case am_dreg:
|
||||
if (ap->preg <= MAX_DATA && reg_alloc[(int)ap->deep].flag) {
|
||||
g_pop(ap->preg, am_dreg, (int) ap->deep);
|
||||
}
|
||||
break;
|
||||
case am_indx2:
|
||||
if (ap->sreg <= MAX_DATA && reg_alloc[(int)ap->deep].flag) {
|
||||
g_pop(ap->sreg, am_dreg, (int) ap->deep);
|
||||
}
|
||||
goto common;
|
||||
case am_indx3:
|
||||
if (ap->sreg <= MAX_ADDR && reg_alloc[(int)ap->deep].flag) {
|
||||
g_pop(ap->sreg, am_areg, (int) ap->deep);
|
||||
}
|
||||
goto common;
|
||||
case am_areg:
|
||||
case am_ind:
|
||||
case am_indx:
|
||||
case am_ainc:
|
||||
case am_adec:
|
||||
common:
|
||||
if (ap->preg <= MAX_ADDR && reg_alloc[(int)ap->deep].flag) {
|
||||
g_pop(ap->preg, am_areg, (int) ap->deep);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct amode *temp_data(void) {
|
||||
/*
|
||||
* allocate a temporary data register and return it's addressing mode.
|
||||
*/
|
||||
struct amode *ap;
|
||||
ap = (struct amode *) xalloc((int) sizeof(struct amode), AMODE+TEMP_DATA);
|
||||
#ifndef INFINITE_REGISTERS
|
||||
if (dreg_in_use[next_data] >= 0)
|
||||
/*
|
||||
* The next available register is already in use. it must be pushed
|
||||
*/
|
||||
g_push(next_data, am_dreg, dreg_in_use[next_data]);
|
||||
dreg_in_use[next_data] = reg_alloc_ptr;
|
||||
#endif
|
||||
ap->mode = am_dreg;
|
||||
ap->preg = next_data;
|
||||
#ifndef INFINITE_REGISTERS
|
||||
ap->deep = reg_alloc_ptr;
|
||||
reg_alloc[reg_alloc_ptr].reg = next_data;
|
||||
reg_alloc[reg_alloc_ptr].mode = am_dreg;
|
||||
reg_alloc[reg_alloc_ptr].flag = 0;
|
||||
if (next_data++ == MAX_DATA)
|
||||
next_data = 0; /* wrap around */
|
||||
if (reg_alloc_ptr++ == MAX_REG_STACK)
|
||||
ierr(TEMP_DATA,1);
|
||||
#else
|
||||
next_data++;
|
||||
#endif
|
||||
return ap;
|
||||
}
|
||||
|
||||
struct amode *temp_addr(void) {
|
||||
/*
|
||||
* allocate a temporary addr register and return it's addressing mode.
|
||||
*/
|
||||
struct amode *ap;
|
||||
ap = (struct amode *) xalloc((int) sizeof(struct amode), AMODE+TEMP_ADDR);
|
||||
#ifndef INFINITE_REGISTERS
|
||||
if (areg_in_use[next_addr] >= 0)
|
||||
/*
|
||||
* The next available register is already in use. it must be pushed
|
||||
*/
|
||||
g_push(next_addr, am_areg, areg_in_use[next_addr]);
|
||||
areg_in_use[next_addr] = reg_alloc_ptr;
|
||||
#endif
|
||||
ap->mode = am_areg;
|
||||
ap->preg = next_addr;
|
||||
#ifndef INFINITE_REGISTERS
|
||||
ap->deep = reg_alloc_ptr;
|
||||
reg_alloc[reg_alloc_ptr].reg = next_addr;
|
||||
reg_alloc[reg_alloc_ptr].mode = am_areg;
|
||||
reg_alloc[reg_alloc_ptr].flag = 0;
|
||||
if (next_addr++ == MAX_ADDR)
|
||||
next_addr = 0; /* wrap around */
|
||||
if (reg_alloc_ptr++ == MAX_REG_STACK)
|
||||
ierr(TEMP_ADDR,1);
|
||||
#else
|
||||
next_addr++;
|
||||
#endif
|
||||
return ap;
|
||||
}
|
||||
|
||||
int free_data(void) {
|
||||
/*
|
||||
* returns TRUE if a data register is available at ,,no cost'' (no push).
|
||||
* Used to determine e.g. wether cmp.w #0,An or move.l An,Dm is better
|
||||
*/
|
||||
#ifndef INFINITE_REGISTERS
|
||||
return (dreg_in_use[next_data] < 0);
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void freeop(struct amode *ap) {
|
||||
/*
|
||||
* release any temporary registers used in an addressing mode.
|
||||
*/
|
||||
int number;
|
||||
if (ap == 0)
|
||||
/* This can happen freeing a NOVALUE result */
|
||||
return;
|
||||
switch (ap->mode) {
|
||||
case am_dreg:
|
||||
if (ap->preg <= MAX_DATA) {
|
||||
if (next_data-- == 0)
|
||||
next_data = MAX_DATA;
|
||||
#ifndef INFINITE_REGISTERS
|
||||
number = dreg_in_use[(int)ap->preg];
|
||||
dreg_in_use[(int)ap->preg] = -1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return;
|
||||
case am_indx2:
|
||||
if (ap->sreg <= MAX_DATA) {
|
||||
if (next_data-- == 0)
|
||||
next_data = MAX_DATA;
|
||||
#ifndef INFINITE_REGISTERS
|
||||
number = dreg_in_use[(int)ap->sreg];
|
||||
dreg_in_use[(int)ap->sreg] = -1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
goto common;
|
||||
case am_indx3:
|
||||
if (ap->sreg <= MAX_ADDR) {
|
||||
if (next_addr-- == 0)
|
||||
next_addr = MAX_ADDR;
|
||||
#ifndef INFINITE_REGISTERS
|
||||
number = areg_in_use[(int)ap->sreg];
|
||||
areg_in_use[(int)ap->sreg] = -1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
goto common;
|
||||
case am_areg:
|
||||
case am_ind:
|
||||
case am_indx:
|
||||
case am_ainc:
|
||||
case am_adec:
|
||||
common:
|
||||
if (ap->preg <= MAX_ADDR) {
|
||||
if (next_addr-- == 0)
|
||||
next_addr = MAX_ADDR;
|
||||
#ifndef INFINITE_REGISTERS
|
||||
number = areg_in_use[(int)ap->preg];
|
||||
areg_in_use[(int)ap->preg] = -1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
#ifndef INFINITE_REGISTERS
|
||||
/* some consistency checks */
|
||||
if (number != ap->deep)
|
||||
ierr(FREEOP,1);
|
||||
/* we should only free the most recently allocated register */
|
||||
if (reg_alloc_ptr-- == 0)
|
||||
ierr(FREEOP,2);
|
||||
if (reg_alloc_ptr != number)
|
||||
ierr(FREEOP,3);
|
||||
/* the just freed register should not be on stack */
|
||||
if (reg_alloc[number].flag)
|
||||
ierr(FREEOP,4);
|
||||
#endif
|
||||
}
|
||||
|
||||
void temp_inv(void) {
|
||||
#ifndef INFINITE_REGISTERS
|
||||
/*
|
||||
* push any used temporary registers.
|
||||
* This is necessary across function calls
|
||||
* The reason for this hacking is actually that temp_inv should dump
|
||||
* the registers in the correct order,
|
||||
* the least recently allocated register first.
|
||||
* the most recently allocated register last.
|
||||
*/
|
||||
int i;
|
||||
|
||||
for (i = 0; i < reg_alloc_ptr; i++)
|
||||
if (reg_alloc[i].flag == 0) {
|
||||
g_push(reg_alloc[i].reg, reg_alloc[i].mode, i);
|
||||
/* mark the register void */
|
||||
if (reg_alloc[i].mode == am_dreg)
|
||||
dreg_in_use[reg_alloc[i].reg] = -1;
|
||||
else
|
||||
areg_in_use[reg_alloc[i].reg] = -1;
|
||||
}
|
||||
#else
|
||||
g_code(_op_cleanup_for_external_call, 0, NIL_AMODE, NIL_AMODE);
|
||||
#endif
|
||||
}
|
||||
#endif /* MC680X0 */
|
||||
// vim:ts=4:sw=4
|
||||
182
gtc/src/searchkw.c
Normal file
182
gtc/src/searchkw.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* keyword searching
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
|
||||
xstatic readonly struct kwblk {
|
||||
char *word;
|
||||
enum(e_sym) stype;
|
||||
#ifndef PC
|
||||
int pad;
|
||||
#endif
|
||||
} keywords[] = {
|
||||
{
|
||||
"__asm__", kw_asm
|
||||
}, {
|
||||
"__attribute__", kw_attr
|
||||
}, {
|
||||
"__builtin_constant_p", kwb_constant_p
|
||||
}, {
|
||||
"__c__", kw_c
|
||||
}, {
|
||||
"__count__", kw_count
|
||||
}, {
|
||||
"__eval__", kw_eval
|
||||
}, {
|
||||
"__loop__", kw_loop
|
||||
}, {
|
||||
"__softcast__", kw_softcast
|
||||
}, {
|
||||
"__until__", kw_until
|
||||
}, {
|
||||
"alloca", kw_alloca
|
||||
}, {
|
||||
"asm", kw_asm
|
||||
}, {
|
||||
"auto", kw_auto
|
||||
}, {
|
||||
"break", kw_break
|
||||
}, {
|
||||
"case", kw_case
|
||||
}, {
|
||||
"char", kw_char
|
||||
}, {
|
||||
"const", kw_const
|
||||
}, {
|
||||
"continue", kw_continue
|
||||
}, {
|
||||
"default", kw_default
|
||||
}, {
|
||||
"defined", kw_defined
|
||||
}, {
|
||||
"do", kw_do
|
||||
}, {
|
||||
"double", kw_double
|
||||
}, {
|
||||
"else", kw_else
|
||||
}, {
|
||||
"enum", kw_enum
|
||||
}, {
|
||||
"extern", kw_extern
|
||||
}, {
|
||||
"float", kw_float
|
||||
}, {
|
||||
"for", kw_for
|
||||
}, {
|
||||
"goto", kw_goto
|
||||
}, {
|
||||
"if", kw_if
|
||||
}, {
|
||||
"incbin", kw_incbin
|
||||
}, {
|
||||
"int", kw_int
|
||||
}, {
|
||||
"long", kw_long
|
||||
}, {
|
||||
"loop", kw_loop
|
||||
}, {
|
||||
"register", kw_register
|
||||
}, {
|
||||
"return", kw_return
|
||||
}, {
|
||||
"short", kw_short
|
||||
}, {
|
||||
"signed", kw_signed
|
||||
}, {
|
||||
"sizeof", kw_sizeof
|
||||
}, {
|
||||
"static", kw_static
|
||||
}, {
|
||||
"struct", kw_struct
|
||||
}, {
|
||||
"switch", kw_switch
|
||||
}, {
|
||||
"typedef", kw_typedef
|
||||
}, {
|
||||
"typeof", kw_typeof
|
||||
}, {
|
||||
"union", kw_union
|
||||
}, {
|
||||
"unsigned", kw_unsigned
|
||||
}, {
|
||||
"until", kw_until
|
||||
}, {
|
||||
"void", kw_void
|
||||
}, {
|
||||
"volatile", kw_volatile
|
||||
}, {
|
||||
"while", kw_while
|
||||
/* }, {
|
||||
0, 0*/
|
||||
}
|
||||
};
|
||||
|
||||
#define kw_N 48
|
||||
|
||||
/*
|
||||
* Dichotomic search allows a max of 6 comparisons instead of 50...
|
||||
*/
|
||||
void searchkw(void) {
|
||||
char *s1,*s2,c;
|
||||
const struct kwblk *kwbp;
|
||||
int a=0,b=kw_N-1,m;
|
||||
#ifdef PC
|
||||
if (sizeof(keywords)/sizeof(struct kwblk)!=kw_N)
|
||||
fatal("BUILD ERROR: INVALID KEYWORDS #");
|
||||
#endif
|
||||
while (a<=b) {
|
||||
m=(a+b)>>1;
|
||||
kwbp=&keywords[m];
|
||||
s1=lastid;
|
||||
s2=kwbp->word;
|
||||
do {
|
||||
if (!(c=*s2++)) {
|
||||
if (!*s1)
|
||||
lastst = kwbp->stype;
|
||||
if (is_lang_ext(lastst) && lastid[0]!='_' && !(flags&X_LANG_EXT))
|
||||
lastst = id;
|
||||
if (*s1!='u') // the only case when a kw is the beginning of another one
|
||||
return; // is 'do' vs 'double'
|
||||
}
|
||||
} while (*s1++==c);
|
||||
if (s1[-1]<c) // il faut aller plus haut
|
||||
b=m-1;
|
||||
else a=m+1;
|
||||
}
|
||||
}
|
||||
/*searchkw() // non-dichotomic version
|
||||
{
|
||||
char *s1,*s2,c;
|
||||
struct kwblk *kwbp;
|
||||
kwbp = keywords;
|
||||
while (kwbp->word != 0) {
|
||||
s1 = lastid;
|
||||
s2 = kwbp->word;
|
||||
kwbp++;
|
||||
do {
|
||||
if (!(c=*s2++)) {
|
||||
if (!*s1++)
|
||||
lastst = (--kwbp)->stype;
|
||||
return;
|
||||
}
|
||||
} while (*s1++==c);
|
||||
}
|
||||
}*/
|
||||
// vim:ts=4:sw=4
|
||||
23
gtc/src/securecommdef.h
Normal file
23
gtc/src/securecommdef.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* (on-calc) GT-Dev header file
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifndef __SECURECOMMDEF_H
|
||||
#define __SECURECOMMDEF_H
|
||||
typedef struct {
|
||||
long dummy;
|
||||
void *sft[];
|
||||
} SecureTab;
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
952
gtc/src/stmt.c
Normal file
952
gtc/src/stmt.c
Normal file
@ -0,0 +1,952 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* statement handling
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
#ifdef PC
|
||||
#ifdef SHORT_INT
|
||||
#undef int
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#ifdef SHORT_INT
|
||||
#define int short
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct enode *init_node CGLOB;
|
||||
|
||||
TYP *lastexpr_tp CGLOB;
|
||||
int lastexpr_size CGLOB, lastexpr_type CGLOB;
|
||||
|
||||
/*
|
||||
* the statement module handles all of the possible c statements and builds a
|
||||
* parse tree of the statements.
|
||||
*
|
||||
* each routine returns a pointer to a statement parse node which reflects the
|
||||
* statement just parsed.
|
||||
*/
|
||||
|
||||
|
||||
int start_block(int m) { // used in block() (func.c)
|
||||
if (m) {
|
||||
needpunc(begin);
|
||||
return 1; // we don't care about the result in this case
|
||||
} else
|
||||
return lastst==begin;
|
||||
}
|
||||
|
||||
unsigned int getconst(enum(e_sym) s,enum(e_sym) e) {
|
||||
struct enode *en;
|
||||
getsym();
|
||||
if (lastst != s)
|
||||
error(ERR_EXPREXPECT);
|
||||
else {
|
||||
getsym();
|
||||
if (exprnc(&en) == 0)
|
||||
error(ERR_EXPREXPECT);
|
||||
needpunc(e);
|
||||
opt0(&en);
|
||||
if (en->nodetype != en_icon)
|
||||
error(ERR_CONSTEXPECT);
|
||||
else if ((unsigned long)en->v.i>=65536)
|
||||
error(ERR_OUTRANGE);
|
||||
else return en->v.i;
|
||||
}
|
||||
return 0; // make the compiler happy
|
||||
}
|
||||
unsigned int getconst2(enum(e_sym) e) {
|
||||
struct enode *en;
|
||||
if (exprnc(&en) == 0)
|
||||
error(ERR_EXPREXPECT);
|
||||
needpunc(e);
|
||||
opt0(&en);
|
||||
if (en->nodetype != en_icon)
|
||||
error(ERR_CONSTEXPECT);
|
||||
else if ((unsigned long)en->v.i>=65536)
|
||||
error(ERR_OUTRANGE);
|
||||
else return en->v.i;
|
||||
return 0; // make the compiler happy
|
||||
}
|
||||
|
||||
struct snode *whilestmt(void) {
|
||||
/*
|
||||
* whilestmt parses the c while statement.
|
||||
*/
|
||||
struct snode *snp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_while;
|
||||
snp->count = 3;
|
||||
getsym();
|
||||
if (lastst != openpa)
|
||||
error(ERR_EXPREXPECT);
|
||||
else {
|
||||
getsym();
|
||||
if (expression(&(snp->exp)) == 0)
|
||||
error(ERR_EXPREXPECT);
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=lineid;
|
||||
#endif
|
||||
needpunc(closepa);
|
||||
if (lastst == kw_count) snp->count=getconst(openpa,closepa);
|
||||
snp->s1 = statement();
|
||||
}
|
||||
return snp;
|
||||
}
|
||||
|
||||
struct snode *asmstmt();
|
||||
#if !defined(AS) && !defined(ASM)
|
||||
struct snode *asmstmt(void) {
|
||||
/*
|
||||
* asmstmt parses the gtc c asm statement.
|
||||
*/
|
||||
struct snode *snp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_asm;
|
||||
snp->count = 1;
|
||||
getsym();
|
||||
if (lastst != openpa)
|
||||
error(ERR_EXPREXPECT);
|
||||
else {
|
||||
getsym();
|
||||
if (lastst != sconst)
|
||||
error(ERR_SYNTAX);
|
||||
snp->v1.i = (long)strsave(laststr);
|
||||
getsym();
|
||||
if (lastst == colon) {
|
||||
getsym();
|
||||
uwarn("only asm(\"...\") is supported yet");
|
||||
error(ERR_SYNTAX);
|
||||
}
|
||||
needpunc(closepa);
|
||||
needpunc(semicolon);
|
||||
}
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=lineid;
|
||||
#endif
|
||||
return snp;
|
||||
}
|
||||
#endif
|
||||
|
||||
//struct enode lp_one = { en_icon, bt_ushort, 2, {1L}, 0, 0};
|
||||
xstatic struct enode *lp_one CGLOB;
|
||||
struct snode *loopstmt(void) {
|
||||
/*
|
||||
* loopstmt parses the gtc c loop statement.
|
||||
*/
|
||||
struct snode *snp; TYP *tp;
|
||||
struct enode *exp;
|
||||
int has_count;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_loop;
|
||||
snp->count = 3;
|
||||
has_count = 0;
|
||||
getsym();
|
||||
if (lastst != openpa)
|
||||
error(ERR_EXPREXPECT);
|
||||
else {
|
||||
getsym();
|
||||
if (lastst != id)
|
||||
error(ERR_IDEXPECT);
|
||||
if (!nameref(&(snp->v1.e))) error(ERR_EXPREXPECT);
|
||||
if (lastst != assign)
|
||||
error(ERR_SYNTAX);
|
||||
getsym();
|
||||
if (!(tp=expression(&(snp->exp))))
|
||||
error(ERR_EXPREXPECT);
|
||||
cast_op(&(snp->exp),tp,(TYP *)&tp_ushort);
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=lineid;
|
||||
#endif
|
||||
needpunc(closepa);
|
||||
if (lastst == kw_count) { snp->count=getconst(openpa,closepa); has_count=1; }
|
||||
opt0(&(snp->exp));
|
||||
if (snp->exp->nodetype==en_icon) {
|
||||
unsigned int c=snp->exp->v.i;
|
||||
if (has_count) {
|
||||
if (c!=snp->count)
|
||||
uwarn("loop has an effective count of %u whereas %u precised",
|
||||
c,snp->count);
|
||||
} else snp->count=c;
|
||||
}
|
||||
lp_one = mk_icon(1L);
|
||||
lp_one->etype = bt_ushort; lp_one->esize = 2;
|
||||
snp->exp = exp = mk_node(en_sub,snp->exp,lp_one);
|
||||
exp->etype = bt_ushort; exp->esize = 2;
|
||||
opt4(&(snp->exp));
|
||||
snp->exp = exp = mk_node(en_assign,snp->v1.e,snp->exp);
|
||||
exp->etype = bt_ushort; exp->esize = 2;
|
||||
snp->s1 = statement();
|
||||
if (lastst == kw_until) {
|
||||
getsym();
|
||||
if (!expression(&(snp->v2.e))) error(ERR_EXPREXPECT);
|
||||
} else snp->v2.e=NULL;
|
||||
}
|
||||
return snp;
|
||||
}
|
||||
|
||||
struct snode *dostmt(void) {
|
||||
/*
|
||||
* dostmt parses the c do-while construct.
|
||||
*/
|
||||
struct snode *snp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_do;
|
||||
snp->count = 3;
|
||||
getsym();
|
||||
snp->s1 = statement();
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=lineid;
|
||||
#endif
|
||||
if (lastst != kw_while)
|
||||
error(ERR_WHILEXPECT);
|
||||
else {
|
||||
getsym();
|
||||
if (lastst != openpa)
|
||||
error(ERR_EXPREXPECT);
|
||||
else {
|
||||
getsym();
|
||||
if (expression(&(snp->exp)) == 0)
|
||||
error(ERR_EXPREXPECT);
|
||||
needpunc(closepa);
|
||||
if (lastst == kw_count) snp->count=getconst(openpa,closepa);
|
||||
}
|
||||
if (lastst != end)
|
||||
needpunc(semicolon);
|
||||
}
|
||||
return snp;
|
||||
}
|
||||
|
||||
struct snode *forstmt(void) {
|
||||
struct snode *snp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_for;
|
||||
snp->count = 3;
|
||||
getsym();
|
||||
needpunc(openpa);
|
||||
/*if (*/expression(&(snp->exp))/* == 0)
|
||||
snp->exp = 0*/;
|
||||
needpunc(semicolon);
|
||||
/*if (*/expression(&(snp->v1.e))/* == 0)
|
||||
snp->v1.e = 0*/;
|
||||
needpunc(semicolon);
|
||||
/*if (*/expression(&(snp->v2.e))/* == 0)
|
||||
snp->v2.e = 0*/;
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=lineid;
|
||||
#endif
|
||||
needpunc(closepa);
|
||||
if (lastst == kw_count) snp->count=getconst(openpa,closepa);
|
||||
snp->s1 = statement();
|
||||
return snp;
|
||||
}
|
||||
|
||||
struct snode *ifstmt(void) {
|
||||
/*
|
||||
* ifstmt parses the c if statement and an else clause if one is present.
|
||||
*/
|
||||
struct snode *snp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_if;
|
||||
snp->count=32768;
|
||||
getsym();
|
||||
if (lastst != openpa)
|
||||
error(ERR_EXPREXPECT);
|
||||
else {
|
||||
getsym();
|
||||
if (expression(&(snp->exp)) == 0)
|
||||
error(ERR_EXPREXPECT);
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=lineid;
|
||||
#endif
|
||||
needpunc(closepa);
|
||||
if (lastst == kw_count) {
|
||||
unsigned int i=getconst(openpa,comma),j=getconst2(closepa);
|
||||
snp->count=((unsigned long)i<<16)/(i+j);
|
||||
}
|
||||
snp->s1 = statement();
|
||||
if (lastst == kw_else) {
|
||||
getsym();
|
||||
snp->v1.s = statement();
|
||||
} else {
|
||||
#ifdef NO_CALLOC
|
||||
snp->v1.s = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return snp;
|
||||
}
|
||||
|
||||
/*
|
||||
* consider the following piece of code:
|
||||
*
|
||||
* switch (i) {
|
||||
* case 1:
|
||||
* if (j) {
|
||||
* .....
|
||||
* } else
|
||||
* case 2:
|
||||
* ....
|
||||
* }
|
||||
*
|
||||
* case statements may be deep inside, so we need a global variable
|
||||
* last_case to link them
|
||||
*/
|
||||
xstatic struct snode *last_case CGLOB; /* last case statement within this switch */
|
||||
|
||||
struct snode *casestmt(void) {
|
||||
/*
|
||||
* cases are returned as seperate statements. for normal cases label is the
|
||||
* case value and v1.i is zero. for the default case v1.i is nonzero.
|
||||
*/
|
||||
struct snode *snp,*snp0;
|
||||
snp0 = snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
#ifdef NO_CALLOC
|
||||
snp->s1 = NIL_SNODE;
|
||||
#endif
|
||||
if (lastst == kw_case) {
|
||||
long v;
|
||||
getsym();
|
||||
snp->stype = st_case;
|
||||
snp->v2.i = v = intexpr();
|
||||
if (lastst == dots) { // TODO : make only one 'case' label
|
||||
long max;
|
||||
getsym();
|
||||
if ((max = intexpr()) < v) error(ERR_CASERANGE);
|
||||
else while (v != max) {
|
||||
last_case = last_case->s1 = snp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
last_case->v1.s = snp;
|
||||
#ifdef NO_CALLOC
|
||||
snp->s1 = NIL_SNODE;
|
||||
#endif
|
||||
snp->stype = st_case;
|
||||
snp->v2.i = ++v;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* lastst is kw_default */
|
||||
getsym();
|
||||
/* CVW: statement type needed for analyze etc. */
|
||||
snp->stype = st_default;
|
||||
}
|
||||
last_case = last_case->s1 = snp;
|
||||
needpunc(colon);
|
||||
if (lastst != end)
|
||||
snp->v1.s = statement();
|
||||
return snp0;
|
||||
}
|
||||
|
||||
int checkcases(struct snode *head) {
|
||||
/*
|
||||
* checkcases will check to see if any duplicate cases exist in the case list
|
||||
* pointed to by head.
|
||||
*/
|
||||
struct snode *top, *cur;
|
||||
cur = top = head;
|
||||
while (top != 0) {
|
||||
cur = top->s1;
|
||||
while (cur != 0) {
|
||||
if (cur->stype != st_default && top->stype != st_default
|
||||
&& cur->v2.i == top->v2.i) {
|
||||
uwarn("duplicate case label for value %ld", cur->v2.i);
|
||||
return 1;
|
||||
}
|
||||
if (cur->stype == st_default && top->stype == st_default) {
|
||||
uwarn("duplicate default label");
|
||||
return 1;
|
||||
}
|
||||
cur = cur->s1;
|
||||
}
|
||||
top = top->s1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snode *switchstmt(void) {
|
||||
struct snode *snp;
|
||||
struct snode *local_last_case;
|
||||
local_last_case = last_case;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
last_case = snp;
|
||||
#ifdef NO_CALLOC
|
||||
snp->s1 = 0;
|
||||
#endif
|
||||
snp->stype = st_switch;
|
||||
getsym();
|
||||
needpunc(openpa);
|
||||
if ((expression(&(snp->exp))) == 0)
|
||||
error(ERR_EXPREXPECT);
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=lineid;
|
||||
#endif
|
||||
needpunc(closepa);
|
||||
needpunc(begin);
|
||||
snp->v1.s = compound(1);
|
||||
if (checkcases(snp->s1))
|
||||
error(ERR_DUPCASE);
|
||||
last_case = local_last_case;
|
||||
return snp;
|
||||
}
|
||||
|
||||
struct snode *retstmt(void) {
|
||||
struct snode *snp;
|
||||
TYP *tp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_return;
|
||||
getsym();
|
||||
tp = expression(&(snp->exp));
|
||||
if (snp->exp != 0)
|
||||
(void) cast_op(&(snp->exp), tp, ret_type);
|
||||
if (lastst != end)
|
||||
needpunc(semicolon);
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=prevlineid;
|
||||
#endif
|
||||
return snp;
|
||||
}
|
||||
|
||||
struct snode *breakstmt(void) {
|
||||
struct snode *snp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_break;
|
||||
getsym();
|
||||
if (lastst != end)
|
||||
needpunc(semicolon);
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=prevlineid;
|
||||
#endif
|
||||
return snp;
|
||||
}
|
||||
|
||||
struct snode *contstmt(void) {
|
||||
struct snode *snp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_continue;
|
||||
getsym();
|
||||
if (lastst != end)
|
||||
needpunc(semicolon);
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=prevlineid;
|
||||
#endif
|
||||
return snp;
|
||||
}
|
||||
|
||||
struct snode *exprstmt(void) {
|
||||
/*
|
||||
* exprstmt is called whenever a statement does not begin with a keyword. the
|
||||
* statement should be an expression.
|
||||
*/
|
||||
struct snode *snp;
|
||||
debug('u');
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_expr;
|
||||
/*
|
||||
* I have a problem here.
|
||||
* If expression() fails on the first character and does not do a getsym(),
|
||||
* there may be an infinite loop since we will continue coming up here.
|
||||
* Since the compiler will stop after MAX_ERROR_COUNT calls to error(),
|
||||
* this might not be THAT much of a problem.
|
||||
*/
|
||||
if (!(lastexpr_tp=expression(&(snp->exp))))
|
||||
error(ERR_EXPREXPECT);
|
||||
else {
|
||||
lastexpr_type=snp->exp->etype;
|
||||
lastexpr_size=snp->exp->esize;
|
||||
}
|
||||
debug('v');
|
||||
if (lastst != end)
|
||||
needpunc(semicolon);
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=prevlineid;
|
||||
#endif
|
||||
debug('w');
|
||||
return snp;
|
||||
}
|
||||
|
||||
#ifdef AUTOINIT_PAD
|
||||
//long auto_init(long offs,TYP *typ,int brace_level,int offmod);
|
||||
long auto_pad(long offs,int len,int offmod) {
|
||||
long nbytes=0;
|
||||
while (len>0) {
|
||||
int size;
|
||||
if ((offs+offmod)&1)
|
||||
size=1;
|
||||
else if (len<=2)
|
||||
size=len;
|
||||
else if (len==3)
|
||||
size=2;
|
||||
else size=4;
|
||||
|
||||
{
|
||||
struct enode *ep1,*ep2=mk_icon(0L),*ep3;
|
||||
ep2->esize = size; /* don't care about the etype, it's set to char */
|
||||
|
||||
ep1 = mk_node(en_autocon, NIL_ENODE, NIL_ENODE);
|
||||
ep1->v.i = offs;
|
||||
ep1->etype = bt_pointer;
|
||||
ep1->esize = 4;
|
||||
|
||||
ep3 = mk_icon((long)offmod);
|
||||
ep3->etype = bt_long;
|
||||
ep3->esize = 4;
|
||||
|
||||
ep1 = mk_node(en_add, ep1, ep3);
|
||||
ep1->etype = bt_pointer;
|
||||
ep1->esize = 4;
|
||||
|
||||
ep1 = mk_node(en_ref, ep1, NIL_ENODE);
|
||||
ep1->esize = size; /* don't care about the etype, it's set to char */
|
||||
|
||||
ep1 = mk_node(en_assign, ep1, ep2);
|
||||
ep1->esize = size; /* don't care about the etype, it's set to char */
|
||||
|
||||
if (init_node == 0) {
|
||||
init_node = ep1;
|
||||
} else {
|
||||
init_node = mk_node(en_void, init_node, ep1);
|
||||
}
|
||||
}
|
||||
|
||||
len-=size;
|
||||
nbytes+=size;
|
||||
offmod+=size;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
#endif
|
||||
|
||||
long auto_init(long offs,TYP *typ,TYP **tpp,int brace_level,int offmod,int stroff) {
|
||||
/*
|
||||
* generated assignment statements for initialization of auto and register
|
||||
* variables. The initialization is generated like comma operators so a
|
||||
* single statement does all the initializations
|
||||
*/
|
||||
struct enode *ep1, *ep2;
|
||||
struct typ *tp;
|
||||
int brace_seen = 0;
|
||||
long nbytes = 0;
|
||||
|
||||
auto_init_restart:
|
||||
if (lastst == begin) {
|
||||
brace_level++;
|
||||
brace_seen++;
|
||||
getsym();
|
||||
}
|
||||
if (typ->type==bt_struct && brace_level) {
|
||||
struct sym *sp;
|
||||
sp = typ->lst.head; /* start at top of symbol table */
|
||||
while (sp != 0) {
|
||||
/* infunc("DrawPacmanLogoAndHandleMenu")
|
||||
bkpt();*/
|
||||
nbytes+=auto_init(offs,sp->tp,NULL,brace_level,(int)(offmod+sp->value.i),-1);
|
||||
if (lastst == comma)
|
||||
getsym();
|
||||
if (lastst == end || lastst == semicolon)
|
||||
break;
|
||||
sp = sp->next;
|
||||
}
|
||||
#ifdef AUTOINIT_PAD
|
||||
nbytes+=auto_pad(offs,(int)(typ->size-nbytes),offmod+nbytes); /* negative args are OK for auto_pad */
|
||||
#endif
|
||||
} else if (typ->type==bt_union) {
|
||||
typ = (typ->lst.head)->tp;
|
||||
goto auto_init_restart;
|
||||
} else if (typ->val_flag) {
|
||||
// if (!brace_level) error(ERR_SYNTAX);
|
||||
if (lastst != end) {
|
||||
int stroff=-1;
|
||||
if (lastst == sconst && !brace_seen)
|
||||
stroff=0;
|
||||
while (1) {
|
||||
nbytes+=auto_init(offs,typ->btp,NULL,brace_level,(int)(offmod+nbytes),stroff);
|
||||
if (stroff>=0) {
|
||||
stroff++;
|
||||
if (stroff>lstrlen || (stroff==lstrlen && typ->size)) {
|
||||
getsym();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (lastst == comma)
|
||||
getsym();
|
||||
if (lastst == end || lastst == semicolon) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typ->size && nbytes > typ->size)
|
||||
error(ERR_INITSIZE);
|
||||
if (nbytes != typ->size && tpp) {
|
||||
/* fix the symbol's size, unless tpp=0 (item of a struct/union or array) */
|
||||
typ = copy_type(typ);
|
||||
*tpp = typ;
|
||||
typ->size = nbytes;
|
||||
}
|
||||
#ifdef AUTOINIT_PAD
|
||||
nbytes+=auto_pad(offs,(int)(typ->size-nbytes),offmod+nbytes); /* negative args are OK for auto_pad */
|
||||
#endif
|
||||
} else {
|
||||
if (stroff<0) {
|
||||
if (!(tp = exprnc(&ep2)))
|
||||
error(ERR_ILLINIT);
|
||||
} else
|
||||
ep2=mk_icon(stroff<lstrlen?laststr[stroff]:0), tp=(TYP *)&tp_char;
|
||||
(void) cast_op(&ep2, tp, typ);
|
||||
nbytes=bt_size(typ->type);
|
||||
|
||||
/* if (offs==0xfffffe4e)
|
||||
bkpt();*/
|
||||
|
||||
ep1 = mk_node(en_autocon, NIL_ENODE, NIL_ENODE);
|
||||
ep1->v.i = offs;
|
||||
/* ep1->etype = typ->type; // this is a ridiculous bug that I spent hours finding...
|
||||
ep1->esize = typ->size; */
|
||||
ep1->etype = bt_pointer;
|
||||
ep1->esize = 4;
|
||||
|
||||
if (offmod) {
|
||||
struct enode *ep3 = mk_icon((long)offmod);
|
||||
ep3->etype = bt_long;
|
||||
ep3->esize = 4;
|
||||
|
||||
ep1 = mk_node(en_add, ep1, ep3);
|
||||
ep1->etype = bt_pointer;
|
||||
ep1->esize = 4;
|
||||
}
|
||||
|
||||
ep1 = mk_node(en_ref, ep1, NIL_ENODE);
|
||||
ep1->etype = typ->type;
|
||||
ep1->esize = typ->size;
|
||||
|
||||
ep1 = mk_node(en_assign, ep1, ep2);
|
||||
ep1->etype = typ->type;
|
||||
ep1->esize = typ->size;
|
||||
|
||||
#ifdef MID_DECL_IN_EXPR
|
||||
if (middle_decl)
|
||||
md_expr = ep1, md_type = typ;
|
||||
#error fix needed around here...
|
||||
else {
|
||||
#endif
|
||||
if (init_node == 0) {
|
||||
init_node = ep1;
|
||||
} else {
|
||||
init_node = mk_node(en_void, init_node, ep1);
|
||||
}
|
||||
#ifdef MID_DECL_IN_EXPR
|
||||
}
|
||||
#endif
|
||||
}
|
||||
while (brace_seen--)
|
||||
needpunc(end);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
struct snode *compound(int no_init) {
|
||||
/*
|
||||
* compound processes a block of statements and forms a linked list of the
|
||||
* statements within the block.
|
||||
*
|
||||
* compound expects the input pointer to already be past the begin symbol of the
|
||||
* block.
|
||||
*
|
||||
* If no_init is true, auto initializations are not desirable
|
||||
*/
|
||||
struct snode *head, *tail, *snp;
|
||||
// struct sym *local_tail, *local_tagtail;
|
||||
HTABLE old_lsyms,old_ltags;
|
||||
// hashinit(&symtab);
|
||||
/* local_tail = lsyms.tail;
|
||||
local_tagtail = ltags.tail;*/
|
||||
memcpy(&old_lsyms,&lsyms,sizeof(HTABLE));
|
||||
memcpy(&old_ltags,<ags,sizeof(HTABLE));
|
||||
dodecl(sc_auto);
|
||||
if (init_node == 0) {
|
||||
head = tail = 0;
|
||||
} else {
|
||||
if (no_init>0) {
|
||||
uwarn("auto initialization not reached");
|
||||
}
|
||||
head = tail = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
head->stype = st_expr;
|
||||
head->exp = init_node;
|
||||
#ifdef NO_CALLOC
|
||||
head->next = 0;
|
||||
#endif
|
||||
#ifdef DB_POSSIBLE
|
||||
head->line = prevlineid;
|
||||
#endif
|
||||
}
|
||||
init_node = 0;
|
||||
while (lastst != end) {
|
||||
if (head == 0)
|
||||
head = tail = statement();
|
||||
else {
|
||||
tail->next = statement();
|
||||
if (tail->next != 0)
|
||||
tail = tail->next;
|
||||
}
|
||||
}
|
||||
if (no_init>=0)
|
||||
getsym();
|
||||
#ifdef LISTING
|
||||
if (list_option) {
|
||||
/* if (local_tail != lsyms.tail) {
|
||||
if (local_tail != 0)
|
||||
symtab.head = local_tail->next;
|
||||
else
|
||||
symtab.head = lsyms.head;
|
||||
symtab.tail = lsyms.tail;
|
||||
fprintf(list, "\n*** local symbol table ***\n\n");
|
||||
list_table(&symtab, 0);
|
||||
fprintf(list, "\n");
|
||||
}*/
|
||||
fprintf(list, "\n*** local symbol table ***\n\n");
|
||||
list_table(&lsyms, 0);
|
||||
fprintf(list, "\n");
|
||||
/* if (local_tagtail != ltags.tail) {
|
||||
if (local_tagtail != 0)
|
||||
symtab.head = local_tagtail->next;
|
||||
else
|
||||
symtab.head = ltags.head;
|
||||
symtab.tail = ltags.tail;
|
||||
fprintf(list, "\n*** local structures and unions ***\n\n");
|
||||
list_table(&symtab, 0);
|
||||
fprintf(list, "\n");
|
||||
}*/
|
||||
fprintf(list, "\n*** local structures and unions ***\n\n");
|
||||
list_table(<ags, 0);
|
||||
fprintf(list, "\n");
|
||||
}
|
||||
#endif
|
||||
/* if (local_tagtail != 0) {
|
||||
ltags.tail = local_tagtail;
|
||||
ltags.tail->next = 0;
|
||||
} else {
|
||||
ltags.head = 0;
|
||||
ltags.tail = 0;
|
||||
}
|
||||
|
||||
|
||||
if (local_tail != 0) {
|
||||
lsyms.tail = local_tail;
|
||||
lsyms.tail->next = 0;
|
||||
} else {
|
||||
lsyms.head = 0;
|
||||
lsyms.tail = 0;
|
||||
}*/
|
||||
memcpy(&lsyms,&old_lsyms,sizeof(HTABLE));
|
||||
memcpy(<ags,&old_ltags,sizeof(HTABLE));
|
||||
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_compound;
|
||||
snp->s1 = head;
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=lineid;
|
||||
#endif
|
||||
return snp;
|
||||
}
|
||||
|
||||
extern unsigned int pos;
|
||||
struct snode *labelstmt(void) {
|
||||
/*
|
||||
* labelstmt processes a label that appears before a statement as a seperate
|
||||
* statement.
|
||||
*/
|
||||
struct snode *snp;
|
||||
struct sym *sp;
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
/*if (pos>=0x25C2)
|
||||
printf("jiotrh");*/
|
||||
snp->stype = st_label;
|
||||
if ((sp = search(lastid, lastcrc, &labsyms)) == 0) {
|
||||
sp = (struct sym *) xalloc((int) sizeof(struct sym), _SYM);
|
||||
sp->name = strsave(lastid);
|
||||
sp->storage_class = sc_label;
|
||||
#ifdef NO_CALLOC
|
||||
sp->tp = 0;
|
||||
#endif
|
||||
sp->value.i = nxtlabel();
|
||||
append(&sp, &labsyms);
|
||||
} else {
|
||||
if (sp->storage_class != sc_ulabel)
|
||||
error(ERR_LABEL);
|
||||
else
|
||||
sp->storage_class = sc_label;
|
||||
}
|
||||
getsym(); /* get past id */
|
||||
needpunc(colon);
|
||||
if (sp->storage_class == sc_label) {
|
||||
snp->v2.i = sp->value.i;
|
||||
if (lastst != end)
|
||||
snp->s1 = statement();
|
||||
return snp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snode *gotostmt(void) {
|
||||
/*
|
||||
* gotostmt processes the goto statement and puts undefined labels into the
|
||||
* symbol table.
|
||||
*/
|
||||
struct snode *snp;
|
||||
struct sym *sp;
|
||||
getsym();
|
||||
if (lastst != id) {
|
||||
error(ERR_IDEXPECT);
|
||||
return 0;
|
||||
}
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
if ((sp = search(lastid, lastcrc, &labsyms)) == 0) {
|
||||
sp = (struct sym *) xalloc((int) sizeof(struct sym), _SYM);
|
||||
sp->name = strsave(lastid);
|
||||
sp->value.i = nxtlabel();
|
||||
sp->storage_class = sc_ulabel;
|
||||
#ifdef NO_CALLOC
|
||||
sp->tp = 0;
|
||||
#endif
|
||||
append(&sp, &labsyms);
|
||||
}
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line=lineid;
|
||||
#endif
|
||||
getsym(); /* get past label name */
|
||||
if (lastst != end)
|
||||
needpunc(semicolon);
|
||||
if (sp->storage_class != sc_label && sp->storage_class != sc_ulabel)
|
||||
error(ERR_LABEL);
|
||||
else {
|
||||
snp->stype = st_goto;
|
||||
snp->v2.i = sp->value.i;
|
||||
snp->next = 0;
|
||||
return snp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct snode *statement(void) {
|
||||
/*
|
||||
* statement figures out which of the statement processors should be called
|
||||
* and transfers control to the proper routine.
|
||||
*/
|
||||
struct snode *snp;
|
||||
/* if (lineid==0x20A)
|
||||
bkpt();*/
|
||||
switch (lastst) {
|
||||
case semicolon:
|
||||
getsym();
|
||||
snp = 0;
|
||||
break;
|
||||
case kw_char: case kw_short: case kw_unsigned: case kw_long:
|
||||
case kw_struct: case kw_union: case kw_enum: case kw_void:
|
||||
case kw_float: case kw_double: case kw_int: case kw_typeof:
|
||||
case kw_signed: case kw_const: case kw_volatile:
|
||||
case kw_register: case kw_auto:
|
||||
case kw_static: case kw_typedef: case kw_extern:
|
||||
middle_decl:
|
||||
if (!(flags & X_MID_DECL)) goto default_decl;
|
||||
#ifdef OLD_MID_DECL
|
||||
snp = compound(0);
|
||||
if ((int)cached_sym IS_VALID) fatal("CACHE"); // will never happen since no caching is
|
||||
// performed when lastst==begin
|
||||
/* cached_sym2 = cached_sym;*/
|
||||
cached_sym = lastst; cached_lineid = lineid;
|
||||
lastst = end;
|
||||
break;
|
||||
#else
|
||||
#ifdef MID_DECL
|
||||
/* the following is much cleaner than the old mid_decl handler */
|
||||
dodecl(sc_auto);
|
||||
if (init_node) {
|
||||
snp = (struct snode *) xalloc((int) sizeof(struct snode), SNODE);
|
||||
snp->stype = st_expr;
|
||||
snp->exp = init_node;
|
||||
#ifdef DB_POSSIBLE
|
||||
snp->line = prevlineid;
|
||||
#endif
|
||||
init_node = 0; // compound resets after calling rather than before...
|
||||
} // I find it pretty weird :) (maybe it should be changed?)
|
||||
else snp = 0;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
case begin:
|
||||
getsym();
|
||||
snp = compound(0);
|
||||
break;
|
||||
case kw_if:
|
||||
snp = ifstmt();
|
||||
break;
|
||||
case kw_while:
|
||||
snp = whilestmt();
|
||||
break;
|
||||
case kw_for:
|
||||
snp = forstmt();
|
||||
break;
|
||||
case kw_return:
|
||||
snp = retstmt();
|
||||
break;
|
||||
case kw_break:
|
||||
snp = breakstmt();
|
||||
break;
|
||||
case kw_goto:
|
||||
snp = gotostmt();
|
||||
break;
|
||||
case kw_continue:
|
||||
snp = contstmt();
|
||||
break;
|
||||
case kw_do:
|
||||
snp = dostmt();
|
||||
break;
|
||||
case kw_switch:
|
||||
snp = switchstmt();
|
||||
break;
|
||||
case kw_case:
|
||||
case kw_default:
|
||||
snp = casestmt();
|
||||
break;
|
||||
case kw_loop:
|
||||
snp = loopstmt();
|
||||
break;
|
||||
case kw_count:
|
||||
snp = NULL;
|
||||
error(ERR_EXPREXPECT);
|
||||
break;
|
||||
case kw_asm:
|
||||
snp = asmstmt();
|
||||
break;
|
||||
case id:
|
||||
if (!getcache(id) && cached_sym==colon) {
|
||||
snp = labelstmt();
|
||||
break;
|
||||
}
|
||||
#if defined(OLD_MID_DECL) || defined(MID_DECL)
|
||||
if (lastsp && lastsp->storage_class == sc_typedef)
|
||||
goto middle_decl;
|
||||
#endif
|
||||
default_decl:
|
||||
/* else fall through to process expression */
|
||||
default:
|
||||
snp = exprstmt();
|
||||
break;
|
||||
}
|
||||
if (snp != 0)
|
||||
snp->next = 0;
|
||||
return snp;
|
||||
}
|
||||
// vim:ts=4:sw=4
|
||||
91
gtc/src/sunpack.c
Normal file
91
gtc/src/sunpack.c
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* precompiled header string unpacking
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#ifdef PC
|
||||
#include <string.h>
|
||||
|
||||
char *sUnpack(char *in,char *out,char *dic) {
|
||||
char c; char *out0=out;
|
||||
while ((c=*in++)) {
|
||||
if ((char)c>=0) *out++=c;
|
||||
else {
|
||||
if (c==(char)0x80) *out++=*in++;
|
||||
else if (c==(char)0xFF) {
|
||||
|
||||
} else {
|
||||
char *dp=dic;
|
||||
c-=(char)0x81;
|
||||
while (c--) {
|
||||
while (*dp++);
|
||||
}
|
||||
strcpy(out,dp);
|
||||
while (*out++); out--;
|
||||
}
|
||||
}
|
||||
}
|
||||
*out++=0;
|
||||
return out0;
|
||||
}
|
||||
#else
|
||||
char *__attribute__((stkparm)) sUnpack(char *in,char *out,char *dic);
|
||||
asm(
|
||||
" xdef sUnpack\n"
|
||||
"sUnpack:\n"
|
||||
"/* bra.s sUnpack*/\n"
|
||||
" move.l 4(%sp),%a0\n"
|
||||
" move.l 8(%sp),%a1\n"
|
||||
" moveq #126,%d1\n"
|
||||
" moveq #0,%d0\n"
|
||||
" move.b (%a0)+,%d0\n"
|
||||
" beq su_quit\n"
|
||||
" bmi su_special\n"
|
||||
"su_copy_lp:\n"
|
||||
" move.b %d0,(%a1)+\n"
|
||||
"su_next:\n"
|
||||
" move.b (%a0)+,%d0\n"
|
||||
" bgt su_copy_lp\n"
|
||||
" beq su_quit\n"
|
||||
"su_special:\n"
|
||||
" subq.b #1,%d0\n"
|
||||
" bmi su_not_escape\n"
|
||||
" move.b (%a0)+,(%a1)+\n"
|
||||
" bra su_next\n"
|
||||
"su_not_escape:\n"
|
||||
" addq.b #2,%d0\n"
|
||||
" bmi su_not_romcall\n"
|
||||
" \n"
|
||||
"su_not_romcall:\n"
|
||||
" add.b %d1,%d0\n"
|
||||
" move.l %a0,%d2\n"
|
||||
" move.l 12(%sp),%a0\n"
|
||||
" dbf %d0,su_search_loop\n"
|
||||
" bra su_search_done\n"
|
||||
"su_search_loop:\n"
|
||||
" tst.b (%a0)+\n"
|
||||
" bne su_search_loop\n"
|
||||
" dbf %d0,su_search_loop\n"
|
||||
"su_search_done:\n"
|
||||
" move.b (%a0)+,(%a1)+\n"
|
||||
" bne su_search_done\n"
|
||||
" subq.w #1,%a1\n"
|
||||
" move.l %d2,%a0\n"
|
||||
" moveq #0,%d0\n"
|
||||
" bra su_next\n"
|
||||
"su_quit:\n"
|
||||
" move.b %d0,(%a1)+\n"
|
||||
" move.l 8(%sp),%a0\n"
|
||||
" rts");
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
343
gtc/src/symbol.c
Normal file
343
gtc/src/symbol.c
Normal file
@ -0,0 +1,343 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* symbol handling (insertion & search)
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
#ifdef PCH
|
||||
#include "pch.h"
|
||||
#endif
|
||||
|
||||
#ifdef EXE_OUT
|
||||
#ifndef AS
|
||||
int exestub_mode CGLOB;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
HTABLE gsyms CGLOBL, gtags CGLOBL, lsyms CGLOBL, labsyms CGLOBL, ltags CGLOBL;
|
||||
|
||||
void concat(TABLE *dest,TABLE *src) {
|
||||
SYM *sp=src->tail,*sp2;
|
||||
while (sp) {
|
||||
sp2=(SYM *)xalloc((int)sizeof(SYM), _SYM+SYMBOL);
|
||||
*sp2=*sp;
|
||||
insert(sp2,(HTABLE *)dest);
|
||||
sp=sp->prev;
|
||||
}
|
||||
}
|
||||
|
||||
void hashinit(HTABLE *t) {
|
||||
t->hash=0x2489;
|
||||
memset(t->h,0,sizeof(t->h));
|
||||
}
|
||||
|
||||
void insert(SYM *sp,HTABLE *table) {
|
||||
/* if (!strcmp(sp->name,"wrong_calc"))
|
||||
uwarn("def!");*/
|
||||
if (!table->hash) {
|
||||
if (!search(sp->name,0,table)) {
|
||||
TABLE *tab=(TABLE *)table;
|
||||
if (!tab->head) {
|
||||
tab->head = tab->tail = sp;
|
||||
sp->prev = 0;
|
||||
sp->used = 0;
|
||||
} else {
|
||||
tab->tail->next = sp;
|
||||
sp->prev = tab->tail;
|
||||
tab->tail = sp;
|
||||
sp->used = 0;
|
||||
tab->tail = sp;
|
||||
}
|
||||
sp->next = 0;
|
||||
}
|
||||
else uerr(ERR_DUPSYM,sp->name);
|
||||
} else {
|
||||
int crc=crcN(sp->name);
|
||||
#ifdef EXE_OUT
|
||||
if (table==&defsyms && sp->name[0]=='E' && !strcmp(sp->name,"EXE_OUT"))
|
||||
exestub_mode=1;
|
||||
#endif
|
||||
if (!search(sp->name,crc,table)) {
|
||||
struct htab *tab=&table->h[crc];
|
||||
if (!tab->head) {
|
||||
tab->head = tab->tail = sp;
|
||||
sp->prev = 0;
|
||||
sp->used = 0;
|
||||
} else {
|
||||
tab->tail->next = sp;
|
||||
sp->prev = tab->tail;
|
||||
tab->tail = sp;
|
||||
sp->used = 0;
|
||||
tab->tail = sp;
|
||||
}
|
||||
sp->next = 0;
|
||||
}
|
||||
else uerr(ERR_DUPSYM,sp->name);
|
||||
}
|
||||
}
|
||||
|
||||
struct sym *symremove(char *na, HTABLE *tab) {
|
||||
SYM *ttail,**prv;
|
||||
struct htab *root;
|
||||
char *s1,*s2,c;
|
||||
if (!tab->hash)
|
||||
ierr(TABLE_HASH,2);
|
||||
#ifdef PC
|
||||
if (tab->hash!=0x2489)
|
||||
ierr(TABLE_HASH,1);
|
||||
#endif
|
||||
prv=&((root=&tab->h[crcN(na)])->tail);
|
||||
while ((ttail=*prv)) {
|
||||
s1 = ttail->name;
|
||||
s2 = na;
|
||||
while (*s1++==(c=*s2++)) {
|
||||
if (!c) {
|
||||
// *prv = ttail->prev;
|
||||
if (ttail->next) ttail->next->prev = ttail->prev;
|
||||
if (ttail->prev) ttail->prev->next = ttail->next;
|
||||
// ttail->next = prv;
|
||||
if (root->tail==ttail) root->tail=ttail->prev;
|
||||
if (root->head==ttail) root->head=ttail->next;
|
||||
/* if (!root->tail)
|
||||
root->head=0;*/
|
||||
return ttail;
|
||||
}
|
||||
}
|
||||
prv = &(ttail->prev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef PC
|
||||
int crcN(char *na) {
|
||||
unsigned long crc=-1; int n;
|
||||
unsigned char c;
|
||||
c=*na++;
|
||||
do {
|
||||
crc^=c;
|
||||
n=crc&7;
|
||||
crc=(crc>>n)+(crc<<(32-n));
|
||||
} while ((c=*na++));
|
||||
crc^=crc>>16;
|
||||
crc^=crc>>8;
|
||||
return crc & (N_HASH-1);
|
||||
}
|
||||
#else
|
||||
int crcN(char *na);
|
||||
asm("crcN:\n"
|
||||
" move.l 4(%sp),%a0\n"
|
||||
" moveq #-1,%d0\n"
|
||||
" move.b (%a0)+,%d1\n"
|
||||
"crcN_loop:\n"
|
||||
" eor.b %d1,%d0\n"
|
||||
" moveq #7,%d1\n"
|
||||
" and.w %d0,%d1\n"
|
||||
" ror.l %d1,%d0\n"
|
||||
" move.b (%a0)+,%d1\n"
|
||||
" bne crcN_loop\n"
|
||||
" move.w %d0,%d1\n"
|
||||
" swap %d0\n"
|
||||
" eor.w %d1,%d0\n"
|
||||
" move.w %d0,-(%sp)\n"
|
||||
" move.b (%sp)+,%d1\n"
|
||||
" eor.b %d1,%d0\n"
|
||||
" and.w #" N_HASH_AND ",%d0\n"
|
||||
" rts");
|
||||
#endif
|
||||
|
||||
/*#ifdef PC*/
|
||||
struct sym *search(char *na, int crc, HTABLE *tab) {
|
||||
char *s1,*s2,c;
|
||||
if (!tab->hash) {
|
||||
SYM *ttail=((TABLE *)tab)->tail;
|
||||
while (ttail) {
|
||||
s1 = ttail->name;
|
||||
s2 = na;
|
||||
while (*s1++==(c=*s2++)) {
|
||||
if (!c) return ttail;
|
||||
}
|
||||
ttail = ttail->prev;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
SYM *ttail;
|
||||
#ifdef PC
|
||||
if (tab->hash!=0x2489)
|
||||
ierr(TABLE_HASH,1);
|
||||
#endif
|
||||
if (crc<0) crc=crcN(na);
|
||||
ttail=tab->h[crc].tail;
|
||||
while (ttail) {
|
||||
s1 = ttail->name;
|
||||
s2 = na;
|
||||
while (*s1++==(c=*s2++)) {
|
||||
if (!c) return ttail;
|
||||
}
|
||||
ttail = ttail->prev;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*#else
|
||||
asm("search:
|
||||
move.l %a2,-(%sp)
|
||||
move.l 8(%sp),%d1
|
||||
move.l %d1,%a1
|
||||
tst.b (%a1)
|
||||
0: beq 0b
|
||||
move.l 12(%sp),%a0
|
||||
move.l %a0,%d0
|
||||
beq search_end
|
||||
search_lp:
|
||||
move.l (%a0)+,%a2
|
||||
move.l %d1,%a1
|
||||
cmpm.b (%a1)+,(%a2)+
|
||||
bne search_nxt
|
||||
search_lp2:
|
||||
move.b (%a1)+,%d0
|
||||
beq search_fnd
|
||||
cmp.b (%a2)+,%d0
|
||||
beq search_lp2
|
||||
search_nxt:
|
||||
move.l (%a0)+,%a0
|
||||
move.l %a0,%d0
|
||||
bne search_lp
|
||||
search_end:
|
||||
move.l (%sp)+,%a2
|
||||
rts
|
||||
search_fnd:
|
||||
tst.b (%a2)+
|
||||
bne search_nxt
|
||||
subq.l #4,%a0
|
||||
move.l (%sp)+,%a2
|
||||
rts");
|
||||
#endif*/
|
||||
|
||||
struct sym *gsearch(char *na,int crc) {
|
||||
struct sym *sp;
|
||||
if (!(sp = search(na, crc, &lsyms)))
|
||||
sp = search(na, crc, &gsyms);
|
||||
return sp;
|
||||
}
|
||||
|
||||
void append(struct sym **ptr_sp, HTABLE *table) {
|
||||
struct sym *sp1, *sp = *ptr_sp;
|
||||
if (table == &gsyms && (sp1 = search(sp->name, -1, table)) != 0) {
|
||||
/*
|
||||
* The global symbol table has only one level, this means that we
|
||||
* only check if the new declaration is compatible with the old one
|
||||
*/
|
||||
|
||||
if (!eq_type(sp->tp, sp1->tp))
|
||||
uerr(ERR_REDECL,sp->name);
|
||||
/*
|
||||
* The new storage class depends on the old and on the new one.
|
||||
*/
|
||||
if (sp->storage_class == sp1->storage_class) {
|
||||
if (sp->storage_class == sc_global) {
|
||||
/*
|
||||
* This hack sets sp->used to -1 so that decl.c knows to
|
||||
* suppress storage allocation
|
||||
*/
|
||||
uwarn("global redeclaration of '%s'", sp->name);
|
||||
sp1->used = -1;
|
||||
}
|
||||
*ptr_sp = sp1; /* caller uses old entry */
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* since we use compiler generated label for static data, we must
|
||||
* retain sc_static
|
||||
*/
|
||||
if (sp1->storage_class == sc_static) {
|
||||
*ptr_sp = sp1; /* caller uses old entry */
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* if the new storage class is global, we must update sp1 to generate
|
||||
* the .globl directive at the very end and perhaps the size (e.g.
|
||||
* for arrays)
|
||||
*/
|
||||
if (sp->storage_class == sc_global) {
|
||||
sp1->storage_class = sc_global;
|
||||
sp1->tp = sp->tp;
|
||||
*ptr_sp = sp1; /* caller uses old entry */
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* if the new storage class is static, set it to global (since we may
|
||||
* have used the ,real' name and cannot use compiler generated names
|
||||
* for this symbol from now on) and set sp->value.i to -1 to prevent
|
||||
* it from being exported via .globl directives
|
||||
*/
|
||||
if (sp->storage_class == sc_static) {
|
||||
sp1->storage_class = sc_global;
|
||||
sp1->value.i = -1;
|
||||
*ptr_sp = sp1; /* caller uses old entry */
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* last case: global declaration followed by external decl.: just do
|
||||
* nothing
|
||||
*/
|
||||
*ptr_sp = sp1; /* caller uses old entry */
|
||||
return;
|
||||
}
|
||||
/* if (table->head == 0) {
|
||||
// The table is empty so far...
|
||||
table->head = table->tail = sp;
|
||||
sp->next = sp->prev = 0;
|
||||
sp->used = 0;
|
||||
} else {
|
||||
table->tail->next = sp;
|
||||
sp->prev = table->tail;
|
||||
table->tail = sp;
|
||||
sp->next = 0;
|
||||
sp->used = 0;
|
||||
}*/
|
||||
if (!table->hash) {
|
||||
TABLE *tab=(TABLE *)table;
|
||||
if (!tab->head) {
|
||||
tab->head = tab->tail = sp;
|
||||
sp->prev = 0;
|
||||
sp->used = 0;
|
||||
} else {
|
||||
tab->tail->next = sp;
|
||||
sp->prev = tab->tail;
|
||||
tab->tail = sp;
|
||||
sp->used = 0;
|
||||
tab->tail = sp;
|
||||
}
|
||||
sp->next = 0;
|
||||
} else {
|
||||
struct htab *tab=&table->h[crcN(sp->name)];
|
||||
if (!tab->head) {
|
||||
tab->head = tab->tail = sp;
|
||||
sp->prev = 0;
|
||||
sp->used = 0;
|
||||
} else {
|
||||
tab->tail->next = sp;
|
||||
sp->prev = tab->tail;
|
||||
tab->tail = sp;
|
||||
sp->used = 0;
|
||||
tab->tail = sp;
|
||||
}
|
||||
sp->next = 0;
|
||||
}
|
||||
}
|
||||
// vim:ts=4:sw=4
|
||||
247
gtc/src/trees.c
Normal file
247
gtc/src/trees.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* GTools C compiler
|
||||
* =================
|
||||
* source file :
|
||||
* tree dumping
|
||||
*
|
||||
* Copyright 2001-2004 Paul Froissart.
|
||||
* Credits to Christoph van Wuellen and Matthew Brandt.
|
||||
* All commercial rights reserved.
|
||||
*
|
||||
* This compiler may be redistributed as long there is no
|
||||
* commercial interest. The compiler must not be redistributed
|
||||
* without its full sources. This notice must stay intact.
|
||||
*/
|
||||
|
||||
#include "define.h"
|
||||
_FILE(__FILE__)
|
||||
#include "c.h"
|
||||
#include "expr.h"
|
||||
#include "gen.h"
|
||||
#include "cglbdec.h"
|
||||
|
||||
typedef struct dump {
|
||||
} DUMP;
|
||||
char *dump_node_stack[MAX_DUMP_NODE_STACK];
|
||||
int dump_node_stack_depth;
|
||||
int dump_attribute_phase;
|
||||
|
||||
#define dump_put printf
|
||||
void dump_startline() {
|
||||
int i;
|
||||
for (i=0;i<dump_node_stack_depth;i++)
|
||||
dump_put(" ");
|
||||
}
|
||||
void dump_newnode(char *name) {
|
||||
if (dump_attribute_phase)
|
||||
dump_put(">\n");
|
||||
dump_startline();
|
||||
dump_put("<%s",name);
|
||||
dump_node_stack[dump_node_stack_depth++] = name;
|
||||
dump_attribute_phase = 1;
|
||||
}
|
||||
void dump_addstr(char *name,char *v) {
|
||||
assert(dump_attribute_phase);
|
||||
dump_put(" %s='%s'",name,v);
|
||||
}
|
||||
void dump_addint(char *name,int v) {
|
||||
char b[100];
|
||||
sprintf(b,"%d",v);
|
||||
dump_addstr(name,b);
|
||||
}
|
||||
void dump_addreg(char *name,int v) {
|
||||
assert(dump_attribute_phase);
|
||||
if (v>=RESULT && v<RESULT+8)
|
||||
dump_put(" %s='d%d'",name,v-RESULT);
|
||||
else if (v>=PRESULT && v<PRESULT+8)
|
||||
dump_put(" %s='a%d'",name,v-PRESULT);
|
||||
else if (v==FRAMEPTR)
|
||||
dump_put(" %s='fp'",name);
|
||||
else
|
||||
ierr(DUMP,3);
|
||||
}
|
||||
void dump_endnode() {
|
||||
dump_node_stack_depth--;
|
||||
if (dump_attribute_phase)
|
||||
dump_put(" />\n");
|
||||
else
|
||||
dump_startline(), dump_put("</%s>",dump_node_stack[dump_node_stack_depth]);
|
||||
dump_attribute_phase = 0;
|
||||
}
|
||||
|
||||
void dump_genstmt(struct snode *stmt) {
|
||||
while (stmt != 0) {
|
||||
switch (stmt->type) {
|
||||
case st_compound:
|
||||
dump_genstmt(stmt->s1);
|
||||
break;
|
||||
case st_label:
|
||||
dump_newnode("st_label");
|
||||
dump_addint("id",stmt->v2.i);
|
||||
dump_endnode();
|
||||
dump_genstmt(stmt->s1);
|
||||
break;
|
||||
case st_goto:
|
||||
dump_newnode("st_goto");
|
||||
dump_addint("id",stmt->v2.i);
|
||||
dump_endnode();
|
||||
break;
|
||||
case st_break:
|
||||
dump_newnode("st_break");
|
||||
dump_endnode();
|
||||
break;
|
||||
case st_continue:
|
||||
dump_newnode("st_continue");
|
||||
dump_endnode();
|
||||
break;
|
||||
case st_expr:
|
||||
dump_newnode("st_expr");
|
||||
dump_expr(stmt->exp);
|
||||
dump_endnode();
|
||||
break;
|
||||
case st_return:
|
||||
if (!stmt->exp || ret_type->type==bt_void) {
|
||||
dump_newnode("st_return");
|
||||
dump_endnode();
|
||||
break;
|
||||
}
|
||||
switch (ret_type->type) {
|
||||
case bt_struct:
|
||||
case bt_union:
|
||||
#ifdef BCDFLT
|
||||
case bt_float:
|
||||
#ifdef DOUBLE
|
||||
case bt_double:
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SHORT_STRUCT_PASSING
|
||||
if (ret_type->size<=4) {
|
||||
if (stmt->exp->nodetype!=en_ref)
|
||||
ierr(DUMP,1);
|
||||
dump_newnode("st_return");
|
||||
dump_newnode("expr");
|
||||
dump_addreg("target",mk_reg(RESULT));
|
||||
dump_newnode("e_deref");
|
||||
dump_addint("esize",ret_type->size);
|
||||
dump_expr(stmt->exp->v.p[0]);
|
||||
dump_endnode();
|
||||
dump_endnode();
|
||||
dump_endnode();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
assert(0);
|
||||
dump_newnode("st_return");
|
||||
dump_newnode("expr");
|
||||
dump_addstr("target","__tmp_structreturn");
|
||||
dump_expr(stmt->exp);
|
||||
dump_newnode("");
|
||||
dump_newnode("");
|
||||
break;
|
||||
#ifndef BCDFLT
|
||||
case bt_float:
|
||||
#ifdef DOUBLE
|
||||
case bt_double:
|
||||
#endif
|
||||
#endif
|
||||
case bt_char: case bt_uchar:
|
||||
case bt_short: case bt_ushort:
|
||||
case bt_long: case bt_ulong:
|
||||
case bt_pointer:
|
||||
dump_newnode("st_return");
|
||||
dump_newnode("expr");
|
||||
dump_addreg("target",ret_type->type==bt_pointer?mk_reg(PRESULT):mk_reg(RESULT));
|
||||
dump_expr(stmt->exp);
|
||||
dump_endnode();
|
||||
dump_endnode();
|
||||
break;
|
||||
default:
|
||||
ierr(DUMP,1);
|
||||
}
|
||||
break;
|
||||
case st_if:
|
||||
dump_newnode("st_if");
|
||||
dump_newnode("condition");
|
||||
dump_expr(stmt->exp);
|
||||
dump_endnode();
|
||||
dump_newnode("true");
|
||||
dump_genstmt(stmt->s1);
|
||||
dump_endnode();
|
||||
dump_newnode("false");
|
||||
dump_genstmt(stmt->v1.s);
|
||||
dump_endnode();
|
||||
dump_endnode();
|
||||
break;
|
||||
case st_asm:
|
||||
dump_newnode("st_asm");
|
||||
dump_newnode("TODO");
|
||||
//dump_asm((struct ocode *)stmt->v1.i);
|
||||
dump_endnode();
|
||||
dump_endnode();
|
||||
break;
|
||||
case st_while:
|
||||
dump_newnode("st_while");
|
||||
if (stmt->exp) {
|
||||
dump_newnode("condition");
|
||||
dump_expr(stmt->exp);
|
||||
dump_endnode();
|
||||
}
|
||||
dump_newnode("body");
|
||||
dump_genstmt(stmt->s1);
|
||||
dump_newnode("st_labelcontinue");
|
||||
dump_endnode();
|
||||
dump_endnode();
|
||||
dump_endnode();
|
||||
break;
|
||||
case st_do:
|
||||
dump_newnode(stmt->exp ? "st_do" : "st_while");
|
||||
dump_newnode("body");
|
||||
dump_genstmt(stmt->s1);
|
||||
dump_endnode();
|
||||
if (stmt->exp) {
|
||||
dump_newnode("condition");
|
||||
dump_expr(stmt->exp);
|
||||
dump_endnode();
|
||||
}
|
||||
dump_endnode();
|
||||
break;
|
||||
case st_for:
|
||||
if (stmt->exp) {
|
||||
dump_newnode("st_expr");
|
||||
dump_expr(stmt->exp);
|
||||
dump_endnode();
|
||||
}
|
||||
dump_newnode("st_while");
|
||||
dump_newnode("condition");
|
||||
dump_expr(stmt->v1.e);
|
||||
dump_endnode();
|
||||
dump_newnode("body");
|
||||
dump_genstmt(stmt->s1);
|
||||
if (stmt->v2.e) {
|
||||
dump_newnode("st_expr");
|
||||
dump_expr(stmt->v2.e);
|
||||
dump_endnode();
|
||||
}
|
||||
dump_endnode();
|
||||
dump_endnode();
|
||||
break;
|
||||
case st_switch:
|
||||
default:
|
||||
ierr(DUMP,2);
|
||||
}
|
||||
stmt = stmt->next;
|
||||
}
|
||||
}
|
||||
|
||||
void dump_genfunc(struct snode *stmt) {
|
||||
opt1(stmt);
|
||||
dump_newnode("function");
|
||||
dump_newnode("returns");
|
||||
dump_type(ret_type);
|
||||
dump_endnode();
|
||||
dump_newnode("code");
|
||||
dump_genstmt(stmt);
|
||||
dump_genreturn(NIL_SNODE);
|
||||
dump_endnode();
|
||||
dump_endnode();
|
||||
}
|
||||
98
gtc/src/vcg.c
Normal file
98
gtc/src/vcg.c
Normal file
@ -0,0 +1,98 @@
|
||||
#ifdef VCG
|
||||
#ifdef PC
|
||||
#define MAXINT 0x7FFFFFFF
|
||||
#endif
|
||||
#ifndef __HAVE_STACK_IMAGE
|
||||
#define __HAVE_STACK_IMAGE
|
||||
typedef struct _stackimg {
|
||||
int next_data,next_addr;
|
||||
#ifndef INFINITE_REGISTERS
|
||||
int reg_alloc_ptr,reg_stack_ptr;
|
||||
char dreg_in_use[MAX_DATA+1];
|
||||
char areg_in_use[MAX_ADDR+1];
|
||||
struct reg_struct reg_stack[MAX_REG_STACK+1],reg_alloc[MAX_REG_STACK+1];
|
||||
int act_scratch;
|
||||
#endif
|
||||
} STACK_IMAGE;
|
||||
#endif
|
||||
STACK_IMAGE vcg_img[VCG_MAX+1];
|
||||
int vcg_nxl[VCG_MAX+1];
|
||||
int vcg_aborted[VCG_MAX+1];
|
||||
int vcg_init() {
|
||||
if (--vcg_lvl<0) {
|
||||
vcg_lvl++;
|
||||
return 0;
|
||||
}
|
||||
// tmp_use();
|
||||
usestack(&vcg_img[vcg_lvl]);
|
||||
vcg_peep_head[vcg_lvl]=0;
|
||||
vcg_aborted[vcg_lvl]=0;
|
||||
vcg_nxl[vcg_lvl]=nextlabel;
|
||||
g_code(op_label,0,0,0);
|
||||
return 1;
|
||||
// vcg_on++;
|
||||
// vcg_cost[vcg_lvl]=0;
|
||||
}
|
||||
int en_dir_cost(struct enode *ep) {
|
||||
switch (ep->nodetype) {
|
||||
case en_icon:
|
||||
return (ep->v.i>=-32768 && ep->v.i<32767)?1:2;
|
||||
case en_labcon:
|
||||
case en_nacon:
|
||||
return 1;
|
||||
case en_add:
|
||||
case en_sub:
|
||||
return max(en_dir_cost(ep->v.p[0]),en_dir_cost(ep->v.p[1]));
|
||||
}
|
||||
}
|
||||
int cost_tab[] = {
|
||||
0,0,0,0,0,1,1,1,-MAXINT-1,2,1,1,1,1,2,0,0
|
||||
};
|
||||
int vcg_cost() {
|
||||
int cost=0;
|
||||
if (!vcg_aborted[vcg_lvl]) {
|
||||
struct ocode *ip;
|
||||
opt3();
|
||||
ip = peep_head;
|
||||
while (ip != 0) {
|
||||
#define am_cost(x) (x?(x->mode==am_direct?en_dir_cost(x->offset):cost_tab[x->mode]):0)
|
||||
cost++;
|
||||
switch (ip->opcode) {
|
||||
case op_label:
|
||||
case op_even:
|
||||
cost--;
|
||||
break;
|
||||
case op_moveq:
|
||||
case op_addq: case op_subq:
|
||||
case op_lsl: case op_lsr: case op_asl: case op_asr:
|
||||
case op_rol: case op_ror: case op_roxl: case op_roxr:
|
||||
case op_trap:
|
||||
cost+=am_cost(ip->oper2);
|
||||
break;
|
||||
case op_bxx:
|
||||
/* what should we do here? */
|
||||
break;
|
||||
case op_dbxx:
|
||||
cost++;
|
||||
break;
|
||||
default:
|
||||
cost+=am_cost(ip->oper1)+am_cost(ip->oper2);
|
||||
break;
|
||||
}
|
||||
if (cost<0) cost+=(-MAXINT-1)+((ip->length+1)>>1);
|
||||
ip = ip->fwd;
|
||||
}
|
||||
// vcg_on--;
|
||||
// tmp_free();
|
||||
} else cost=12345;
|
||||
return cost;
|
||||
}
|
||||
int vcg_done() {
|
||||
freestack(&vcg_img[vcg_lvl]);
|
||||
nextlabel=vcg_nxl[vcg_lvl];
|
||||
int cost=vcg_cost();
|
||||
vcg_lvl++;
|
||||
return cost;
|
||||
}
|
||||
#endif
|
||||
// vim:ts=4:sw=4
|
||||
8
gtc/src/version.h
Normal file
8
gtc/src/version.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef VERSION_H_
|
||||
#define VERSION_H_
|
||||
|
||||
#define GTC_MAJOR 0
|
||||
#define GTC_MINOR 902
|
||||
#define GTC_VERSION "0.90.2"
|
||||
|
||||
#endif
|
||||
24
h/Makefile
Normal file
24
h/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
BIN=../bin
|
||||
STRIP = perl script/strip.pl
|
||||
TXT89 = $(BIN)/txt89t
|
||||
|
||||
all: src/*.h
|
||||
$(RM) *.89t
|
||||
$(RM) processed/*.89t
|
||||
$(RM) -r stripped
|
||||
mkdir stripped
|
||||
sh -c 'for f in src/*.h; do $(STRIP) "$$f" > "stripped/$${f#src/}"; done'
|
||||
$(TXT89) --compact -f gtchdr stripped/*.h
|
||||
mv *.89t processed
|
||||
$(RM) -r stripped
|
||||
touch all
|
||||
|
||||
clean:
|
||||
distclean: clean
|
||||
scratchclean: distclean
|
||||
$(RM) processed/*.89t all
|
||||
|
||||
include ../config.mk
|
||||
install: all
|
||||
mkdir -p $(prefix)/share/gtc/include
|
||||
install -m 644 src/*.h $(prefix)/share/gtc/include
|
||||
1
h/legacy/README
Normal file
1
h/legacy/README
Normal file
@ -0,0 +1 @@
|
||||
These files are deprecated, but I'm leaving them here for reference purposes.
|
||||
67
h/legacy/ezgen
Normal file
67
h/legacy/ezgen
Normal file
@ -0,0 +1,67 @@
|
||||
#include "inclgen"
|
||||
#include "genle"
|
||||
#ifdef RESOURCE
|
||||
FILE *resf=0;
|
||||
#ifdef RES_TYPE
|
||||
RES_TYPE *data=0;
|
||||
#else
|
||||
void *data=0;
|
||||
#endif
|
||||
#endif
|
||||
DSCREEN *scr1=0,*scr2=0,*sc=0;
|
||||
#ifdef DISP_SCR
|
||||
DSCREEN *sd=0;
|
||||
#endif
|
||||
|
||||
int curscr=0;
|
||||
void gl_main();
|
||||
void gl_upd() {
|
||||
if (!curscr) {
|
||||
gl_set_dscreen_int(
|
||||
#ifdef DISP_SCR
|
||||
sd=
|
||||
#endif
|
||||
scr1);
|
||||
gl_set_dscreen_function(sc=scr2);
|
||||
} else {
|
||||
gl_set_dscreen_int(
|
||||
#ifdef DISP_SCR
|
||||
sd=
|
||||
#endif
|
||||
scr2);
|
||||
gl_set_dscreen_function(sc=scr1);
|
||||
}
|
||||
curscr=~curscr;
|
||||
}
|
||||
int gl_load() {
|
||||
int hd;
|
||||
gl_init();
|
||||
gl_init_dscreen(&scr1, &hd);
|
||||
if (!hd) goto nohd;
|
||||
gl_push_hd(hd);
|
||||
gl_init_dscreen(&scr2, &hd);
|
||||
if (!hd) goto nohd;
|
||||
gl_push_hd(hd);
|
||||
gl_upd();
|
||||
#ifdef RESOURCE
|
||||
resf=fopen(RESOURCE,"rb");
|
||||
if (!resf) goto nohd;
|
||||
(void *)data=*(void **)resf;
|
||||
#ifdef GFX_RES
|
||||
gl_set_spr_xy(0,0);
|
||||
gl_set_spr_tile(data);
|
||||
#endif
|
||||
#endif
|
||||
return 1;
|
||||
nohd:
|
||||
return 0;
|
||||
}
|
||||
void _main() {
|
||||
if (gl_load()) gl_main();
|
||||
#ifdef RESOURCE
|
||||
if (resf) fclose(resf);
|
||||
#endif
|
||||
gl_wait_no_key();
|
||||
gl_free_hd();
|
||||
gl_quit();
|
||||
}
|
||||
42
h/legacy/ezgensc
Normal file
42
h/legacy/ezgensc
Normal file
@ -0,0 +1,42 @@
|
||||
#include "inclgen"
|
||||
#include "genle"
|
||||
#include "sccomm"
|
||||
#include "scliba"
|
||||
#ifdef RESOURCE
|
||||
FILE *resf;
|
||||
#endif
|
||||
|
||||
void gl_main();
|
||||
int gl_load() {
|
||||
GLB
|
||||
int hd;
|
||||
gl_init();
|
||||
gl_init_dscreen(&g scr1, &hd);
|
||||
if (!hd) goto nohd;
|
||||
gl_push_hd(hd);
|
||||
gl_init_dscreen(&g scr2, &hd);
|
||||
if (!hd) goto nohd;
|
||||
gl_push_hd(hd);
|
||||
gl_upd();
|
||||
#ifdef RESOURCE
|
||||
resf=fopen(RESOURCE,"rb");
|
||||
if (!resf) goto nohd;
|
||||
(void *)g data=*(void **)resf;
|
||||
#ifdef GFX_RES
|
||||
gl_set_spr_xy(0,0);
|
||||
gl_set_spr_tile(g data);
|
||||
#endif
|
||||
#endif
|
||||
return 1;
|
||||
nohd:
|
||||
return 0;
|
||||
}
|
||||
void _main() {
|
||||
if (gl_load()) gl_main();
|
||||
#ifdef RESOURCE
|
||||
if (resf) fclose(resf);
|
||||
#endif
|
||||
gl_wait_no_key();
|
||||
gl_free_hd();
|
||||
gl_quit();
|
||||
}
|
||||
1
h/legacy/genle
Normal file
1
h/legacy/genle
Normal file
@ -0,0 +1 @@
|
||||
#include <gen.h>
|
||||
4
h/legacy/inclgen
Normal file
4
h/legacy/inclgen
Normal file
@ -0,0 +1,4 @@
|
||||
#define USE_KERNEL
|
||||
#include <tigcclib.h>
|
||||
#define X 160
|
||||
#define Y 100
|
||||
1
h/legacy/include
Normal file
1
h/legacy/include
Normal file
@ -0,0 +1 @@
|
||||
#include <tigcclib.h>
|
||||
340
h/processed/COPYING
Normal file
340
h/processed/COPYING
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
BIN
h/processed/assert.89t
Normal file
BIN
h/processed/assert.89t
Normal file
Binary file not shown.
BIN
h/processed/compat.89t
Normal file
BIN
h/processed/compat.89t
Normal file
Binary file not shown.
BIN
h/processed/default.89t
Normal file
BIN
h/processed/default.89t
Normal file
Binary file not shown.
BIN
h/processed/doors.89t
Normal file
BIN
h/processed/doors.89t
Normal file
Binary file not shown.
BIN
h/processed/extgraph.89t
Normal file
BIN
h/processed/extgraph.89t
Normal file
Binary file not shown.
BIN
h/processed/gen.89t
Normal file
BIN
h/processed/gen.89t
Normal file
Binary file not shown.
BIN
h/processed/nostub.89t
Normal file
BIN
h/processed/nostub.89t
Normal file
Binary file not shown.
BIN
h/processed/patch.89t
Normal file
BIN
h/processed/patch.89t
Normal file
Binary file not shown.
BIN
h/processed/std.89t
Normal file
BIN
h/processed/std.89t
Normal file
Binary file not shown.
BIN
h/processed/tigcclib.89t
Normal file
BIN
h/processed/tigcclib.89t
Normal file
Binary file not shown.
BIN
h/processed/ttunpack.89t
Normal file
BIN
h/processed/ttunpack.89t
Normal file
Binary file not shown.
BIN
h/processed/xupak.89t
Normal file
BIN
h/processed/xupak.89t
Normal file
Binary file not shown.
31
h/script/strip.pl
Normal file
31
h/script/strip.pl
Normal file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
my $multicomment=0;
|
||||
|
||||
while (<>) {
|
||||
chomp;
|
||||
if (!$multicomment) {
|
||||
s|//.*$| |g;
|
||||
s|/\*.*?\*/| |g;
|
||||
if (m|/\*|) {
|
||||
s|/\*.*$| |g;
|
||||
$multicomment=1;
|
||||
}
|
||||
} elsif (m|\*/|) {
|
||||
s|^.*?\*/| |g;
|
||||
$multicomment=0;
|
||||
} else {
|
||||
$_='';
|
||||
}
|
||||
s|^\s+||g;
|
||||
s|\s+$||g;
|
||||
s|\s+| |g;
|
||||
s|^(\#define \w+) |\1\t|g;
|
||||
s|(\W) (.)|\1\2|g;
|
||||
s|(.) (\W)|\1\2|g;
|
||||
s:(?<!\w)0x([A-Fa-f0-9]{1,5})(?!(\#|\d)):hex($1):ge;
|
||||
while (s:(?<!\w)(\d+)\*(\d+)(?!(\#|\d)):$1*$2:ge) {}
|
||||
s|\t| |g;
|
||||
$_.="\n" if $_;
|
||||
print;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user