and E cvs did givbe birth to an Embryo! :)

SVN revision: 9445
This commit is contained in:
Carsten Haitzler 2004-03-24 09:48:28 +00:00
parent 04ac65be8f
commit 7b4b36e5d2
53 changed files with 18995 additions and 0 deletions

2
legacy/embryo/AUTHORS Normal file
View File

@ -0,0 +1,2 @@
The Rasterman (Carsten Haitzler) <raster@rasterman.com>

28
legacy/embryo/COPYING Normal file
View File

@ -0,0 +1,28 @@
Copyright (C) 2000 Carsten Haitzler and various contributors (see AUTHORS)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies of the Software and its Copyright notices. In addition publicly
documented acknowledgment must be given that this software has been used if no
source code of this software is made available publicly. This includes
acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
documents or any documentation provided with any product containing this
software. This License does not apply to any software that links to the
libraries provided by this software (statically or dynamically), but only to
the software provided.
Please see the COPYING.PLAIN for a plain-english explanation of this notice
and it's intent.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,33 @@
Plain English Copyright Notice
This file is not intended to be the actual License. The reason this file
exists is that we here are programmers and engineers. We aren't lawyers. We
provide licenses that we THINK say the right things, but we have our own
intentions at heart. This is a plain-english explanation of what those
intentions are, and if you follow them you will be within the "spirit" of
the license.
The intent is for us to enjoy writing software that is useful to us (the
AUTHORS) and allow others to use it freely and also benefit from the work we
put into making it. We don't want to restrict others using it. They should
not *HAVE* to make the source code of the applications they write that
simply link to these libraries (be that statically or dynamically), or for
them to be limited as to what license they choose to use (be it open, closed
or anything else). But we would like to know you are using these libraries.
We simply would like to know that it has been useful to someone. This is why
we ask for acknowledgement of some sort.
You can do what you want with the source of this software - it doesn't
matter. We still have it here for ourselves and it is open and free to use
and download and play with. It can't be taken away. We don't really mind what
you do with the source to your software. We would simply like to know that
you are using it - especially if it makes it to a commerical product. If you
simply e-mail all the AUTHORS (see COPYING and AUTHORS files) telling us, and
then make sure you include a paragraph or page in the manual for the product
with the copyright notice and state that you used this software, we will be
very happy. If you want to contribute back modifications and fixes you may have
made we will welcome those too with open arms (generally). If you want help
with changes needed, ports needed or features to be added, arrangements can
be easily made with some dialogue.
Carsten Haitzler <raster@rasterman.com>

0
legacy/embryo/ChangeLog Normal file
View File

145
legacy/embryo/Doxyfile Normal file
View File

@ -0,0 +1,145 @@
PROJECT_NAME = Embryo
PROJECT_NUMBER =
OUTPUT_DIRECTORY = doc
INPUT = embryo.c
IMAGE_PATH = doc/img
OUTPUT_LANGUAGE = English
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER = doc/head.html
HTML_FOOTER = doc/foot.html
HTML_STYLESHEET = doc/embryo.css
HTML_ALIGN_MEMBERS = YES
ENUM_VALUES_PER_LINE = 1
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = NO
HIDE_UNDOC_MEMBERS = YES
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = YES
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
INTERNAL_DOCS = NO
STRIP_CODE_COMMENTS = YES
CASE_SENSE_NAMES = YES
SHORT_NAMES = NO
HIDE_SCOPE_NAMES = NO
VERBATIM_HEADERS = NO
SHOW_INCLUDE_FILES = NO
JAVADOC_AUTOBRIEF = YES
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 2
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ALIASES =
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
SHOW_USED_FILES = NO
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
FILE_PATTERNS =
RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
INPUT_FILTER =
FILTER_SOURCE_FILES = NO
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 2
IGNORE_PREFIX =
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
GENERATE_MAN = YES
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = YES
GENERATE_XML = NO
XML_SCHEMA =
XML_DTD =
GENERATE_AUTOGEN_DEF = NO
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = NO
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
CLASS_DIAGRAMS = NO
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
CLASS_GRAPH = NO
COLLABORATION_GRAPH = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = NO
INCLUDED_BY_GRAPH = NO
GRAPHICAL_HIERARCHY = NO
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 512
MAX_DOT_GRAPH_HEIGHT = 512
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
SEARCHENGINE = NO
CGI_NAME = search.cgi
CGI_URL =
DOC_URL =
DOC_ABSPATH =
BIN_ABSPATH = /usr/bin/
EXT_DOC_PATHS =

14
legacy/embryo/INSTALL Normal file
View File

@ -0,0 +1,14 @@
COMPILING and INSTALLING:
If you got a official release tar archive do:
./configure
( otherwise if you got this from enlightenment cvs do: ./autogen.sh )
Then to compile:
make
To install (run this as root, or the user who handles installs):
make install
NOTE: You MUST make install Embryo for it to run properly.

24
legacy/embryo/Makefile.am Normal file
View File

@ -0,0 +1,24 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = src
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess \
config.h.in config.sub configure install-sh \
ltconfig ltmain.sh missing mkinstalldirs \
stamp-h.in embryo_docs.tar embryo_docs.tar.gz embryo.c
dist-hook:
./gendoc; \
tar cvf embryo_docs.tar doc/html doc/latex doc/man; \
rm -f embryo_docs.tar.gz; \
gzip -9 embryo_docs.tar;
bin_SCRIPTS = embryo-config
EXTRA_DIST = README AUTHORS COPYING COPYING-PLAIN embryo.spec embryo.c.in \
gendoc Doxyfile embryo_docs.tar.gz embryo.pc.in \
make_cross_compile_arm.sh
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = embryo.pc

0
legacy/embryo/NEWS Normal file
View File

1
legacy/embryo/README Normal file
View File

@ -0,0 +1 @@
Embryo 0.0.1

137
legacy/embryo/autogen.sh Executable file
View File

@ -0,0 +1,137 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
PKG_NAME="the package."
DIE=0
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`autoconf' installed to."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
(grep "^AM_PROG_LIBTOOL" $srcdir/configure.in >/dev/null) && {
(libtool --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`libtool' installed."
echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2d.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
}
grep "^AM_GNU_GETTEXT" $srcdir/configure.in >/dev/null && {
grep "sed.*POTFILES" $srcdir/configure.in >/dev/null || \
(gettext --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`gettext' installed."
echo "Get ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
}
(automake --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`automake' installed."
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
NO_AUTOMAKE=yes
}
# if no automake, don't bother testing for aclocal
test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: Missing \`aclocal'. The version of \`automake'"
echo "installed doesn't appear recent enough."
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
if test "$DIE" -eq 1; then
exit 1
fi
if test -z "$*"; then
echo "**Warning**: I am going to run \`configure' with no arguments."
echo "If you wish to pass any to it, please specify them on the"
echo \`$0\'" command line."
echo
fi
case $CC in
xlc )
am_opt=--include-deps;;
esac
for coin in `find $srcdir -name configure.in -print`
do
dr=`dirname $coin`
if test -f $dr/NO-AUTO-GEN; then
echo skipping $dr -- flagged as no auto-gen
else
echo processing $dr
macrodirs=`sed -n -e 's,AM_ACLOCAL_INCLUDE(\(.*\)),\1,gp' < $coin`
( cd $dr
aclocalinclude="$ACLOCAL_FLAGS"
for k in $macrodirs; do
if test -d $k; then
aclocalinclude="$aclocalinclude -I $k"
##else
## echo "**Warning**: No such directory \`$k'. Ignored."
fi
done
if grep "^AM_GNU_GETTEXT" configure.in >/dev/null; then
if grep "sed.*POTFILES" configure.in >/dev/null; then
: do nothing -- we still have an old unmodified configure.in
else
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running gettextize... Ignore non-fatal messages."
echo "no" | gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
fi
if grep "^AM_GNOME_GETTEXT" configure.in >/dev/null; then
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running gettextize... Ignore non-fatal messages."
echo "no" | gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then
echo "Running libtoolize..."
libtoolize --force --copy
fi
echo "Running aclocal $aclocalinclude ..."
aclocal $aclocalinclude
if grep "^AM_CONFIG_HEADER" configure.in >/dev/null; then
echo "Running autoheader..."
autoheader
fi
echo "Running automake --gnu $am_opt ..."
automake --add-missing --gnu $am_opt
echo "Running autoconf ..."
autoconf
)
fi
done
#conf_flags="--enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c
if test x$NOCONFIGURE = x; then
echo Running $srcdir/configure $conf_flags "$@" ...
$srcdir/configure $conf_flags "$@" \
&& echo Now type \`make\' to compile $PKG_NAME
else
echo Skipping configure process.
fi

View File

@ -0,0 +1,85 @@
dnl Process this file with autoconf to produce a configure script.
# get rid of that stupid cache mechanism
rm -f config.cache
AC_INIT(configure.in)
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
AC_ISC_POSIX
AM_INIT_AUTOMAKE(embryo, 0.0.1)
AM_CONFIG_HEADER(config.h)
AC_PROG_CC
AM_PROG_CC_STDC
AC_HEADER_STDC
AC_C_CONST
AM_ENABLE_SHARED
AM_PROG_LIBTOOL
if test "x${exec_prefix}" = "xNONE"; then
if test "x${prefix}" = "xNONE"; then
bindir="${ac_default_prefix}/bin";
else
bindir="${prefix}/bin";
fi
else
if test "x${prefix}" = "xNONE"; then
bindir="${ac_default_prefix}/bin";
else
bindir="${prefix}/bin";
fi
fi
if test "x${exec_prefix}" = "xNONE"; then
if test "x${prefix}" = "xNONE"; then
libdir="${ac_default_prefix}/lib";
else
libdir="${prefix}/lib";
fi
else
if test "x${prefix}" = "xNONE"; then
libdir="${ac_default_prefix}/lib";
else
libdir="${prefix}/lib";
fi
fi
dnl Set PACKAGE_BIN_DIR in config.h.
if test "x${bindir}" = 'xNONE'; then
if test "x${prefix}" = "xNONE"; then
AC_DEFINE_UNQUOTED(PACKAGE_BIN_DIR, "${ac_default_prefix}/bin", [Installation directory for user executables])
else
AC_DEFINE_UNQUOTED(PACKAGE_BIN_DIR, "${prefix}/bin", [Installation directory for user executables])
fi
else
AC_DEFINE_UNQUOTED(PACKAGE_BIN_DIR, "${bindir}", [Installation directory for user executables])
fi
dnl Set PACKAGE_LIB_DIR in config.h.
if test "x${libdir}" = 'xNONE'; then
if test "x${prefix}" = "xNONE"; then
AC_DEFINE_UNQUOTED(PACKAGE_LIB_DIR, "${ac_default_prefix}/lib", [Installation directory for libraries] )
else
AC_DEFINE_UNQUOTED(PACKAGE_LIB_DIR, "${prefix}/lib", [Installation directory for libraries])
fi
else
AC_DEFINE_UNQUOTED(PACKAGE_LIB_DIR, "${libdir}", [Installation directory for libraries])
fi
dnl Set PACKAGE_SOURCE_DIR in config.h.
packagesrcdir=`cd $srcdir && pwd`
AC_DEFINE_UNQUOTED(PACKAGE_SOURCE_DIR, "${packagesrcdir}", [Source code directory])
AC_OUTPUT([
Makefile
embryo.pc
src/Makefile
src/lib/Makefile
src/bin/Makefile
embryo-config
],[
chmod +x embryo-config
touch embryo_docs.tar.gz
])

View File

@ -0,0 +1,178 @@
td.md {
background-color: #ffffff;
font-family: monospace;
text-align: left;
vertical-align: center;
font-size: 10;
padding-right : 1px;
padding-top : 1px;
padding-left : 1px;
padding-bottom : 1px;
margin-left : 1px;
margin-right : 1px;
margin-top : 1px;
margin-bottom : 1px
}
td.mdname {
font-family: monospace;
text-align: left;
vertical-align: center;
font-size: 10;
padding-right : 1px;
padding-top : 1px;
padding-left : 1px;
padding-bottom : 1px;
margin-left : 1px;
margin-right : 1px;
margin-top : 1px;
margin-bottom : 1px
}
h1
{
text-align: center;
color: #333333
}
h2
{
text-align: left;
color: #333333
}
h3
{
text-align: left;
color: #333333
}
a:link
{
text-decoration: none;
color: #444444;
font-weight: bold;
}
a:visited
{
text-decoration: none;
color: #666666;
font-weight: bold;
}
a:hover
{
text-decoration: none;
color: #000000;
font-weight: bold;
}
a.nav:link
{
text-decoration: none;
color: #444444;
font-weight: normal;
}
a.nav:visited
{
text-decoration: none;
color: #666666;
font-weight: normal;
}
a.nav:hover
{
text-decoration: none;
color: #000000;
font-weight: normal;
}
a.qindex:link
{
text-decoration: none;
color: #444444;
font-weight: normal;
}
a.qindex:visited
{
text-decoration: none;
color: #666666;
font-weight: normal;
}
a.qindex:hover
{
text-decoration: none;
color: #000000;
font-weight: normal;
}
p
{
color: #000000;
font-family: sans-serif;
font-size: 10;
}
body {
background-image: url("hilite.png");
background-repeat: no-repeat;
background-position: left top;
background-color: #dddddd;
color: #000000;
font-family: sans-serif;
padding: 8px;
margin: 0;
}
div.fragment
{
background-image: url("hilite.png");
background-repeat: no-repeat;
background-position: left top;
border: thin solid #888888;
background-color: #eeeeee;
padding: 4px;
text-align: left;
vertical-align: center;
font-size: 12;
}
hr
{
border: 0;
background-color: #000000;
width: 80%;
height: 1;
}
dl
{
background-image: url("hilite.png");
background-repeat: no-repeat;
background-position: left top;
border: thin solid #aaaaaa;
background-color: #eeeeee;
padding: 4px;
text-align: left;
vertical-align: center;
font-size: 12;
}
em
{
color: #334466;
font-family: courier;
font-size: 10;
font-style: normal;
}
div.nav
{
border: thin solid #000000;
background-color: #ffffff;
padding: 1px;
text-align: center;
vertical-align: center;
font-size: 12;
}
div.body
{
border: thin solid #000000;
background-color: #ffffff;
padding: 4px;
text-align: left;
font-size: 10;
}
div.diag
{
border: thin solid #888888;
background-color: #eeeeee;
padding: 4px;
text-align: center;
font-size: 8;
}

View File

@ -0,0 +1,2 @@
</body>
</html>

View File

@ -0,0 +1,19 @@
<html>
<head>
<title>$title</title>
<link href=embryo.css rel=stylesheet type=text/css>
</head>
<body>
<div class=nav>
<table border=0 align=center><tr>
<td width=16><img src=embryo_mini.png width=16 height=16 alt=E></td>
<td width=100% align=center>
E : M : B : R : Y : O
</td>
<td width=16><img src=embryo_mini.png width=16 height=16 alt=E></td>
</tr></table>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -0,0 +1,59 @@
#!/bin/sh
prefix=@prefix@
exec_prefix=@exec_prefix@
exec_prefix_set=no
usage="\
Usage: embryo-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]"
if test $# -eq 0; then
echo "${usage}" 1>&2
exit 1
fi
while test $# -gt 0; do
case "$1" in
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) optarg= ;;
esac
case $1 in
--prefix=*)
prefix=$optarg
if test $exec_prefix_set = no ; then
exec_prefix=$optarg
fi
;;
--prefix)
echo $prefix
;;
--exec-prefix=*)
exec_prefix=$optarg
exec_prefix_set=yes
;;
--exec-prefix)
echo $exec_prefix
;;
--version)
echo @VERSION@
;;
--cflags)
if test @includedir@ != /usr/include ; then
includes=-I@includedir@
fi
echo $includes
;;
--libs)
libdirs=-L@libdir@
echo $libdirs -lembryo -lm
;;
*)
echo "${usage}" 1>&2
exit 1
;;
esac
shift
done
exit 0

30
legacy/embryo/embryo.c.in Normal file
View File

@ -0,0 +1,30 @@
/**
@file
@brief Embryo virtual machine library & compiler
These routines are used for Embryo library interaction
*/
/**
@mainpage Embryo Library Documentation
@image html embryo.png
@version 0.0.1
@author Carsten Haitzler <raster@rasterman.com>
@date 2004
@section intro What is Embryo?
It is a tiny library designed interpret limited small programs compiled by the
included scmall compiler. This is mostly cleaning up and reduction in size of
the original small abstract machine. the compiler itself has been left alone
almost completely.
@todo Document it all
@todo Clean up compiler code.
*/

View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: embryo
Description: embryo
Version: @VERSION@
Libs: -L${libdir} -lembryo -lm
Cflags: -I${includedir}

80
legacy/embryo/embryo.spec Normal file
View File

@ -0,0 +1,80 @@
# Note that this is NOT a relocatable package
%define ver 0.0.1
%define rel 1
%define prefix /usr
Summary: embryo
Name: embryo
Version: %ver
Release: %rel
Copyright: BSD
Group: System Environment/Libraries
Source: ftp://ftp.enlightenment.org/pub/embryo/embryo-%{ver}.tar.gz
BuildRoot: /var/tmp/embryo-root
Packager: The Rasterman <raster@rasterman.com>
URL: http://www.enlightenment.org/
Docdir: %{prefix}/doc
%description
Embryo is a tiny library designed as a virtual machine to interpret a limited
set of small compiled programs.
%package devel
Summary: Embryo headers, static libraries, documentation and test programs
Group: System Environment/Libraries
Requires: %{name} = %{version}
%description devel
Headers, static libraries, test programs and documentation for Embryo
%prep
rm -rf $RPM_BUILD_ROOT
%setup -q
%build
./configure --prefix=%prefix
if [ "$SMP" != "" ]; then
(make "MAKE=make -k -j $SMP"; exit 0)
make
else
make
fi
###########################################################################
%install
make DESTDIR=$RPM_BUILD_ROOT install
%clean
rm -rf $RPM_BUILD_ROOT
%post
/sbin/ldconfig
%postun
/sbin/ldconfig
%files
%defattr(-,root,root)
%attr(755,root,root) %{prefix}/lib/libembryo.so.*
%{prefix}/lib/libembryo.la
%attr(755,root,root) %{prefix}/bin/embryo_cc
%attr(755,root,root) %{prefix}/bin/embryo
%files devel
%attr(755,root,root) %{prefix}/lib/libembryo.so
%attr(755,root,root) %{prefix}/lib/libembryo.a
%attr(755,root,root) %{prefix}/bin/embryo-config
%{prefix}/lib/pkgconfig/embryo.pc
%{prefix}/include/Embryo*
%doc AUTHORS
%doc COPYING
%doc README
%doc embryo_docs.tar.gz
%changelog
* Sat Jun 23 2001 The Rasterman <raster@rasterman.com>
- Created spec file

12
legacy/embryo/gendoc Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
cp ./embryo.c.in ./embryo.c
for I in `find ./src/lib -name "*.c" -print`; do
cat $I >> ./embryo.c
done
rm -rf ./doc/html ./doc/latex ./doc/man
doxygen
cp doc/img/*.png doc/html/
rm -f embryo_docs.tar embryo_docs.tar.gz
tar -cvf embryo_docs.tar doc/html doc/man doc/latex
gzip -9 embryo_docs.tar
exit 0

View File

@ -0,0 +1,75 @@
#!/bin/sh
PROJ="embryo"
SKIFF="/skiff/local"
HOSTARCH="i686-pc-linux-gnu"
TARGETCPU="arm"
TARGETARCH=$TARGETCPU"-pc-linux-gnu"
make clean distclean
export CC=$SKIFF"/bin/"$TARGETCPU"-linux-gcc"
export CFLAGS=-O9
./configure \
--host=$HOSTARCH \
--build=$TARGETARCH \
--target=$TARGETARCH
INST="/tmp/"$PROJ"-instroot"
sudo rm -rf $INST
make
for I in find . -name "*.la" -print; do
sed s:"/usr/local":$INST:g < $I > "/tmp/.sed.tmp"
sudo cp "/tmp/.sed.tmp" $I
rm -f "/tmp/.sed.tmp"
done
sudo \
make \
prefix=$INST \
exec_prefix=$INST \
bindir=$INST"/bin" \
sbindir=$INST"/sbin" \
sysconfdir=$INST"/etc" \
datadir=$INST"/share" \
includedir=$INST"/include" \
libdir=$INST"/lib" \
libexecdir=$INST"/libexec" \
localstatedir=$INST"/var/run" \
mandir=$INST"/share/man" \
infodir=$INST"/share/info" \
install
## FIXUPS
for I in $INST"/bin/"* $INST"/sbin/"* $INST"/libexec/"*; do
J=`echo $I | sed s:$TARGETARCH"-"::g`
sudo mv $I $J
done
CF=$INST"/bin/"$PROJ"-config"
sed s:"/usr/local":$SKIFF"/"$TARGETCPU"-linux":g < $CF > "/tmp/.sed.tmp"
sudo cp "/tmp/.sed.tmp" $CF
rm -f "/tmp/.sed.tmp"
for I in $INST"/lib/"*.la; do
sed s:"/usr/local":$SKIFF"/"$TARGETCPU"-linux":g < $I > "/tmp/.sed.tmp"
sudo cp "/tmp/.sed.tmp" $I
rm -f "/tmp/.sed.tmp"
done
## package it all up
PACK=$PROJ"-"$TARGETCPU"-inst.tar.gz"
DIR=$PWD
cd $INST
sudo tar zcvf $DIR"/"$PACK *
sudo chown $USER $DIR"/"$PACK
cd $DIR
sudo rm -rf $INST
## install it in our skiff tree
cd $SKIFF"/"$TARGETCPU"-linux"
sudo tar zxvf $DIR"/"$PACK

View File

@ -0,0 +1,3 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = lib bin

View File

@ -0,0 +1,34 @@
## Process this file with automake to produce Makefile.in
INCLUDES = -DLINUX -I$(top_srcdir)/src/lib
bin_PROGRAMS = embryo embryo_cc
embryo_SOURCES = \
embryo_main.c
embryo_LDADD = $(top_builddir)/src/lib/libembryo.la
embryo_DEPENDENCIES = $(top_builddir)/src/lib/libembryo.la
embryo_cc_SOURCES = \
embryo_cc_amx.h \
embryo_cc_osdefs.h \
embryo_cc_sc.h \
embryo_cc_sc1.c \
embryo_cc_sc2.c \
embryo_cc_sc3.c \
embryo_cc_sc4.c \
embryo_cc_sc5.c \
embryo_cc_sc6.c \
embryo_cc_sc7.c \
embryo_cc_scexpand.c \
embryo_cc_sclinux.h \
embryo_cc_sclist.c \
embryo_cc_scvars.c
embryo_cc_LDADD =
embryo_cc_DEPENDENCIES =
EXTRA_DIST = \
embryo_cc_sc5.scp \
embryo_cc_sc7.scp

View File

@ -0,0 +1,349 @@
/* Abstract Machine for the Small compiler
*
* Copyright (c) ITB CompuPhase, 1997-2003
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#if defined LINUX
#include <embryo_cc_sclinux.h>
#endif
#ifndef __AMX_H
#define __AMX_H
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
/* The ISO C99 defines the int16_t and int_32t types. If the compiler got
* here, these types are probably undefined.
*/
#if defined __LCC__ || defined LINUX
#include <stdint.h>
#else
typedef short int int16_t;
typedef unsigned short int uint16_t;
#if defined SN_TARGET_PS2
typedef int int32_t;
typedef unsigned int uint32_t;
#else
typedef long int int32_t;
typedef unsigned long int uint32_t;
#endif
#endif
#endif
#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined __MSDOS__
#if !defined alloca
#define alloca(n) _alloca(n)
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* calling convention for native functions */
#if !defined AMX_NATIVE_CALL
#define AMX_NATIVE_CALL
#endif
/* calling convention for all interface functions and callback functions */
#if !defined AMXAPI
#if defined STDECL
#define AMXAPI __stdcall
#elif defined CDECL
#define AMXAPI __cdecl
#else
#define AMXAPI
#endif
#endif
#if !defined AMXEXPORT
#define AMXEXPORT
#endif
/* File format version Required AMX version
* 0 (original version) 0
* 1 (opcodes JUMP.pri, SWITCH and CASETBL) 1
* 2 (compressed files) 2
* 3 (public variables) 2
* 4 (opcodes SWAP.pri/alt and PUSHADDR) 4
* 5 (tagnames table) 4
* 6 (reformatted header) 6
* 7 (name table, opcodes SYMTAG & SYSREQ.D) 7
*/
#define CUR_FILE_VERSION 7 /* current file version; also the current AMX version */
#define MIN_FILE_VERSION 6 /* lowest supported file format version for the current AMX version */
#define MIN_AMX_VERSION 7 /* minimum AMX version needed to support the current file format */
#if !defined CELL_TYPE
#define CELL_TYPE
#if defined(BIT16)
typedef uint16_t ucell; /* only for type casting */
typedef int16_t cell;
#else
typedef uint32_t ucell;
typedef int32_t cell;
#endif
#endif
struct tagAMX;
typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params);
typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index,
cell *result, cell *params);
typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx);
#if !defined _FAR
#define _FAR
#endif
#if defined _MSC_VER
#pragma warning(disable:4103) /* disable warning message 4103 that complains
* about pragma pack in a header file */
#pragma warning(disable:4100) /* "'%$S' : unreferenced formal parameter" */
#endif
/* Some compilers do not support the #pragma align, which should be fine. Some
* compilers give a warning on unknown #pragmas, which is not so fine...
*/
#if defined SN_TARGET_PS2 || defined __GNUC__
#define AMX_NO_ALIGN
#endif
#if defined __GNUC__
#define PACKED __attribute__((packed))
#else
#define PACKED
#endif
#if !defined AMX_NO_ALIGN
#if defined LINUX
#pragma pack(1) /* structures must be packed (byte-aligned) */
#else
#pragma pack(push)
#pragma pack(1) /* structures must be packed (byte-aligned) */
#if defined __TURBOC__
#pragma option -a- /* "pack" pragma for older Borland compilers */
#endif
#endif
#endif
typedef struct {
char _FAR *name PACKED;
AMX_NATIVE func PACKED;
} AMX_NATIVE_INFO PACKED;
#define AMX_USERNUM 4
#define sEXPMAX 19 /* maximum name length for file version <= 6 */
#define sNAMEMAX 31 /* maximum name length of symbol name */
typedef struct tagAMX_FUNCSTUB {
uint32_t address PACKED;
char name[sEXPMAX+1] PACKED;
} AMX_FUNCSTUB PACKED;
/* The AMX structure is the internal structure for many functions. Not all
* fields are valid at all times; many fields are cached in local variables.
*/
typedef struct tagAMX {
unsigned char _FAR *base PACKED; /* points to the AMX header ("amxhdr") plus the code, optionally also the data */
unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */
AMX_CALLBACK callback PACKED;
AMX_DEBUG debug PACKED; /* debug callback */
/* for external functions a few registers must be accessible from the outside */
cell cip PACKED; /* instruction pointer: relative to base + amxhdr->cod */
cell frm PACKED; /* stack frame base: relative to base + amxhdr->dat */
cell hea PACKED; /* top of the heap: relative to base + amxhdr->dat */
cell hlw PACKED; /* bottom of the heap: relative to base + amxhdr->dat */
cell stk PACKED; /* stack pointer: relative to base + amxhdr->dat */
cell stp PACKED; /* top of the stack: relative to base + amxhdr->dat */
int flags PACKED; /* current status, see amx_Flags() */
/* for assertions and debug hook */
cell curline PACKED;
cell curfile PACKED;
int dbgcode PACKED;
cell dbgaddr PACKED;
cell dbgparam PACKED;
char _FAR *dbgname PACKED;
/* user data */
long usertags[AMX_USERNUM] PACKED;
void _FAR *userdata[AMX_USERNUM] PACKED;
/* native functions can raise an error */
int error PACKED;
/* the sleep opcode needs to store the full AMX status */
cell pri PACKED;
cell alt PACKED;
cell reset_stk PACKED;
cell reset_hea PACKED;
cell _FAR *syscall_d PACKED; /* relocated value/address for the SYSCALL.D opcode */
#if defined JIT
/* support variables for the JIT */
int reloc_size PACKED; /* required temporary buffer for relocations */
long code_size PACKED; /* estimated memory footprint of the native code */
#endif
} AMX PACKED;
/* The AMX_HEADER structure is both the memory format as the file format. The
* structure is used internaly.
*/
typedef struct tagAMX_HEADER {
int32_t size PACKED; /* size of the "file" */
uint16_t magic PACKED; /* signature */
char file_version PACKED; /* file format version */
char amx_version PACKED; /* required version of the AMX */
int16_t flags PACKED;
int16_t defsize PACKED; /* size of a definition record */
int32_t cod PACKED; /* initial value of COD - code block */
int32_t dat PACKED; /* initial value of DAT - data block */
int32_t hea PACKED; /* initial value of HEA - start of the heap */
int32_t stp PACKED; /* initial value of STP - stack top */
int32_t cip PACKED; /* initial value of CIP - the instruction pointer */
int32_t publics PACKED; /* offset to the "public functions" table */
int32_t natives PACKED; /* offset to the "native functions" table */
int32_t libraries PACKED; /* offset to the table of libraries */
int32_t pubvars PACKED; /* the "public variables" table */
int32_t tags PACKED; /* the "public tagnames" table */
int32_t nametable PACKED; /* name table, file version 7 only */
} AMX_HEADER PACKED;
#define AMX_MAGIC 0xf1e0
enum {
AMX_ERR_NONE,
/* reserve the first 15 error codes for exit codes of the abstract machine */
AMX_ERR_EXIT, /* forced exit */
AMX_ERR_ASSERT, /* assertion failed */
AMX_ERR_STACKERR, /* stack/heap collision */
AMX_ERR_BOUNDS, /* index out of bounds */
AMX_ERR_MEMACCESS, /* invalid memory access */
AMX_ERR_INVINSTR, /* invalid instruction */
AMX_ERR_STACKLOW, /* stack underflow */
AMX_ERR_HEAPLOW, /* heap underflow */
AMX_ERR_CALLBACK, /* no callback, or invalid callback */
AMX_ERR_NATIVE, /* native function failed */
AMX_ERR_DIVIDE, /* divide by zero */
AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */
AMX_ERR_MEMORY = 16, /* out of memory */
AMX_ERR_FORMAT, /* invalid file format */
AMX_ERR_VERSION, /* file is for a newer version of the AMX */
AMX_ERR_NOTFOUND, /* function not found */
AMX_ERR_INDEX, /* invalid index parameter (bad entry point) */
AMX_ERR_DEBUG, /* debugger cannot run */
AMX_ERR_INIT, /* AMX not initialized (or doubly initialized) */
AMX_ERR_USERDATA, /* unable to set user data field (table full) */
AMX_ERR_INIT_JIT, /* cannot initialize the JIT */
AMX_ERR_PARAMS, /* parameter error */
AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */
};
enum {
DBG_INIT, /* query/initialize */
DBG_FILE, /* file number in curfile, filename in name */
DBG_LINE, /* line number in curline, file number in curfile */
DBG_SYMBOL, /* address in dbgaddr, class/type in dbgparam */
DBG_CLRSYM, /* stack address below which locals should be removed. stack address in stk */
DBG_CALL, /* function call, address jumped to in dbgaddr */
DBG_RETURN, /* function returns */
DBG_TERMINATE, /* program ends, code address in dbgaddr, reason in dbgparam */
DBG_SRANGE, /* symbol size and dimensions (arrays); level in dbgaddr (!); length in dbgparam */
DBG_SYMTAG, /* tag of the most recent symbol (if non-zero), tag in dbgparam */
};
#define AMX_FLAG_CHAR16 0x01 /* characters are 16-bit */
#define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */
#define AMX_FLAG_COMPACT 0x04 /* compact encoding */
#define AMX_FLAG_BIGENDIAN 0x08 /* big endian encoding */
#define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking */
#define AMX_FLAG_BROWSE 0x4000 /* browsing/relocating or executing */
#define AMX_FLAG_RELOC 0x8000 /* jump/call addresses relocated */
#define AMX_EXEC_MAIN -1 /* start at program entry point */
#define AMX_EXEC_CONT -2 /* continue from last address */
#define AMX_USERTAG(a,b,c,d) ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24))
#define AMX_EXPANDMARGIN 64
/* for native functions that use floating point parameters, the following
* two macros are convenient for casting a "cell" into a "float" type _without_
* changing the bit pattern
*/
#define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
#define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */
#define amx_StrParam(amx,param,result) { \
cell *amx_cstr_; int amx_length_; \
amx_GetAddr((amx), (param), &amx_cstr_); \
amx_StrLen(amx_cstr_, &amx_length_); \
if (amx_length_ > 0 && \
((result) = (char*)alloca(amx_length_ + 1)) != NULL) \
amx_GetString((result), amx_cstr_); \
else (result) = NULL; \
}
uint16_t * AMXAPI amx_Align16(uint16_t *v);
uint32_t * AMXAPI amx_Align32(uint32_t *v);
int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr);
int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params);
int AMXAPI amx_Cleanup(AMX *amx);
int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data);
int AMXAPI amx_Debug(AMX *amx); /* default debug procedure, does nothing */
int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...);
int AMXAPI amx_Execv(AMX *amx, cell *retval, int index, int numparams, cell params[]);
int AMXAPI amx_FindNative(AMX *amx, char *name, int *index);
int AMXAPI amx_FindPublic(AMX *amx, char *funcname, int *index);
int AMXAPI amx_FindPubVar(AMX *amx, char *varname, cell *amx_addr);
int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname);
int AMXAPI amx_Flags(AMX *amx,uint16_t *flags);
int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr);
int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname);
int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname);
int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr);
int AMXAPI amx_GetString(char *dest,cell *source);
int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id);
int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr);
int AMXAPI amx_Init(AMX *amx, void *program);
int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code);
int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap);
int AMXAPI amx_NameLength(AMX *amx, int *length);
AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(char *name,AMX_NATIVE func);
int AMXAPI amx_NumNatives(AMX *amx, int *number);
int AMXAPI amx_NumPublics(AMX *amx, int *number);
int AMXAPI amx_NumPubVars(AMX *amx, int *number);
int AMXAPI amx_NumTags(AMX *amx, int *number);
int AMXAPI amx_RaiseError(AMX *amx, int error);
int AMXAPI amx_Register(AMX *amx, AMX_NATIVE_INFO *nativelist, int number);
int AMXAPI amx_Release(AMX *amx, cell amx_addr);
int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback);
int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug);
int AMXAPI amx_SetString(cell *dest, char *source, int pack);
int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr);
char * AMXAPI amx_StrError(int errnum);
int AMXAPI amx_StrLen(cell *cstring, int *length);
#if !defined AMX_NO_ALIGN
#if defined LINUX
#pragma pack() /* reset default packing */
#else
#pragma pack(pop) /* reset previous packing */
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif /* __AMX_H */

View File

@ -0,0 +1,84 @@
/* __MSDOS__ set when compiling for DOS (not Windows)
* _Windows set when compiling for any version of Microsoft Windows
* __WIN32__ set when compiling for Windows95 or WindowsNT (32 bit mode)
* __32BIT__ set when compiling in 32-bit "flat" mode (DOS or Windows)
*
* Copyright 1998-2003, ITB CompuPhase, The Netherlands.
* info@compuphase.com.
*/
#ifndef _OSDEFS_H
#define _OSDEFS_H
/* Every compiler uses different "default" macros to indicate the mode
* it is in. Throughout the source, we use the Borland C++ macros, so
* the macros of Watcom C/C++ and Microsoft Visual C/C++ are mapped to
* those of Borland C++.
*/
#if defined(__WATCOMC__)
# if defined(__WINDOWS__) || defined(__NT__)
# define _Windows 1
# endif
# ifdef __386__
# define __32BIT__ 1
# endif
# if defined(_Windows) && defined(__32BIT__)
# define __WIN32__ 1
# endif
#elif defined(_MSC_VER)
# if defined(_WINDOWS) || defined(_WIN32)
# define _Windows 1
# endif
# ifdef _WIN32
# define __WIN32__ 1
# define __32BIT__ 1
# endif
#endif
#if defined LINUX
#include <endian.h>
#endif
/* Linux NOW has these */
#if !defined BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif
#if !defined LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif
/* educated guess, BYTE_ORDER is undefined, i386 is common => little endian */
#if !defined BYTE_ORDER
#if defined UCLINUX
#define BYTE_ORDER BIG_ENDIAN
#else
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#endif
/* _MAX_PATH is sometimes called differently and it may be in limits.h instead
* stdio.h.
*/
#if !defined _MAX_PATH
/* not defined, perhaps stdio.h was not included */
#include <stdio.h>
#if !defined _MAX_PATH
/* still undefined, try a common alternative name */
#if defined MAX_PATH
#define _MAX_PATH MAX_PATH
#else
/* no _MAX_PATH and no MAX_PATH, perhaps it is in limits.h */
#include <limits.h>
#if defined PATH_MAX
#define _MAX_PATH PATH_MAX
#elif defined _POSIX_PATH_MAX
#define _MAX_PATH _POSIX_PATH_MAX
#else
/* everything failed, actually we have a problem here... */
#define _MAX_PATH 1024
#endif
#endif
#endif
#endif
#endif /* _OSDEFS_H */

View File

@ -0,0 +1,687 @@
/* Small compiler
*
* Drafted after the Small-C compiler Version 2.01, originally created
* by Ron Cain, july 1980, and enhanced by James E. Hendrix.
*
* This version comes close to a complete rewrite.
*
* Copyright R. Cain, 1980
* Copyright J.E. Hendrix, 1982, 1983
* Copyright T. Riemersma, 1997-2003
*
* Version: $Id$
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __SC_H
#define __SC_H
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#if defined __BORLANDC__ && defined _Windows && !(defined __32BIT__ || defined __WIN32__)
/* setjmp() and longjmp() not well supported in 16-bit windows */
#include <windows.h>
typedef int jmp_buf[9];
#define setjmp(b) Catch(b)
#define longjmp(b,e) Throw(b,e)
#else
#include <setjmp.h>
#endif
#include "embryo_cc_osdefs.h"
#include "embryo_cc_amx.h"
/* Note: the "cell" and "ucell" types are defined in AMX.H */
#define PUBLIC_CHAR '@' /* character that defines a function "public" */
#define CTRL_CHAR '\\' /* default control character */
#if defined __MSDOS__ || defined __WIN32__ || defined _Windows
#define DIRSEP_CHAR '\\'
#elif defined macintosh
#define DIRSEP_CHAR ':'
#else
#define DIRSEP_CHAR '/' /* directory separator character */
#endif
#define sDIMEN_MAX 2 /* maximum number of array dimensions */
#define sDEF_LITMAX 500 /* initial size of the literal pool, in "cells" */
#define sLINEMAX 511 /* input line length (in characters) */
#define sDEF_AMXSTACK 4096 /* default stack size for AMX files */
#define sSTKMAX 80 /* stack for nested #includes and other uses */
#define PREPROC_TERM '\x7f'/* termination character for preprocessor expressions (the "DEL" code) */
#define sDEF_PREFIX "default.inc" /* default prefix filename */
typedef void *stkitem; /* type of items stored on the stack */
typedef struct __s_arginfo { /* function argument info */
char name[sNAMEMAX+1];
char ident; /* iVARIABLE, iREFERENCE, iREFARRAY or iVARARGS */
char usage; /* uCONST */
int *tags; /* argument tag id. list */
int numtags; /* number of tags in the tag list */
int dim[sDIMEN_MAX];
int numdim; /* number of dimensions */
unsigned char hasdefault; /* bit0: is there a default value? bit6: "tagof"; bit7: "sizeof" */
union {
cell val; /* default value */
struct {
char *symname; /* name of another symbol */
short level; /* indirection level for that symbol */
} size; /* used for "sizeof" default value */
struct {
cell *data; /* values of default array */
int size; /* complete length of default array */
int arraysize; /* size to reserve on the heap */
cell addr; /* address of the default array in the data segment */
} array;
} defvalue; /* default value, or pointer to default array */
int defvalue_tag; /* tag of the default value */
} arginfo;
/* Equate table, tagname table, library table */
typedef struct __s_constvalue {
struct __s_constvalue *next;
char name[sNAMEMAX+1];
cell value;
short index;
} constvalue;
/* Symbol table format
*
* The symbol name read from the input file is stored in "name", the
* value of "addr" is written to the output file. The address in "addr"
* depends on the class of the symbol:
* global offset into the data segment
* local offset relative to the stack frame
* label generated hexadecimal number
* function offset into code segment
*/
typedef struct __s_symbol {
struct __s_symbol *next;
struct __s_symbol *parent; /* hierarchical types (multi-dimensional arrays) */
char name[sNAMEMAX+1];
uint32_t hash; /* value derived from name, for quicker searching */
cell addr; /* address or offset (or value for constant, index for native function) */
char vclass; /* sLOCAL if "addr" refers to a local symbol */
char ident; /* see below for possible values */
char usage; /* see below for possible values */
int compound; /* compound level (braces nesting level) */
int tag; /* tagname id */
union {
int declared; /* label: how many local variables are declared */
int idxtag; /* array: tag of array indices */
constvalue *lib; /* native function: library it is part of */ //??? use "stringlist"
} x; /* 'x' for 'extra' */
union {
arginfo *arglist; /* types of all parameters for functions */
struct {
cell length; /* arrays: length (size) */
short level; /* number of dimensions below this level */
} array;
} dim; /* for 'dimension', both functions and arrays */
int fnumber; /* static global variables: file number in which the declaration is visible */
struct __s_symbol **refer; /* referrer list, functions that "use" this symbol */
int numrefers; /* number of entries in the referrer list */
} symbol;
/* Possible entries for "ident". These are used in the "symbol", "value"
* and arginfo structures. Not every constant is valid for every use.
* In an argument list, the list is terminated with a "zero" ident; labels
* cannot be passed as function arguments, so the value 0 is overloaded.
*/
#define iLABEL 0
#define iVARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
#define iREFERENCE 2 /* iVARIABLE, but must be dereferenced */
#define iARRAY 3
#define iREFARRAY 4 /* an array passed by reference (i.e. a pointer) */
#define iARRAYCELL 5 /* array element, cell that must be fetched indirectly */
#define iARRAYCHAR 6 /* array element, character from cell from array */
#define iEXPRESSION 7 /* expression result, has no address (rvalue) */
#define iCONSTEXPR 8 /* constant expression (or constant symbol) */
#define iFUNCTN 9
#define iREFFUNC 10 /* function passed as a parameter */
#define iVARARGS 11 /* function specified ... as argument(s) */
/* Possible entries for "usage"
*
* This byte is used as a serie of bits, the syntax is different for
* functions and other symbols:
*
* VARIABLE
* bits: 0 (uDEFINE) the variable is defined in the source file
* 1 (uREAD) the variable is "read" (accessed) in the source file
* 2 (uWRITTEN) the variable is altered (assigned a value)
* 3 (uCONST) the variable is constant (may not be assigned to)
* 4 (uPUBLIC) the variable is public
* 6 (uSTOCK) the variable is discardable (without warning)
*
* FUNCTION
* bits: 0 (uDEFINE) the function is defined ("implemented") in the source file
* 1 (uREAD) the function is invoked in the source file
* 2 (uRETVALUE) the function returns a value (or should return a value)
* 3 (uPROTOTYPED) the function was prototyped
* 4 (uPUBLIC) the function is public
* 5 (uNATIVE) the function is native
* 6 (uSTOCK) the function is discardable (without warning)
* 7 (uMISSING) the function is not implemented in this source file
*
* CONSTANT
* bits: 0 (uDEFINE) the symbol is defined in the source file
* 1 (uREAD) the constant is "read" (accessed) in the source file
* 3 (uPREDEF) the constant is pre-defined and should be kept between passes
*/
#define uDEFINE 0x01
#define uREAD 0x02
#define uWRITTEN 0x04
#define uRETVALUE 0x04 /* function returns (or should return) a value */
#define uCONST 0x08
#define uPROTOTYPED 0x08
#define uPREDEF 0x08 /* constant is pre-defined */
#define uPUBLIC 0x10
#define uNATIVE 0x20
#define uSTOCK 0x40
#define uMISSING 0x80
/* uRETNONE is not stored in the "usage" field of a symbol. It is
* used during parsing a function, to detect a mix of "return;" and
* "return value;" in a few special cases.
*/
#define uRETNONE 0x10
#define uTAGOF 0x40 /* set in the "hasdefault" field of the arginfo struct */
#define uSIZEOF 0x80 /* set in the "hasdefault" field of the arginfo struct */
#define uMAINFUNC "main"
#define sGLOBAL 0 /* global/local variable/constant class */
#define sLOCAL 1
#define sSTATIC 2 /* global life, local scope */
typedef struct {
symbol *sym; /* symbol in symbol table, NULL for (constant) expression */
cell constval; /* value of the constant expression (if ident==iCONSTEXPR)
* also used for the size of a literal array */
int tag; /* tagname id (of the expression) */
char ident; /* iCONSTEXPR, iVARIABLE, iARRAY, iARRAYCELL,
* iEXPRESSION or iREFERENCE */
char boolresult; /* boolean result for relational operators */
cell *arrayidx; /* last used array indices, for checking self assignment */
} value;
/* "while" statement queue (also used for "for" and "do - while" loops) */
enum {
wqBRK, /* used to restore stack for "break" */
wqCONT, /* used to restore stack for "continue" */
wqLOOP, /* loop start label number */
wqEXIT, /* loop exit label number (jump if false) */
/* --- */
wqSIZE /* "while queue" size */
};
#define wqTABSZ (24*wqSIZE) /* 24 nested loop statements */
enum {
statIDLE, /* not compiling yet */
statFIRST, /* first pass */
statWRITE, /* writing output */
statSKIP, /* skipping output */
};
typedef struct __s_stringlist {
struct __s_stringlist *next;
char *line;
} stringlist;
typedef struct __s_stringpair {
struct __s_stringpair *next;
char *first;
char *second;
int matchlength;
} stringpair;
/* macros for code generation */
#define opcodes(n) ((n)*sizeof(cell)) /* opcode size */
#define opargs(n) ((n)*sizeof(cell)) /* size of typical argument */
/* Tokens recognized by lex()
* Some of these constants are assigned as well to the variable "lastst"
*/
#define tFIRST 256 /* value of first multi-character operator */
#define tMIDDLE 279 /* value of last multi-character operator */
#define tLAST 320 /* value of last multi-character match-able token */
/* multi-character operators */
#define taMULT 256 /* *= */
#define taDIV 257 /* /= */
#define taMOD 258 /* %= */
#define taADD 259 /* += */
#define taSUB 260 /* -= */
#define taSHL 261 /* <<= */
#define taSHRU 262 /* >>>= */
#define taSHR 263 /* >>= */
#define taAND 264 /* &= */
#define taXOR 265 /* ^= */
#define taOR 266 /* |= */
#define tlOR 267 /* || */
#define tlAND 268 /* && */
#define tlEQ 269 /* == */
#define tlNE 270 /* != */
#define tlLE 271 /* <= */
#define tlGE 272 /* >= */
#define tSHL 273 /* << */
#define tSHRU 274 /* >>> */
#define tSHR 275 /* >> */
#define tINC 276 /* ++ */
#define tDEC 277 /* -- */
#define tELLIPS 278 /* ... */
#define tDBLDOT 279 /* .. */
/* reserved words (statements) */
#define tASSERT 280
#define tBREAK 281
#define tCASE 282
#define tCHAR 283
#define tCONST 284
#define tCONTINUE 285
#define tDEFAULT 286
#define tDEFINED 287
#define tDO 288
#define tELSE 289
#define tENUM 290
#define tEXIT 291
#define tFOR 292
#define tFORWARD 293
#define tGOTO 294
#define tIF 295
#define tNATIVE 296
#define tNEW 297
#define tOPERATOR 298
#define tPUBLIC 299
#define tRETURN 300
#define tSIZEOF 301
#define tSLEEP 302
#define tSTATIC 303
#define tSTOCK 304
#define tSWITCH 305
#define tTAGOF 306
#define tWHILE 307
/* compiler directives */
#define tpASSERT 308 /* #assert */
#define tpDEFINE 309
#define tpELSE 310 /* #else */
#define tpEMIT 311
#define tpENDIF 312
#define tpENDINPUT 313
#define tpENDSCRPT 314
#define tpFILE 315
#define tpIF 316 /* #if */
#define tINCLUDE 317
#define tpLINE 318
#define tpPRAGMA 319
#define tpUNDEF 320
/* semicolon is a special case, because it can be optional */
#define tTERM 321 /* semicolon or newline */
#define tENDEXPR 322 /* forced end of expression */
/* other recognized tokens */
#define tNUMBER 323 /* integer number */
#define tRATIONAL 324 /* rational number */
#define tSYMBOL 325
#define tLABEL 326
#define tSTRING 327
#define tEXPR 328 /* for assigment to "lastst" only */
/* (reversed) evaluation of staging buffer */
#define sSTARTREORDER 1
#define sENDREORDER 2
#define sEXPRSTART 0xc0 /* top 2 bits set, rest is free */
#define sMAXARGS 64 /* relates to the bit pattern of sEXPRSTART */
/* codes for ffabort() */
#define xEXIT 1 /* exit code in PRI */
#define xASSERTION 2 /* abort caused by failing assertion */
#define xSTACKERROR 3 /* stack/heap overflow */
#define xBOUNDSERROR 4 /* array index out of bounds */
#define xMEMACCESS 5 /* data access error */
#define xINVINSTR 6 /* invalid instruction */
#define xSTACKUNDERFLOW 7 /* stack underflow */
#define xHEAPUNDERFLOW 8 /* heap underflow */
#define xCALLBACKERR 9 /* no, or invalid, callback */
#define xSLEEP 12 /* sleep, exit code in PRI, tag in ALT */
/* Miscellaneous */
#if !defined TRUE
#define FALSE 0
#define TRUE 1
#endif
#define sIN_CSEG 1 /* if parsing CODE */
#define sIN_DSEG 2 /* if parsing DATA */
#define sCHKBOUNDS 1 /* bit position in "debug" variable: check bounds */
#define sSYMBOLIC 2 /* bit position in "debug" variable: symbolic info */
#define sNOOPTIMIZE 4 /* bit position in "debug" variable: no optimization */
#define sRESET 0 /* reset error flag */
#define sFORCESET 1 /* force error flag on */
#define sEXPRMARK 2 /* mark start of expression */
#define sEXPRRELEASE 3 /* mark end of expression */
#if INT_MAX<0x8000u
#define PUBLICTAG 0x8000u
#define FIXEDTAG 0x4000u
#else
#define PUBLICTAG 0x80000000Lu
#define FIXEDTAG 0x40000000Lu
#endif
#define TAGMASK (~PUBLICTAG)
/* interface functions */
#if defined __cplusplus
extern "C" {
#endif
/*
* Functions you call from the "driver" program
*/
int sc_compile(int argc, char **argv);
int sc_addconstant(char *name,cell value,int tag);
int sc_addtag(char *name);
/*
* Functions called from the compiler (to be implemented by you)
*/
/* general console output */
int sc_printf(const char *message,...);
/* error report function */
int sc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr);
/* input from source file */
void *sc_opensrc(char *filename); /* reading only */
void sc_closesrc(void *handle); /* never delete */
void sc_resetsrc(void *handle,void *position); /* reset to a position marked earlier */
char *sc_readsrc(void *handle,char *target,int maxchars);
void *sc_getpossrc(void *handle); /* mark the current position */
int sc_eofsrc(void *handle);
/* output to intermediate (.ASM) file */
void *sc_openasm(char *filename); /* read/write */
void sc_closeasm(void *handle,int deletefile);
void sc_resetasm(void *handle);
int sc_writeasm(void *handle,char *str);
char *sc_readasm(void *handle,char *target,int maxchars);
/* output to binary (.AMX) file */
void *sc_openbin(char *filename);
void sc_closebin(void *handle,int deletefile);
void sc_resetbin(void *handle);
int sc_writebin(void *handle,void *buffer,int size);
long sc_lengthbin(void *handle); /* return the length of the file */
#if defined __cplusplus
}
#endif
/* by default, functions and variables used in throughout the compiler
* files are "external"
*/
#if !defined SC_FUNC
#define SC_FUNC
#endif
#if !defined SC_VDECL
#define SC_VDECL extern
#endif
#if !defined SC_VDEFINE
#define SC_VDEFINE
#endif
/* function prototypes in SC1.C */
SC_FUNC void set_extension(char *filename,char *extension,int force);
SC_FUNC symbol *fetchfunc(char *name,int tag);
SC_FUNC char *operator_symname(char *symname,char *opername,int tag1,int tag2,int numtags,int resulttag);
SC_FUNC char *funcdisplayname(char *dest,char *funcname);
SC_FUNC int constexpr(cell *val,int *tag);
SC_FUNC constvalue *append_constval(constvalue *table,char *name,cell val,short index);
SC_FUNC constvalue *find_constval(constvalue *table,char *name,short index);
SC_FUNC void delete_consttable(constvalue *table);
SC_FUNC void add_constant(char *name,cell val,int vclass,int tag);
SC_FUNC void exporttag(int tag);
/* function prototypes in SC2.C */
SC_FUNC void pushstk(stkitem val);
SC_FUNC stkitem popstk(void);
SC_FUNC int plungequalifiedfile(char *name); /* explicit path included */
SC_FUNC int plungefile(char *name,int try_currentpath,int try_includepaths); /* search through "include" paths */
SC_FUNC void preprocess(void);
SC_FUNC void lexinit(void);
SC_FUNC int lex(cell *lexvalue,char **lexsym);
SC_FUNC void lexpush(void);
SC_FUNC void lexclr(int clreol);
SC_FUNC int matchtoken(int token);
SC_FUNC int tokeninfo(cell *val,char **str);
SC_FUNC int needtoken(int token);
SC_FUNC void stowlit(cell value);
SC_FUNC int alphanum(char c);
SC_FUNC int ishex(char c);
SC_FUNC void delete_symbol(symbol *root,symbol *sym);
SC_FUNC void delete_symbols(symbol *root,int level,int del_labels,int delete_functions);
SC_FUNC int refer_symbol(symbol *entry,symbol *bywhom);
SC_FUNC void markusage(symbol *sym,int usage);
SC_FUNC uint32_t namehash(char *name);
SC_FUNC symbol *findglb(char *name);
SC_FUNC symbol *findloc(char *name);
SC_FUNC symbol *findconst(char *name);
SC_FUNC symbol *finddepend(symbol *parent);
SC_FUNC symbol *addsym(char *name,cell addr,int ident,int vclass,int tag,
int usage);
SC_FUNC symbol *addvariable(char *name,cell addr,int ident,int vclass,int tag,
int dim[],int numdim,int idxtag[]);
SC_FUNC int getlabel(void);
SC_FUNC char *itoh(ucell val);
/* function prototypes in SC3.C */
SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
value *lval,int *resulttag);
SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce);
SC_FUNC int expression(int *constant,cell *val,int *tag,int chkfuncresult);
SC_FUNC int hier14(value *lval1); /* the highest expression level */
/* function prototypes in SC4.C */
SC_FUNC void writeleader(void);
SC_FUNC void writetrailer(void);
SC_FUNC void begcseg(void);
SC_FUNC void begdseg(void);
SC_FUNC void setactivefile(int fnumber);
SC_FUNC cell nameincells(char *name);
SC_FUNC void setfile(char *name,int fileno);
SC_FUNC void setline(int line,int fileno);
SC_FUNC void setfiledirect(char *name);
SC_FUNC void setlinedirect(int line);
SC_FUNC void setlabel(int index);
SC_FUNC void endexpr(int fullexpr);
SC_FUNC void startfunc(char *fname);
SC_FUNC void endfunc(void);
SC_FUNC void alignframe(int numbytes);
SC_FUNC void defsymbol(char *name,int ident,int vclass,cell offset,int tag);
SC_FUNC void symbolrange(int level,cell size);
SC_FUNC void rvalue(value *lval);
SC_FUNC void address(symbol *ptr);
SC_FUNC void store(value *lval);
SC_FUNC void memcopy(cell size);
SC_FUNC void copyarray(symbol *sym,cell size);
SC_FUNC void fillarray(symbol *sym,cell size,cell value);
SC_FUNC void const1(cell val);
SC_FUNC void const2(cell val);
SC_FUNC void moveto1(void);
SC_FUNC void push1(void);
SC_FUNC void push2(void);
SC_FUNC void pushval(cell val);
SC_FUNC void pop1(void);
SC_FUNC void pop2(void);
SC_FUNC void swap1(void);
SC_FUNC void ffswitch(int label);
SC_FUNC void ffcase(cell value,char *labelname,int newtable);
SC_FUNC void ffcall(symbol *sym,int numargs);
SC_FUNC void ffret(void);
SC_FUNC void ffabort(int reason);
SC_FUNC void ffbounds(cell size);
SC_FUNC void jumplabel(int number);
SC_FUNC void defstorage(void);
SC_FUNC void modstk(int delta);
SC_FUNC void setstk(cell value);
SC_FUNC void modheap(int delta);
SC_FUNC void setheap_pri(void);
SC_FUNC void setheap(cell value);
SC_FUNC void cell2addr(void);
SC_FUNC void cell2addr_alt(void);
SC_FUNC void addr2cell(void);
SC_FUNC void char2addr(void);
SC_FUNC void charalign(void);
SC_FUNC void addconst(cell value);
/* Code generation functions for arithmetic operators.
*
* Syntax: o[u|s|b]_name
* | | | +--- name of operator
* | | +----- underscore
* | +--------- "u"nsigned operator, "s"igned operator or "b"oth
* +------------- "o"perator
*/
SC_FUNC void os_mult(void); /* multiplication (signed) */
SC_FUNC void os_div(void); /* division (signed) */
SC_FUNC void os_mod(void); /* modulus (signed) */
SC_FUNC void ob_add(void); /* addition */
SC_FUNC void ob_sub(void); /* subtraction */
SC_FUNC void ob_sal(void); /* shift left (arithmetic) */
SC_FUNC void os_sar(void); /* shift right (arithmetic, signed) */
SC_FUNC void ou_sar(void); /* shift right (logical, unsigned) */
SC_FUNC void ob_or(void); /* bitwise or */
SC_FUNC void ob_xor(void); /* bitwise xor */
SC_FUNC void ob_and(void); /* bitwise and */
SC_FUNC void ob_eq(void); /* equality */
SC_FUNC void ob_ne(void); /* inequality */
SC_FUNC void relop_prefix(void);
SC_FUNC void relop_suffix(void);
SC_FUNC void os_le(void); /* less or equal (signed) */
SC_FUNC void os_ge(void); /* greater or equal (signed) */
SC_FUNC void os_lt(void); /* less (signed) */
SC_FUNC void os_gt(void); /* greater (signed) */
SC_FUNC void lneg(void);
SC_FUNC void neg(void);
SC_FUNC void invert(void);
SC_FUNC void nooperation(void);
SC_FUNC void inc(value *lval);
SC_FUNC void dec(value *lval);
SC_FUNC void jmp_ne0(int number);
SC_FUNC void jmp_eq0(int number);
SC_FUNC void outval(cell val,int newline);
/* function prototypes in SC5.C */
SC_FUNC int error(int number,...);
SC_FUNC void errorset(int code);
/* function prototypes in SC6.C */
SC_FUNC void assemble(FILE *fout,FILE *fin);
/* function prototypes in SC7.C */
SC_FUNC void stgbuffer_cleanup(void);
SC_FUNC void stgmark(char mark);
SC_FUNC void stgwrite(char *st);
SC_FUNC void stgout(int index);
SC_FUNC void stgdel(int index,cell code_index);
SC_FUNC int stgget(int *index,cell *code_index);
SC_FUNC void stgset(int onoff);
SC_FUNC int phopt_init(void);
SC_FUNC int phopt_cleanup(void);
/* function prototypes in SCLIST.C */
SC_FUNC char* duplicatestring(const char* sourcestring);
SC_FUNC stringpair *insert_alias(char *name,char *alias);
SC_FUNC stringpair *find_alias(char *name);
SC_FUNC int lookup_alias(char *target,char *name);
SC_FUNC void delete_aliastable(void);
SC_FUNC stringlist *insert_path(char *path);
SC_FUNC char *get_path(int index);
SC_FUNC void delete_pathtable(void);
SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen);
SC_FUNC int get_subst(int index,char **pattern,char **substitution);
SC_FUNC stringpair *find_subst(char *name,int length);
SC_FUNC int delete_subst(char *name,int length);
SC_FUNC void delete_substtable(void);
/* external variables (defined in scvars.c) */
#if !defined SC_SKIP_VDECL
SC_VDECL symbol loctab; /* local symbol table */
SC_VDECL symbol glbtab; /* global symbol table */
SC_VDECL cell *litq; /* the literal queue */
SC_VDECL char pline[]; /* the line read from the input file */
SC_VDECL char *lptr; /* points to the current position in "pline" */
SC_VDECL constvalue tagname_tab;/* tagname table */
SC_VDECL constvalue libname_tab;/* library table (#pragma library "..." syntax) */ //??? use "stringlist" type
SC_VDECL constvalue *curlibrary;/* current library */
SC_VDECL symbol *curfunc; /* pointer to current function */
SC_VDECL char *inpfname; /* name of the file currently read from */
SC_VDECL char outfname[]; /* output file name */
SC_VDECL char errfname[]; /* error file name */
SC_VDECL char sc_ctrlchar; /* the control character (or escape character) */
SC_VDECL int litidx; /* index to literal table */
SC_VDECL int litmax; /* current size of the literal table */
SC_VDECL int stgidx; /* index to the staging buffer */
SC_VDECL int labnum; /* number of (internal) labels */
SC_VDECL int staging; /* true if staging output */
SC_VDECL cell declared; /* number of local cells declared */
SC_VDECL cell glb_declared; /* number of global cells declared */
SC_VDECL cell code_idx; /* number of bytes with generated code */
SC_VDECL int ntv_funcid; /* incremental number of native function */
SC_VDECL int errnum; /* number of errors */
SC_VDECL int warnnum; /* number of warnings */
SC_VDECL int sc_debug; /* debug/optimization options (bit field) */
SC_VDECL int charbits; /* number of bits for a character */
SC_VDECL int sc_packstr; /* strings are packed by default? */
SC_VDECL int sc_asmfile; /* create .ASM file? */
SC_VDECL int sc_listing; /* create .LST file? */
SC_VDECL int sc_compress; /* compress bytecode? */
SC_VDECL int sc_needsemicolon;/* semicolon required to terminate expressions? */
SC_VDECL int sc_dataalign; /* data alignment value */
SC_VDECL int sc_alignnext; /* must frame of the next function be aligned? */
SC_VDECL int curseg; /* 1 if currently parsing CODE, 2 if parsing DATA */
SC_VDECL cell sc_stksize; /* stack size */
SC_VDECL int freading; /* is there an input file ready for reading? */
SC_VDECL int fline; /* the line number in the current file */
SC_VDECL int fnumber; /* number of files in the file table (debugging) */
SC_VDECL int fcurrent; /* current file being processed (debugging) */
SC_VDECL int intest; /* true if inside a test */
SC_VDECL int sideeffect; /* true if an expression causes a side-effect */
SC_VDECL int stmtindent; /* current indent of the statement */
SC_VDECL int indent_nowarn; /* skip warning "217 loose indentation" */
SC_VDECL int sc_tabsize; /* number of spaces that a TAB represents */
SC_VDECL int sc_allowtags; /* allow/detect tagnames in lex() */
SC_VDECL int sc_status; /* read/write status */
SC_VDECL int sc_rationaltag; /* tag for rational numbers */
SC_VDECL int rational_digits; /* number of fractional digits */
SC_VDECL FILE *inpf; /* file read from (source or include) */
SC_VDECL FILE *inpf_org; /* main source file */
SC_VDECL FILE *outf; /* file written to */
SC_VDECL jmp_buf errbuf; /* target of longjmp() on a fatal error */
#if !defined SC_LIGHT
SC_VDECL int sc_makereport; /* generate a cross-reference report */
#endif
#endif /* SC_SKIP_VDECL */
#endif /* __SC_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,165 @@
/* Small compiler - Error message system
* In fact a very simple system, using only 'panic mode'.
*
* Copyright (c) ITB CompuPhase, 1997-2003
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#if defined __WIN32__ || defined _WIN32 || defined __MSDOS__
#include <io.h>
#endif
#if defined LINUX || defined __GNUC__
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h> /* ANSI standardized variable argument list functions */
#include <string.h>
#if defined FORTIFY
#include "fortify.h"
#endif
#include "embryo_cc_sc.h"
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable:4125) /* decimal digit terminates octal escape sequence */
#endif
#include "embryo_cc_sc5.scp"
#if defined _MSC_VER
#pragma warning(pop)
#endif
static int errflag;
static int errstart; /* line number at which the instruction started */
/* error
*
* Outputs an error message (note: msg is passed optionally).
* If an error is found, the variable "errflag" is set and subsequent
* errors are ignored until lex() finds a semicolumn or a keyword
* (lex() resets "errflag" in that case).
*
* Global references: inpfname (reffered to only)
* fline (reffered to only)
* fcurrent (reffered to only)
* errflag (altered)
*/
SC_FUNC int error(int number,...)
{
static char *prefix[3]={ "error", "fatal error", "warning" };
static int lastline,lastfile,errorcount;
char *msg,*pre;
va_list argptr;
char string[128];
/* errflag is reset on each semicolon.
* In a two-pass compiler, an error should not be reported twice. Therefore
* the error reporting is enabled only in the second pass (and only when
* actually producing output). Fatal errors may never be ignored.
*/
if ((errflag || sc_status!=statWRITE) && (number<100 || number>=200))
return 0;
if (number<100){
msg=errmsg[number-1];
pre=prefix[0];
errflag=TRUE; /* set errflag (skip rest of erroneous expression) */
errnum++;
} else if (number<200){
msg=fatalmsg[number-100];
pre=prefix[1];
errnum++; /* a fatal error also counts as an error */
} else {
msg=warnmsg[number-200];
pre=prefix[2];
warnnum++;
} /* if */
strexpand(string,(unsigned char *)msg,sizeof string,SCPACK_TABLE);
assert(errstart<=fline);
va_start(argptr,number);
if (strlen(errfname)==0) {
int start= (errstart==fline) ? -1 : errstart;
if (sc_error(number,string,inpfname,start,fline,argptr)) {
sc_closeasm(outf,TRUE);
outf=NULL;
longjmp(errbuf,3); /* user abort */
} /* if */
} else {
FILE *fp=fopen(errfname,"at");
if (fp!=NULL) {
if (errstart>=0 && errstart!=fline)
fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,fline,pre,number);
else
fprintf(fp,"%s(%d) : %s %03d: ",inpfname,fline,pre,number);
vfprintf(fp,string,argptr);
fclose(fp);
} /* if */
} /* if */
va_end(argptr);
if (number>=100 && number<200 || errnum>25){
if (strlen(errfname)==0) {
va_start(argptr,number);
sc_error(0,"\nCompilation aborted.",NULL,0,0,argptr);
va_end(argptr);
} /* if */
if (outf!=NULL) {
sc_closeasm(outf,TRUE);
outf=NULL;
} /* if */
longjmp(errbuf,2); /* fatal error, quit */
} /* if */
/* check whether we are seeing many errors on the same line */
if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile)
errorcount=0;
lastline=fline;
lastfile=fcurrent;
if (number<200)
errorcount++;
if (errorcount>=3)
error(107); /* too many error/warning messages on one line */
return 0;
}
SC_FUNC void errorset(int code)
{
switch (code) {
case sRESET:
errflag=FALSE; /* start reporting errors */
break;
case sFORCESET:
errflag=TRUE; /* stop reporting errors */
break;
case sEXPRMARK:
errstart=fline; /* save start line number */
break;
case sEXPRRELEASE:
errstart=-1; /* forget start line number */
break;
} /* switch */
}
#undef SCPACK_TABLE

View File

@ -0,0 +1,283 @@
/* Small compiler - Error message strings (plain and compressed formats)
*
* Copyright (c) ITB CompuPhase, 2000-2003
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2]);
#define SCPACK_TABLE errstr_table
/*-*SCPACK start of pair table, do not change or remove this line */
unsigned char errstr_table[][2] = {
{101,32}, {116,32}, {111,110}, {105,110}, {97,114}, {100,32}, {105,130}, {101,114}, {101,110}, {115,32}, {97,108}, {97,116}, {117,110}, {115,34}, {37,141}, {34,142},
{109,136}, {121,32}, {97,110}, {114,101}, {99,116}, {134,32}, {110,111}, {101,133}, {118,138}, {115,105}, {98,108}, {111,114}, {115,116}, {41,10}, {109,98}, {100,101},
{117,115}, {150,129}, {102,140}, {117,144}, {162,148}, {103,163}, {132,165}, {114,97}, {105,133}, {152,168}, {99,104}, {32,143}, {97,32}, {131,169}, {97,115}, {164,149},
{111,108}, {101,120}, {97,154}, {135,32}, {132,167}, {111,102}, {105,116}, {166,129}, {101,100}, {98,128}, {178,128}, {160,129}, {105,137}, {180,145}, {121,158}, {190,176},
{109,187}, {115,191}, {118,132}, {101,10}, {115,10}, {112,147}, {155,32}, {181,32}, {159,102}, {194,105}, {99,130}, {103,32}, {201,186}, {116,111}, {34,32}, {109,97},
{153,122}, {171,10}, {104,97}, {100,105}, {108,111}, {111,112}, {200,131}, {139,134}, {213,135}, {101,137}, {202,156}, {143,157}, {138,32}, {192,185}, {58,209}, {105,99},
{112,111}, {115,115}, {110,117}, {115,117}, {146,129}, {226,158}, {229,179}, {177,197}, {231,225}, {132,97}, {98,101}, {99,111}, {216,139}, {109,139}, {116,10}, {99,146},
{44,32}, {237,170}, {131,203}, {116,104}, {117,108}, {152,117}, {108,128}, {118,128}, {101,144}, {233,148}, {174,153}, {110,32}, {131,32}, {146,32}, {239,161}
};
/*-*SCPACK end of pair table, do not change or remove this line */
static char *errmsg[] = {
#ifdef SCPACK
/*001*/ "expected token: \"%s\", but found \"%s\"\n",
/*002*/ "only a single statement (or expression) can follow each \"case\"\n",
/*003*/ "declaration of a local variable must appear in a compound block\n",
/*004*/ "function \"%s\" is not implemented\n",
/*005*/ "function may not have arguments\n",
/*006*/ "must be assigned to an array\n",
/*007*/ "assertion failed\n",
/*008*/ "must be a constant expression; assumed zero\n",
/*009*/ "invalid array size (negative or zero)\n",
/*010*/ "invalid function or declaration\n",
/*011*/ "invalid outside functions\n",
/*012*/ "invalid function call, not a valid address\n",
/*013*/ "no entry point (no public functions)\n",
/*014*/ "invalid statement; not in switch\n",
/*015*/ "\"default\" case must be the last case in switch statement\n",
/*016*/ "multiple defaults in \"switch\"\n",
/*017*/ "undefined symbol \"%s\"\n",
/*018*/ "initialization data exceeds declared size\n",
/*019*/ "not a label: \"%s\"\n",
/*020*/ "invalid symbol name \"%s\"\n",
/*021*/ "symbol already defined: \"%s\"\n",
/*022*/ "must be lvalue (non-constant)\n",
/*023*/ "array assignment must be simple assignment\n",
/*024*/ "\"break\" or \"continue\" is out of context\n",
/*025*/ "function heading differs from prototype\n",
/*026*/ "no matching \"#if...\"\n",
/*027*/ "invalid character constant\n",
/*028*/ "invalid subscript (not an array or too many subscripts)\n",
/*029*/ "invalid expression, assumed zero\n",
/*030*/ "compound statement not closed at the end of file\n",
/*031*/ "unknown directive\n",
/*032*/ "array index out of bounds (variable \"%s\")\n",
/*033*/ "array must be indexed (variable \"%s\")\n",
/*034*/ "argument does not have a default value (argument %d)\n",
/*035*/ "argument type mismatch (argument %d)\n",
/*036*/ "empty statement\n",
/*037*/ "invalid string (possibly non-terminated string)\n",
/*038*/ "extra characters on line\n",
/*039*/ "constant symbol has no size\n",
/*040*/ "duplicate \"case\" label (value %d)\n",
/*041*/ "invalid ellipsis, array size is not known\n",
/*042*/ "invalid combination of class specifiers\n",
/*043*/ "character constant exceeds range for packed string\n",
/*044*/ "positional parameters must precede all named parameters\n",
/*045*/ "too many function arguments\n",
/*046*/ "unknown array size (variable \"%s\")\n",
/*047*/ "array sizes must match\n",
/*048*/ "array dimensions must match\n",
/*049*/ "invalid line continuation\n",
/*050*/ "invalid range\n",
/*051*/ "invalid subscript, use \"[ ]\" operators on major dimensions\n",
/*052*/ "only the last dimension may be variable length\n",
/*053*/ "exceeding maximum number of dimensions\n",
/*054*/ "unmatched closing brace\n",
/*055*/ "start of function body without function header\n",
/*056*/ "arrays, local variables and function arguments cannot be public (variable \"%s\")\n",
/*057*/ "unfinished expression before compiler directive\n",
/*058*/ "duplicate argument; same argument is passed twice\n",
/*059*/ "function argument may not have a default value (variable \"%s\")\n",
/*060*/ "multiple \"#else\" directives between \"#if ... #endif\"\n",
/*061*/ "operator cannot be redefined\n",
/*062*/ "number of operands does not fit the operator\n",
/*063*/ "function result tag of operator \"%s\" must be \"%s\"\n",
/*064*/ "cannot change predefined operators\n",
/*065*/ "function argument may only have a single tag (argument %d)\n",
/*066*/ "function argument may not be a reference argument or an array (argument \"%s\")\n",
/*067*/ "variable cannot be both a reference and an array (variable \"%s\")\n",
/*068*/ "invalid rational number precision in #pragma\n",
/*069*/ "rational number format already defined\n",
/*070*/ "rational number support was not enabled\n",
/*071*/ "user-defined operator must be declared before use (function \"%s\")\n",
/*072*/ "\"sizeof\" operator is invalid on \"function\" symbols\n",
/*073*/ "function argument must be an array (argument \"%s\")\n",
/*074*/ "#define pattern must start with an alphabetic character\n",
/*075*/ "input line too long (after substitutions)\n"
#else
"\261pe\224\227\315k\210:\253\360bu\201fo\214\205\217\012",
"\202l\221\254s\203g\366\234\213\370\201(\306\350\206) \357 f\260\324w ea\252 \042c\256e\042\012",
"\237cl\204\213\225\307\254\324c\334\314\300appe\204 \374\254\353m\340\214\205\232ock\012",
"\257\217 \274\241impl\370t\270\012",
"\257\317\221\241\322\367\246t\304",
"\335\372gn\227\315 \375\264y\012",
"\256s\207t\225fail\270\012",
"\335\254\332\344\350\206; \256\343m\227z\207o\012",
"\255\275\320\200(neg\213i\367\306z\207o\235",
"\255\257\306\237cl\204\327\012",
"\255out\231d\200\244\206\304",
"\255\257c\212l\360\241\254\251add\223s\304",
"\226 \210tr\221\340\203\201(\226 pu\232\337 \244\206s\235",
"\255\234\213\370t; \241\374sw\266\252\012",
"\042\310a\364t\316c\256\200\335\363\200l\256\201c\256\200\374sw\266\252 \234\213\370\356",
"m\364tip\366\310a\364t\211\374\042sw\266\252\042\012",
"\214\326\227\301\321",
"\203\266i\212iz\213\225d\213\254\261ce\270\211\237cl\204\227\320\303",
"\241\254la\352l\336",
"\255\301 nam\200\217\012",
"\301 \212\223ad\221\326\270\336",
"\335l\365\200(n\202-\332\222t\235",
"\275\372gn\220\201\335\231mp\366\372gn\220\356",
"\042b\223ak\316\306\042\312t\203ue\316\274ou\201\307\312t\261\356",
"\257head\362\323ff\207\211from pro\315typ\303",
"\226 \361\362\042#if...\042\012",
"\255\252\371\263\332\222\356",
"\255\343bscrip\201(\241\375\275\306\315o m\222\221\343bscripts\235",
"\255\350\206\360\256\343m\227z\207o\012",
"\353m\340\214\205\234\213\370\201\241c\324s\227a\201\363\200\210\205\307fil\303",
"\214k\226w\373\323\223\224iv\303",
"\275\203\237x ou\201\307bo\214d\211(\314\333",
"\275\335\203\237x\227(\314\333",
"\267do\331\241\322\367\254\310a\364\201\365\200(\267%d\235",
"\267typ\200mis\361 (\267%d\235",
"empt\221\234\213\370\356",
"\255\234r\362(\340s\231\232\221n\202-t\207m\203\213\227\234r\203g\235",
"\261t\247 \252\371\207\211\202 l\203\303",
"\332\344\301 \322\211\226 \320\303",
"dupl\337\213\200\042c\256e\316la\352l (\365\200%d\235",
"\255ellip\231s\360\275\320\200\274\241k\226wn\012",
"\255\353\236\203\213\225\307cl\256\211specifi\207\304",
"\252\371\263\332\344\261ce\270\211r\222g\200f\306pack\227\234r\203g\012",
"\340\231t\206\334p\351met\207\211\300\305c\270\200\212l nam\227p\351met\207\304",
"\315o m\222\221\257\246t\304",
"\214k\226w\373\275\320\200(\314\333",
"\275\320\331\300\361\012",
"\275\323\220s\206\211\300\361\012",
"\255l\203\200\312t\203u\327\012",
"\255r\222g\303",
"\255\343bscript\360\240\200\042[ ]\316\354\233\211\202 \317j\306\323\220s\206\304",
"\202l\221\363\200l\256\201\323\220s\225\317\221\271\314l\210g\363\012",
"\261ce\270\362\317ximum \346\307\323\220s\206\304",
"\214\361\227c\324s\362b\247c\303",
"\234\204\201\307\257bod\221w\266hou\201\257head\207\012",
"\264ys\360\324c\334\311\262\331\222\205\257\246t\211\376\271pu\232\337 (\314\333",
"\214f\203ish\227\350\225\352f\233\200\353mpil\263\323\223\224iv\303",
"dupl\337\213\200\246t; sam\200\267\274p\256s\227tw\337\303",
"\257\267\317\221\241\322\367\254\310a\364\201\365\200(\314\333",
"m\364tip\366\042#else\316\323\223\224iv\331\352twe\210 \042#if ... #\210\323f\042\012",
"\354\306\376\271\223\326\270\012",
"\346\307\330\222d\211do\331\241fi\201\363\200\354\233\012",
"\257\223\343l\201ta\313\307\354\233\253 \335\217\012",
"\376\252\222g\200\305\326\227\354\233\304",
"\257\267\317\221\202l\221\322\367\254s\203g\366ta\313(\267%d\235",
"\257\267\317\221\241\271\254\223f\207\210c\200\267\306\375\275(\267\333",
"\314\376\271bo\363 \254\223f\207\210c\200\222\205\375\275(\314\333",
"\255r\327\334\346\305cis\225\374#p\247g\317\012",
"r\327\334\346f\233\317\201\212\223ad\221\326\270\012",
"r\327\334\346\343pp\233\201wa\211\241\210\262\270\012",
"\240\207-\326\227\354\306\335\237cl\204\227\352f\233\200\240\200(\257\333",
"\042\320e\265\316\354\306\274\255\202 \042\244\206\316\301\304",
"\257\267\335\375\275(\267\333",
"#\326\200p\213t\207\373\300\234\204\201w\266h \375\212p\322\352t\337 \252\371\207\012",
"\203pu\201l\203\200\315o l\202\313(aft\263\343b\234\266ut\206s\235"
#endif
};
static char *fatalmsg[] = {
#ifdef SCPACK
/*100*/ "cannot read from file: \"%s\"\n",
/*101*/ "cannot write to file: \"%s\"\n",
/*102*/ "table overflow: \"%s\"\n",
/* table can be: loop table
* literal table
* staging buffer
* parser stack (recursive include?)
* option table (response file)
* peephole optimizer table
*/
/*103*/ "insufficient memory\n",
/*104*/ "invalid assembler instruction \"%s\"\n",
/*105*/ "numeric overflow, exceeding capacity\n",
/*106*/ "compaction buffer overflow\n",
/*107*/ "too many error messages on one line\n"
#else
"\376\223a\205from file\336",
"\376wr\266\200\315 file\336",
"t\272ov\207f\324w\336",
"\203\343ff\337i\210\201mem\233y\012",
"\255\256sem\232\263\203\234ru\224\225\217\012",
"\342m\207\337 ov\207f\324w\360\261ce\270\362capac\266y\012",
"\353mpa\224\225buff\263ov\207f\324w\012",
"\315o m\222\221\207r\306me\341ag\331\202 \202\200l\203\303"
#endif
};
static char *warnmsg[] = {
#ifdef SCPACK
/*200*/ "symbol \"%s\" is truncated to %d characters\n",
/*201*/ "redefinition of constant/macro (symbol \"%s\")\n",
/*202*/ "number of arguments does not match definition\n",
/*203*/ "symbol is never used: \"%s\"\n",
/*204*/ "symbol is assigned a value that is never used: \"%s\"\n",
/*205*/ "redundant code: constant expression is zero\n",
/*206*/ "redundant test: constant expression is non-zero\n",
/*207*/ "unknown #pragma\n",
/*208*/ "function uses both \"return;\" and \"return <value>;\"\n",
/*209*/ "function \"%s\" should return a value\n",
/*210*/ "possible use of symbol before initialization: \"%s\"\n",
/*211*/ "possibly unintended assignment\n",
/*212*/ "possibly unintended bitwise operation\n",
/*213*/ "tag mismatch\n",
/*214*/ "possibly a \"const\" array argument was intended: \"%s\"\n",
/*215*/ "expression has no effect\n",
/*216*/ "nested comment\n",
/*217*/ "loose indentation\n",
/*218*/ "old style prototypes used with optional semicolumns\n",
/*219*/ "local variable \"%s\" shadows a variable at a preceding level\n",
/*220*/ "exported or native symbol \"%s\" is truncated to %d characters\n",
/*221*/ "label name \"%s\" shadows tag name\n",
/*222*/ "number of digits exceeds rational number precision\n",
/*223*/ "redundant \"sizeof\": argument size is always 1 (symbol \"%s\")\n",
/*224*/ "indeterminate array size in \"sizeof\" expression (symbol \"%s\")\n",
/*225*/ "unreachable code\n",
/*226*/ "a variable is assigned to itself (symbol \"%s\")\n"
#else
"\301\253 \274tr\214c\213\227\315 %\205\252\371\207\304",
"\223\326\266\225\307\332\222t/\317cro (\301\253\235",
"\346\307\246t\211do\331\241\361 \326\266\206\012",
"\301 \274nev\263\240\270\336",
"\301 \274\372gn\227\254\365\200t\322\201\274nev\263\240\270\336",
"\223d\214d\344\353\237: \332\344\350\225\274z\207o\012",
"\223d\214d\344te\234: \332\344\350\225\274n\202-z\207o\012",
"\214k\226w\373#p\247g\317\012",
"\257\240\331bo\363 \042\223turn;\316\222\205\042\223tur\373<\365e>;\042\012",
"\257\217 sho\364\205\223tur\373\254\365\303",
"\340s\231\232\200\240\200\307\301 \352f\233\200\203\266i\212iz\327\336",
"\340s\231\232\221\214\203t\210d\227\372gn\220\356",
"\340s\231\232\221\214\203t\210d\227b\266wis\200\330\327\012",
"ta\313mis\361\012",
"\340s\231\232\221\254\042\332\316\275\267wa\211\203t\210\237d\336",
"\350\225\322\211\226 effe\224\012",
"ne\234\227\353m\220\356",
"\324os\200\203d\210t\327\012",
"\260\205\234y\366pro\315typ\331\240\227w\266h \325t\206\334sem\337\260umn\304",
"\324c\334\314\217 s\322dow\211\254\314a\201\254\305c\270\362level\012",
"\261p\233t\227\306n\213i\367\301\253 \274tr\214c\213\227\315 %\205\252\371\207\304",
"la\352l nam\200\217 s\322dow\211ta\313nam\303",
"\346\307\323g\266\211\261ce\270\211r\327\334\346\305cis\206\012",
"\223d\214d\344\042\320e\265\042: \267\320\200\274\212way\2111 (\301\253\235",
"\203\237t\207m\203\213\200\275\320\200\374\042\320e\265\316\350\225(\301\253\235",
"\214\223a\252\272\353\237\012",
"\254\314\274\372gn\227\315 \266self (\301\253\235"
#endif
};

View File

@ -0,0 +1,967 @@
/* Small compiler - Binary code generation (the "assembler")
*
* Copyright (c) ITB CompuPhase, 1997-2003
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h> /* for macro max() */
#include <string.h>
#include <ctype.h>
#if defined LINUX
#include <embryo_cc_sclinux.h>
#endif
#if defined FORTIFY
#include "fortify.h"
#endif
#include "embryo_cc_sc.h"
typedef cell (*OPCODE_PROC)(FILE *fbin,char *params,cell opcode);
typedef struct {
cell opcode;
char *name;
int segment; /* sIN_CSEG=parse in cseg, sIN_DSEG=parse in dseg */
OPCODE_PROC func;
} OPCODE;
static cell codeindex; /* similar to "code_idx" */
static cell *lbltab; /* label table */
static int writeerror;
static int bytes_in, bytes_out;
/* apparently, strtol() does not work correctly on very large (unsigned)
* hexadecimal values */
static ucell hex2long(char *s,char **n)
{
unsigned long result=0L;
int negate=FALSE;
int digit;
/* ignore leading whitespace */
while (*s==' ' || *s=='\t')
s++;
/* allow a negation sign to create the two's complement of numbers */
if (*s=='-') {
negate=TRUE;
s++;
} /* if */
assert((*s>='0' && *s<='9') || (*s>='a' && *s<='f') || (*s>='a' && *s<='f'));
for ( ;; ) {
if (*s>='0' && *s<='9')
digit=*s-'0';
else if (*s>='a' && *s<='f')
digit=*s-'a' + 10;
else if (*s>='A' && *s<='F')
digit=*s-'A' + 10;
else
break; /* probably whitespace */
result=(result<<4) | digit;
s++;
} /* for */
if (n!=NULL)
*n=s;
if (negate)
result=(~result)+1; /* take two's complement of the result */
return (ucell)result;
}
#if BYTE_ORDER==BIG_ENDIAN
static short *align16(short *v)
{
unsigned char *s = (unsigned char *)v;
unsigned char t;
/* swap two bytes */
t=s[0];
s[0]=s[1];
s[1]=t;
return v;
}
static long *align32(long *v)
{
unsigned char *s = (unsigned char *)v;
unsigned char t;
/* swap outer two bytes */
t=s[0];
s[0]=s[3];
s[3]=t;
/* swap inner two bytes */
t=s[1];
s[1]=s[2];
s[2]=t;
return v;
}
#if defined BIT16
#define aligncell(v) align16(v)
#else
#define aligncell(v) align32(v)
#endif
#else
#define align16(v) (v)
#define align32(v) (v)
#define aligncell(v) (v)
#endif
static char *skipwhitespace(char *str)
{
while (isspace(*str))
str++;
return str;
}
static char *stripcomment(char *str)
{
char *ptr=strchr(str,';');
if (ptr!=NULL) {
*ptr++='\n'; /* terminate the line, but leave the '\n' */
*ptr='\0';
} /* if */
return str;
}
static void write_encoded(FILE *fbin,ucell *c,int num)
{
assert(sizeof(cell)<=4); /* code must be adjusted for larger cells */
assert(fbin!=NULL);
while (num-->0) {
if (sc_compress) {
ucell p=(ucell)*c;
unsigned char t[5]; /* a 32-bit cell is encoded in max. 5 bytes (3 bytes for a 16-bit cell) */
unsigned char code;
int index;
for (index=0; index<5; index++) {
t[index]=(unsigned char)(p & 0x7f); /* store 7 bits */
p>>=7;
} /* for */
/* skip leading zeros */
while (index>1 && t[index-1]==0 && (t[index-2] & 0x40)==0)
index--;
/* skip leading -1s */ /* ??? for BIT16, check for index==3 && t[index-1]==0x03 */
if (index==5 && t[index-1]==0x0f && (t[index-2] & 0x40)!=0)
index--;
while (index>1 && t[index-1]==0x7f && (t[index-2] & 0x40)!=0)
index--;
/* write high byte first, write continuation bits */
assert(index>0);
while (index-->0) {
code=(unsigned char)((index==0) ? t[index] : (t[index]|0x80));
writeerror |= !sc_writebin(fbin,&code,1);
bytes_out++;
} /* while */
bytes_in+=sizeof *c;
assert(AMX_EXPANDMARGIN>2);
if (bytes_out-bytes_in>=AMX_EXPANDMARGIN-2)
error(106); /* compression buffer overflow */
} else {
assert((sc_lengthbin(fbin) % sizeof(cell)) == 0);
writeerror |= !sc_writebin(fbin,aligncell(c),sizeof *c);
} /* if */
c++;
} /* while */
}
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell noop(FILE *fbin,char *params,cell opcode)
{
return 0;
}
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell parm0(FILE *fbin,char *params,cell opcode)
{
if (fbin!=NULL)
write_encoded(fbin,(ucell*)&opcode,1);
return opcodes(1);
}
static cell parm1(FILE *fbin,char *params,cell opcode)
{
ucell p=hex2long(params,NULL);
if (fbin!=NULL) {
write_encoded(fbin,(ucell*)&opcode,1);
write_encoded(fbin,&p,1);
} /* if */
return opcodes(1)+opargs(1);
}
static cell parm2(FILE *fbin,char *params,cell opcode)
{
ucell p[2];
p[0]=hex2long(params,&params);
p[1]=hex2long(params,NULL);
if (fbin!=NULL) {
write_encoded(fbin,(ucell*)&opcode,1);
write_encoded(fbin,p,2);
} /* if */
return opcodes(1)+opargs(2);
}
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell do_dump(FILE *fbin,char *params,cell opcode)
{
ucell p;
int num = 0;
while (*params!='\0') {
p=hex2long(params,&params);
if (fbin!=NULL)
write_encoded(fbin,&p,1);
num++;
while (isspace(*params))
params++;
} /* while */
return num*sizeof(cell);
}
static cell do_call(FILE *fbin,char *params,cell opcode)
{
char name[sNAMEMAX+1];
int i;
symbol *sym;
ucell p;
for (i=0; !isspace(*params); i++,params++) {
assert(*params!='\0');
assert(i<sNAMEMAX);
name[i]=*params;
} /* for */
name[i]='\0';
/* look up the function address; note that the correct file number must
* already have been set (in order for static globals to be found).
*/
sym=findglb(name);
assert(sym!=NULL);
assert(sym->ident==iFUNCTN || sym->ident==iREFFUNC);
assert(sym->vclass==sGLOBAL);
p=sym->addr;
if (fbin!=NULL) {
write_encoded(fbin,(ucell*)&opcode,1);
write_encoded(fbin,&p,1);
} /* if */
return opcodes(1)+opargs(1);
}
static cell do_jump(FILE *fbin,char *params,cell opcode)
{
int i;
ucell p;
i=(int)hex2long(params,NULL);
assert(i>=0 && i<labnum);
if (fbin!=NULL) {
assert(lbltab!=NULL);
p=lbltab[i];
write_encoded(fbin,(ucell*)&opcode,1);
write_encoded(fbin,&p,1);
} /* if */
return opcodes(1)+opargs(1);
}
static cell do_file(FILE *fbin,char *params,cell opcode)
{
ucell p, clen;
int len;
p=hex2long(params,&params);
/* remove leading and trailing white space from the filename */
while (isspace(*params))
params++;
len=strlen(params);
while (len>0 && isspace(params[len-1]))
len--;
params[len++]='\0'; /* zero-terminate */
while (len % sizeof(cell) != 0)
params[len++]='\0'; /* pad with zeros up to full cell */
assert(len>0 && len<256);
clen=len+sizeof(cell); /* add size of file ordinal */
if (fbin!=NULL) {
write_encoded(fbin,(ucell*)&opcode,1);
write_encoded(fbin,&clen,1);
write_encoded(fbin,&p,1);
write_encoded(fbin,(ucell*)params,len/sizeof(cell));
} /* if */
return opcodes(1)+opargs(1)+clen; /* other argument is in clen */
}
static cell do_symbol(FILE *fbin,char *params,cell opcode)
{
char *endptr;
ucell offset, clen, flags;
int len;
unsigned char mclass,type;
for (endptr=params; !isspace(*endptr) && endptr!='\0'; endptr++)
/* nothing */;
assert(*endptr==' ');
len=(int)(endptr-params);
assert(len>0 && len<sNAMEMAX);
/* first get the other parameters from the line */
offset=hex2long(endptr,&endptr);
mclass=(unsigned char)hex2long(endptr,&endptr);
type=(unsigned char)hex2long(endptr,NULL);
flags=type + 256*mclass;
/* now finish up the name (overwriting the input line) */
params[len++]='\0'; /* zero-terminate */
while (len % sizeof(cell) != 0)
params[len++]='\0'; /* pad with zeros up to full cell */
clen=len+2*sizeof(cell); /* add size of symbol address and flags */
if (fbin!=NULL) {
write_encoded(fbin,(ucell*)&opcode,1);
write_encoded(fbin,&clen,1);
write_encoded(fbin,&offset,1);
write_encoded(fbin,&flags,1);
write_encoded(fbin,(ucell*)params,len/sizeof(cell));
} /* if */
#if !defined NDEBUG
/* function should start right after the symbolic information */
if (fbin==NULL && mclass==0 && type==iFUNCTN)
assert(offset==codeindex + opcodes(1)+opargs(1)+clen);
#endif
return opcodes(1)+opargs(1)+clen; /* other 2 arguments are in clen */
}
static cell do_switch(FILE *fbin,char *params,cell opcode)
{
int i;
ucell p;
i=(int)hex2long(params,NULL);
assert(i>=0 && i<labnum);
if (fbin!=NULL) {
assert(lbltab!=NULL);
p=lbltab[i];
write_encoded(fbin,(ucell*)&opcode,1);
write_encoded(fbin,&p,1);
} /* if */
return opcodes(1)+opargs(1);
}
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell do_case(FILE *fbin,char *params,cell opcode)
{
int i;
ucell p,v;
v=hex2long(params,&params);
i=(int)hex2long(params,NULL);
assert(i>=0 && i<labnum);
if (fbin!=NULL) {
assert(lbltab!=NULL);
p=lbltab[i];
write_encoded(fbin,&v,1);
write_encoded(fbin,&p,1);
} /* if */
return opcodes(0)+opargs(2);
}
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell curfile(FILE *fbin,char *params,cell opcode)
{
fcurrent=(int)hex2long(params,NULL);
return 0;
}
static OPCODE opcodelist[] = {
/* node for "invalid instruction" */
{ 0, NULL, 0, noop },
/* opcodes in sorted order */
{ 78, "add", sIN_CSEG, parm0 },
{ 87, "add.c", sIN_CSEG, parm1 },
{ 14, "addr.alt", sIN_CSEG, parm1 },
{ 13, "addr.pri", sIN_CSEG, parm1 },
{ 30, "align.alt", sIN_CSEG, parm1 },
{ 29, "align.pri", sIN_CSEG, parm1 },
{ 81, "and", sIN_CSEG, parm0 },
{121, "bounds", sIN_CSEG, parm1 },
{ 49, "call", sIN_CSEG, do_call },
{ 50, "call.pri", sIN_CSEG, parm0 },
{ 0, "case", sIN_CSEG, do_case },
{130, "casetbl", sIN_CSEG, parm0 }, /* version 1 */
{118, "cmps", sIN_CSEG, parm1 },
{ 0, "code", 0, noop },
{ 12, "const.alt", sIN_CSEG, parm1 },
{ 11, "const.pri", sIN_CSEG, parm1 },
{ 0, "curfile", sIN_CSEG, curfile },
{ 0, "data", 0, noop },
{114, "dec", sIN_CSEG, parm1 },
{113, "dec.alt", sIN_CSEG, parm0 },
{116, "dec.i", sIN_CSEG, parm0 },
{112, "dec.pri", sIN_CSEG, parm0 },
{115, "dec.s", sIN_CSEG, parm1 },
{ 0, "dump", sIN_DSEG, do_dump },
{ 95, "eq", sIN_CSEG, parm0 },
{106, "eq.c.alt", sIN_CSEG, parm1 },
{105, "eq.c.pri", sIN_CSEG, parm1 },
{124, "file", sIN_CSEG, do_file },
{119, "fill", sIN_CSEG, parm1 },
{100, "geq", sIN_CSEG, parm0 },
{ 99, "grtr", sIN_CSEG, parm0 },
{120, "halt", sIN_CSEG, parm1 },
{ 45, "heap", sIN_CSEG, parm1 },
{ 27, "idxaddr", sIN_CSEG, parm0 },
{ 28, "idxaddr.b", sIN_CSEG, parm1 },
{109, "inc", sIN_CSEG, parm1 },
{108, "inc.alt", sIN_CSEG, parm0 },
{111, "inc.i", sIN_CSEG, parm0 },
{107, "inc.pri", sIN_CSEG, parm0 },
{110, "inc.s", sIN_CSEG, parm1 },
{ 86, "invert", sIN_CSEG, parm0 },
{ 55, "jeq", sIN_CSEG, do_jump },
{ 60, "jgeq", sIN_CSEG, do_jump },
{ 59, "jgrtr", sIN_CSEG, do_jump },
{ 58, "jleq", sIN_CSEG, do_jump },
{ 57, "jless", sIN_CSEG, do_jump },
{ 56, "jneq", sIN_CSEG, do_jump },
{ 54, "jnz", sIN_CSEG, do_jump },
{ 52, "jrel", sIN_CSEG, parm1 }, /* always a number */
{ 64, "jsgeq", sIN_CSEG, do_jump },
{ 63, "jsgrtr", sIN_CSEG, do_jump },
{ 62, "jsleq", sIN_CSEG, do_jump },
{ 61, "jsless", sIN_CSEG, do_jump },
{ 51, "jump", sIN_CSEG, do_jump },
{128, "jump.pri", sIN_CSEG, parm0 }, /* version 1 */
{ 53, "jzer", sIN_CSEG, do_jump },
{ 31, "lctrl", sIN_CSEG, parm1 },
{ 98, "leq", sIN_CSEG, parm0 },
{ 97, "less", sIN_CSEG, parm0 },
{ 25, "lidx", sIN_CSEG, parm0 },
{ 26, "lidx.b", sIN_CSEG, parm1 },
{125, "line", sIN_CSEG, parm2 },
{ 2, "load.alt", sIN_CSEG, parm1 },
{ 9, "load.i", sIN_CSEG, parm0 },
{ 1, "load.pri", sIN_CSEG, parm1 },
{ 4, "load.s.alt", sIN_CSEG, parm1 },
{ 3, "load.s.pri", sIN_CSEG, parm1 },
{ 10, "lodb.i", sIN_CSEG, parm1 },
{ 6, "lref.alt", sIN_CSEG, parm1 },
{ 5, "lref.pri", sIN_CSEG, parm1 },
{ 8, "lref.s.alt", sIN_CSEG, parm1 },
{ 7, "lref.s.pri", sIN_CSEG, parm1 },
{ 34, "move.alt", sIN_CSEG, parm0 },
{ 33, "move.pri", sIN_CSEG, parm0 },
{117, "movs", sIN_CSEG, parm1 },
{ 85, "neg", sIN_CSEG, parm0 },
{ 96, "neq", sIN_CSEG, parm0 },
{134, "nop", sIN_CSEG, parm0 }, /* version 6 */
{ 84, "not", sIN_CSEG, parm0 },
{ 82, "or", sIN_CSEG, parm0 },
{ 43, "pop.alt", sIN_CSEG, parm0 },
{ 42, "pop.pri", sIN_CSEG, parm0 },
{ 46, "proc", sIN_CSEG, parm0 },
{ 40, "push", sIN_CSEG, parm1 },
{ 37, "push.alt", sIN_CSEG, parm0 },
{ 39, "push.c", sIN_CSEG, parm1 },
{ 36, "push.pri", sIN_CSEG, parm0 },
{ 38, "push.r", sIN_CSEG, parm1 },
{ 41, "push.s", sIN_CSEG, parm1 },
{133, "pushaddr", sIN_CSEG, parm1 }, /* version 4 */
{ 47, "ret", sIN_CSEG, parm0 },
{ 48, "retn", sIN_CSEG, parm0 },
{ 32, "sctrl", sIN_CSEG, parm1 },
{ 73, "sdiv", sIN_CSEG, parm0 },
{ 74, "sdiv.alt", sIN_CSEG, parm0 },
{104, "sgeq", sIN_CSEG, parm0 },
{103, "sgrtr", sIN_CSEG, parm0 },
{ 65, "shl", sIN_CSEG, parm0 },
{ 69, "shl.c.alt", sIN_CSEG, parm1 },
{ 68, "shl.c.pri", sIN_CSEG, parm1 },
{ 66, "shr", sIN_CSEG, parm0 },
{ 71, "shr.c.alt", sIN_CSEG, parm1 },
{ 70, "shr.c.pri", sIN_CSEG, parm1 },
{ 94, "sign.alt", sIN_CSEG, parm0 },
{ 93, "sign.pri", sIN_CSEG, parm0 },
{102, "sleq", sIN_CSEG, parm0 },
{101, "sless", sIN_CSEG, parm0 },
{ 72, "smul", sIN_CSEG, parm0 },
{ 88, "smul.c", sIN_CSEG, parm1 },
{127, "srange", sIN_CSEG, parm2 }, /* version 1 */
{ 20, "sref.alt", sIN_CSEG, parm1 },
{ 19, "sref.pri", sIN_CSEG, parm1 },
{ 22, "sref.s.alt", sIN_CSEG, parm1 },
{ 21, "sref.s.pri", sIN_CSEG, parm1 },
{ 67, "sshr", sIN_CSEG, parm0 },
{ 44, "stack", sIN_CSEG, parm1 },
{ 0, "stksize", 0, noop },
{ 16, "stor.alt", sIN_CSEG, parm1 },
{ 23, "stor.i", sIN_CSEG, parm0 },
{ 15, "stor.pri", sIN_CSEG, parm1 },
{ 18, "stor.s.alt", sIN_CSEG, parm1 },
{ 17, "stor.s.pri", sIN_CSEG, parm1 },
{ 24, "strb.i", sIN_CSEG, parm1 },
{ 79, "sub", sIN_CSEG, parm0 },
{ 80, "sub.alt", sIN_CSEG, parm0 },
{132, "swap.alt", sIN_CSEG, parm0 }, /* version 4 */
{131, "swap.pri", sIN_CSEG, parm0 }, /* version 4 */
{129, "switch", sIN_CSEG, do_switch }, /* version 1 */
{126, "symbol", sIN_CSEG, do_symbol },
{136, "symtag", sIN_CSEG, parm1 }, /* version 7 */
{123, "sysreq.c", sIN_CSEG, parm1 },
{135, "sysreq.d", sIN_CSEG, parm1 }, /* version 7, not generated directly */
{122, "sysreq.pri", sIN_CSEG, parm0 },
{ 76, "udiv", sIN_CSEG, parm0 },
{ 77, "udiv.alt", sIN_CSEG, parm0 },
{ 75, "umul", sIN_CSEG, parm0 },
{ 35, "xchg", sIN_CSEG, parm0 },
{ 83, "xor", sIN_CSEG, parm0 },
{ 91, "zero", sIN_CSEG, parm1 },
{ 90, "zero.alt", sIN_CSEG, parm0 },
{ 89, "zero.pri", sIN_CSEG, parm0 },
{ 92, "zero.s", sIN_CSEG, parm1 },
};
#define MAX_INSTR_LEN 30
static int findopcode(char *instr,int maxlen)
{
int low,high,mid,cmp;
char str[MAX_INSTR_LEN];
if (maxlen>=MAX_INSTR_LEN)
return 0;
strncpy(str,instr,maxlen);
str[maxlen]='\0'; /* make sure the string is zero terminated */
/* look up the instruction with a binary search
* the assembler is case insensitive to instructions (but case sensitive
* to symbols)
*/
low=1; /* entry 0 is reserved (for "not found") */
high=(sizeof opcodelist / sizeof opcodelist[0])-1;
while (low<high) {
mid=(low+high)/2;
assert(opcodelist[mid].name!=NULL);
cmp=stricmp(str,opcodelist[mid].name);
if (cmp>0)
low=mid+1;
else
high=mid;
} /* while */
assert(low==high);
if (stricmp(str,opcodelist[low].name)==0)
return low; /* found */
return 0; /* not found, return special index */
}
SC_FUNC void assemble(FILE *fout,FILE *fin)
{
typedef struct tagFUNCSTUB {
uint32_t address,nameofs;
} FUNCSTUB;
AMX_HEADER hdr;
FUNCSTUB func;
int numpublics,numnatives,numlibraries,numpubvars,numtags,padding;
long nametablesize,nameofs;
char line[256],*instr,*params;
int i,pass;
int16_t count;
symbol *sym, **nativelist;
constvalue *constptr;
cell mainaddr;
#if !defined NDEBUG
/* verify that the opcode list is sorted (skip entry 1; it is reserved
* for a non-existant opcode)
*/
assert(opcodelist[1].name!=NULL);
for (i=2; i<(sizeof opcodelist / sizeof opcodelist[0]); i++) {
assert(opcodelist[i].name!=NULL);
assert(stricmp(opcodelist[i].name,opcodelist[i-1].name)>0);
} /* for */
#endif
writeerror=FALSE;
nametablesize=sizeof(int16_t);
numpublics=0;
numnatives=0;
numpubvars=0;
mainaddr=-1;
/* count number of public and native functions and public variables */
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
char alias[sNAMEMAX+1]="";
int match=0;
if (sym->ident==iFUNCTN) {
assert(strlen(sym->name)<=sNAMEMAX);
if ((sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)!=0 && sym->addr>=0) {
match=++numnatives;
if (!lookup_alias(alias,sym->name))
strcpy(alias,sym->name);
} /* if */
if ((sym->usage & uPUBLIC)!=0 && (sym->usage & uDEFINE)!=0) {
match=++numpublics;
strcpy(alias,sym->name);
} /* if */
if (strcmp(sym->name,uMAINFUNC)==0) {
assert(sym->vclass==sGLOBAL);
mainaddr=sym->addr;
} /* if */
} else if (sym->ident==iVARIABLE) {
if ((sym->usage & uPUBLIC)!=0) {
match=++numpubvars;
strcpy(alias,sym->name);
} /* if */
} /* if */
if (match) {
assert(strlen(alias)>0);
nametablesize+=strlen(alias)+1;
} /* if */
} /* for */
assert(numnatives==ntv_funcid);
/* count number of libraries */
numlibraries=0;
for (constptr=libname_tab.next; constptr!=NULL; constptr=constptr->next) {
if (constptr->value>0) {
assert(strlen(constptr->name)>0);
numlibraries++;
nametablesize+=strlen(constptr->name)+1;
} /* if */
} /* for */
/* count number of public tags */
numtags=0;
for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
if ((constptr->value & PUBLICTAG)!=0) {
assert(strlen(constptr->name)>0);
numtags++;
nametablesize+=strlen(constptr->name)+1;
} /* if */
} /* for */
/* pad the header to sc_dataalign
* => thereby the code segment is aligned
* => since the code segment is padded to a sc_dataalign boundary, the data segment is aligned
* => and thereby the stack top is aligned too
*/
assert(sc_dataalign!=0);
padding= sc_dataalign - (sizeof hdr + nametablesize) % sc_dataalign;
if (padding==sc_dataalign)
padding=0;
/* write the abstract machine header */
memset(&hdr, 0, sizeof hdr);
hdr.magic=(unsigned short)0xF1E0;
hdr.file_version=CUR_FILE_VERSION;
hdr.amx_version=MIN_AMX_VERSION;
hdr.flags=(short)(sc_debug & sSYMBOLIC);
if (charbits==16)
hdr.flags|=AMX_FLAG_CHAR16;
if (sc_compress)
hdr.flags|=AMX_FLAG_COMPACT;
if (sc_debug==0)
hdr.flags|=AMX_FLAG_NOCHECKS;
#if BYTE_ORDER==BIG_ENDIAN
hdr.flags|=AMX_FLAG_BIGENDIAN;
#endif
hdr.defsize=sizeof(FUNCSTUB);
assert((hdr.defsize % sizeof(cell))==0);
hdr.publics=sizeof hdr; /* public table starts right after the header */
hdr.natives=hdr.publics + numpublics*sizeof(FUNCSTUB);
hdr.libraries=hdr.natives + numnatives*sizeof(FUNCSTUB);
hdr.pubvars=hdr.libraries + numlibraries*sizeof(FUNCSTUB);
hdr.tags=hdr.pubvars + numpubvars*sizeof(FUNCSTUB);
hdr.nametable=hdr.tags + numtags*sizeof(FUNCSTUB);
hdr.cod=hdr.nametable + nametablesize + padding;
hdr.dat=hdr.cod + code_idx;
hdr.hea=hdr.dat + glb_declared*sizeof(cell);
hdr.stp=hdr.hea + sc_stksize*sizeof(cell);
hdr.cip=mainaddr;
hdr.size=hdr.hea; /* preset, this is incorrect in case of compressed output */
#if BYTE_ORDER==BIG_ENDIAN
align32(&hdr.size);
align16(&hdr.magic);
align16(&hdr.flags);
align16(&hdr.defsize);
align32(&hdr.publics);
align32(&hdr.natives);
align32(&hdr.libraries);
align32(&hdr.pubvars);
align32(&hdr.tags);
align32(&hdr.nametable);
align32(&hdr.cod);
align32(&hdr.dat);
align32(&hdr.hea);
align32(&hdr.stp);
align32(&hdr.cip);
#endif
sc_writebin(fout,&hdr,sizeof hdr);
/* dump zeros up to the rest of the header, so that we can easily "seek" */
for (nameofs=sizeof hdr; nameofs<hdr.cod; nameofs++)
putc(0,fout);
nameofs=hdr.nametable+sizeof(int16_t);
/* write the public functions table */
count=0;
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
if (sym->ident==iFUNCTN
&& (sym->usage & uPUBLIC)!=0 && (sym->usage & uDEFINE)!=0)
{
assert(sym->vclass==sGLOBAL);
func.address=sym->addr;
func.nameofs=nameofs;
#if BYTE_ORDER==BIG_ENDIAN
align32(&func.address);
align32(&func.nameofs);
#endif
fseek(fout,hdr.publics+count*sizeof(FUNCSTUB),SEEK_SET);
sc_writebin(fout,&func,sizeof func);
fseek(fout,func.nameofs,SEEK_SET);
sc_writebin(fout,sym->name,strlen(sym->name)+1);
nameofs+=strlen(sym->name)+1;
count++;
} /* if */
} /* for */
/* write the natives table */
/* The native functions must be written in sorted order. (They are
* sorted on their "id", not on their name). A nested loop to find
* each successive function would be an O(n^2) operation. But we
* do not really need to sort, because the native function id's
* are sequential and there are no duplicates. So we first walk
* through the complete symbol list and store a pointer to every
* native function of interest in a temporary table, where its id
* serves as the index in the table. Now we can walk the table and
* have all native functions in sorted order.
*/
if (numnatives>0) {
nativelist=(symbol **)malloc(numnatives*sizeof(symbol *));
if (nativelist==NULL)
error(103); /* insufficient memory */
#if !defined NDEBUG
memset(nativelist,0,numnatives*sizeof(symbol *)); /* for NULL checking */
#endif
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
if (sym->ident==iFUNCTN && (sym->usage & uNATIVE)!=0 && (sym->usage & uREAD)!=0 && sym->addr>=0) {
assert(sym->addr < numnatives);
nativelist[(int)sym->addr]=sym;
} /* if */
} /* for */
count=0;
for (i=0; i<numnatives; i++) {
char alias[sNAMEMAX+1];
sym=nativelist[i];
assert(sym!=NULL);
if (!lookup_alias(alias,sym->name)) {
assert(strlen(sym->name)<=sNAMEMAX);
strcpy(alias,sym->name);
} /* if */
assert(sym->vclass==sGLOBAL);
func.address=0;
func.nameofs=nameofs;
#if BYTE_ORDER==BIG_ENDIAN
align32(&func.address);
align32(&func.nameofs);
#endif
fseek(fout,hdr.natives+count*sizeof(FUNCSTUB),SEEK_SET);
sc_writebin(fout,&func,sizeof func);
fseek(fout,func.nameofs,SEEK_SET);
sc_writebin(fout,alias,strlen(alias)+1);
nameofs+=strlen(alias)+1;
count++;
} /* for */
free(nativelist);
} /* if */
/* write the libraries table */
count=0;
for (constptr=libname_tab.next; constptr!=NULL; constptr=constptr->next) {
if (constptr->value>0) {
assert(strlen(constptr->name)>0);
func.address=0;
func.nameofs=nameofs;
#if BYTE_ORDER==BIG_ENDIAN
align32(&func.address);
align32(&func.nameofs);
#endif
fseek(fout,hdr.libraries+count*sizeof(FUNCSTUB),SEEK_SET);
sc_writebin(fout,&func,sizeof func);
fseek(fout,func.nameofs,SEEK_SET);
sc_writebin(fout,constptr->name,strlen(constptr->name)+1);
nameofs+=strlen(constptr->name)+1;
count++;
} /* if */
} /* for */
/* write the public variables table */
count=0;
for (sym=glbtab.next; sym!=NULL; sym=sym->next) {
if (sym->ident==iVARIABLE && (sym->usage & uPUBLIC)!=0) {
assert((sym->usage & uDEFINE)!=0);
assert(sym->vclass==sGLOBAL);
func.address=sym->addr;
func.nameofs=nameofs;
#if BYTE_ORDER==BIG_ENDIAN
align32(&func.address);
align32(&func.nameofs);
#endif
fseek(fout,hdr.pubvars+count*sizeof(FUNCSTUB),SEEK_SET);
sc_writebin(fout,&func,sizeof func);
fseek(fout,func.nameofs,SEEK_SET);
sc_writebin(fout,sym->name,strlen(sym->name)+1);
nameofs+=strlen(sym->name)+1;
count++;
} /* if */
} /* for */
/* write the public tagnames table */
count=0;
for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
if ((constptr->value & PUBLICTAG)!=0) {
assert(strlen(constptr->name)>0);
func.address=constptr->value & TAGMASK;
func.nameofs=nameofs;
#if BYTE_ORDER==BIG_ENDIAN
align32(&func.address);
align32(&func.nameofs);
#endif
fseek(fout,hdr.tags+count*sizeof(FUNCSTUB),SEEK_SET);
sc_writebin(fout,&func,sizeof func);
fseek(fout,func.nameofs,SEEK_SET);
sc_writebin(fout,constptr->name,strlen(constptr->name)+1);
nameofs+=strlen(constptr->name)+1;
count++;
} /* if */
} /* for */
/* write the "maximum name length" field in the name table */
assert(nameofs==hdr.nametable+nametablesize);
fseek(fout,hdr.nametable,SEEK_SET);
count=sNAMEMAX;
#if BYTE_ORDER==BIG_ENDIAN
align16(&count);
#endif
sc_writebin(fout,&count,sizeof count);
fseek(fout,hdr.cod,SEEK_SET);
/* First pass: relocate all labels */
/* This pass is necessary because the code addresses of labels is only known
* after the peephole optimization flag. Labels can occur inside expressions
* (e.g. the conditional operator), which are optimized.
*/
lbltab=NULL;
if (labnum>0) {
/* only very short programs have zero labels; no first pass is needed
* if there are no labels */
lbltab=(cell *)malloc(labnum*sizeof(cell));
if (lbltab==NULL)
error(103); /* insufficient memory */
codeindex=0;
sc_resetasm(fin);
while (sc_readasm(fin,line,sizeof line)!=NULL) {
stripcomment(line);
instr=skipwhitespace(line);
/* ignore empty lines */
if (*instr=='\0')
continue;
if (tolower(*instr)=='l' && *(instr+1)=='.') {
int lindex=(int)hex2long(instr+2,NULL);
assert(lindex<labnum);
lbltab[lindex]=codeindex;
} else {
/* get to the end of the instruction (make use of the '\n' that fgets()
* added at the end of the line; this way we will *always* drop on a
* whitespace character) */
for (params=instr; *params!='\0' && !isspace(*params); params++)
/* nothing */;
assert(params>instr);
i=findopcode(instr,(int)(params-instr));
if (opcodelist[i].name==NULL) {
*params='\0';
error(104,instr); /* invalid assembler instruction */
} /* if */
if (opcodelist[i].segment==sIN_CSEG)
codeindex+=opcodelist[i].func(NULL,skipwhitespace(params),opcodelist[i].opcode);
} /* if */
} /* while */
} /* if */
/* Second pass (actually 2 more passes, one for all code and one for all data) */
bytes_in=0;
bytes_out=0;
for (pass=sIN_CSEG; pass<=sIN_DSEG; pass++) {
sc_resetasm(fin);
while (sc_readasm(fin,line,sizeof line)!=NULL) {
stripcomment(line);
instr=skipwhitespace(line);
/* ignore empty lines and labels (labels have a special syntax, so these
* must be parsed separately) */
if (*instr=='\0' || tolower(*instr)=='l' && *(instr+1)=='.')
continue;
/* get to the end of the instruction (make use of the '\n' that fgets()
* added at the end of the line; this way we will *always* drop on a
* whitespace character) */
for (params=instr; *params!='\0' && !isspace(*params); params++)
/* nothing */;
assert(params>instr);
i=findopcode(instr,(int)(params-instr));
assert(opcodelist[i].name!=NULL);
if (opcodelist[i].segment==pass)
opcodelist[i].func(fout,skipwhitespace(params),opcodelist[i].opcode);
} /* while */
} /* for */
if (bytes_out-bytes_in>0)
error(106); /* compression buffer overflow */
if (lbltab!=NULL) {
free(lbltab);
#if !defined NDEBUG
lbltab=NULL;
#endif
} /* if */
if (writeerror)
error(101,"disk full");
/* adjust the header */
if (sc_compress) {
hdr.size=sc_lengthbin(fout);
#if BYTE_ORDER==BIG_ENDIAN
align32(&hdr.size);
#endif
sc_resetbin(fout); /* "size" is the very first field */
sc_writebin(fout,&hdr.size,sizeof hdr.size);
} /* if */
}

View File

@ -0,0 +1,606 @@
/* Small compiler - Staging buffer and optimizer
*
* The staging buffer
* ------------------
* The staging buffer allows buffered output of generated code, deletion
* of redundant code, optimization by a tinkering process and reversing
* the ouput of evaluated expressions (which is used for the reversed
* evaluation of arguments in functions).
* Initially, stgwrite() writes to the file directly, but after a call to
* stgset(TRUE), output is redirected to the buffer. After a call to
* stgset(FALSE), stgwrite()'s output is directed to the file again. Thus
* only one routine is used for writing to the output, which can be
* buffered output or direct output.
*
* staging buffer variables: stgbuf - the buffer
* stgidx - current index in the staging buffer
* staging - if true, write to the staging buffer;
* if false, write to file directly.
*
* Copyright (c) ITB CompuPhase, 1997-2003
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h> /* for atoi() */
#include <string.h>
#include <ctype.h>
#if defined FORTIFY
#include "fortify.h"
#endif
#include "embryo_cc_sc.h"
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable:4125) /* decimal digit terminates octal escape sequence */
#endif
#include "embryo_cc_sc7.scp"
#if defined _MSC_VER
#pragma warning(pop)
#endif
static void stgstring(char *start,char *end);
static void stgopt(char *start,char *end);
#define sSTG_GROW 512
#define sSTG_MAX 20480
static char *stgbuf = NULL;
static int stgmax = 0; /* current size of the staging buffer */
#define CHECK_STGBUFFER(index) if ((int)(index)>=stgmax) grow_stgbuffer((index)+1)
static void grow_stgbuffer(int requiredsize)
{
char *p;
int clear = stgbuf==NULL; /* if previously none, empty buffer explicitly */
assert(stgmax<requiredsize);
/* if the staging buffer (holding intermediate code for one line) grows
* over a few kBytes, there is probably a run-away expression
*/
if (requiredsize>sSTG_MAX)
error(102,"staging buffer"); /* staging buffer overflow (fatal error) */
stgmax=requiredsize+sSTG_GROW;
if (stgbuf!=NULL)
p=(char *)realloc(stgbuf,stgmax*sizeof(char));
else
p=(char *)malloc(stgmax*sizeof(char));
if (p==NULL)
error(102,"staging buffer"); /* staging buffer overflow (fatal error) */
stgbuf=p;
if (clear)
*stgbuf='\0';
}
SC_FUNC void stgbuffer_cleanup(void)
{
if (stgbuf!=NULL) {
free(stgbuf);
stgbuf=NULL;
stgmax=0;
} /* if */
}
/* the variables "stgidx" and "staging" are declared in "scvars.c" */
/* stgmark
*
* Copies a mark into the staging buffer. At this moment there are three
* possible marks:
* sSTARTREORDER identifies the beginning of a series of expression
* strings that must be written to the output file in
* reordered order
* sENDREORDER identifies the end of 'reverse evaluation'
* sEXPRSTART + idx only valid within a block that is evaluated in
* reordered order, it identifies the start of an
* expression; the "idx" value is the argument position
*
* Global references: stgidx (altered)
* stgbuf (altered)
* staging (referred to only)
*/
SC_FUNC void stgmark(char mark)
{
if (staging) {
CHECK_STGBUFFER(stgidx);
stgbuf[stgidx++]=mark;
} /* if */
}
static int filewrite(char *str)
{
if (sc_status==statWRITE)
return sc_writeasm(outf,str);
return TRUE;
}
/* stgwrite
*
* Writes the string "st" to the staging buffer or to the output file. In the
* case of writing to the staging buffer, the terminating byte of zero is
* copied too, but... the optimizer can only work on complete lines (not on
* fractions of it. Therefore if the string is staged, if the last character
* written to the buffer is a '\0' and the previous-to-last is not a '\n',
* the string is concatenated to the last string in the buffer (the '\0' is
* overwritten). This also means an '\n' used in the middle of a string isn't
* recognized and could give wrong results with the optimizer.
* Even when writing to the output file directly, all strings are buffered
* until a whole line is complete.
*
* Global references: stgidx (altered)
* stgbuf (altered)
* staging (referred to only)
*/
SC_FUNC void stgwrite(char *st)
{
int len;
CHECK_STGBUFFER(0);
if (staging) {
if (stgidx>=2 && stgbuf[stgidx-1]=='\0' && stgbuf[stgidx-2]!='\n')
stgidx-=1; /* overwrite last '\0' */
while (*st!='\0') { /* copy to staging buffer */
CHECK_STGBUFFER(stgidx);
stgbuf[stgidx++]=*st++;
} /* while */
CHECK_STGBUFFER(stgidx);
stgbuf[stgidx++]='\0';
} else {
CHECK_STGBUFFER(strlen(stgbuf)+strlen(st)+1);
strcat(stgbuf,st);
len=strlen(stgbuf);
if (len>0 && stgbuf[len-1]=='\n') {
filewrite(stgbuf);
stgbuf[0]='\0';
} /* if */
} /* if */
}
/* stgout
*
* Writes the staging buffer to the output file via stgstring() (for
* reversing expressions in the buffer) and stgopt() (for optimizing). It
* resets "stgidx".
*
* Global references: stgidx (altered)
* stgbuf (referred to only)
* staging (referred to only)
*/
SC_FUNC void stgout(int index)
{
if (!staging)
return;
stgstring(&stgbuf[index],&stgbuf[stgidx]);
stgidx=index;
}
typedef struct {
char *start,*end;
} argstack;
/* stgstring
*
* Analyses whether code strings should be output to the file as they appear
* in the staging buffer or whether portions of it should be re-ordered.
* Re-ordering takes place in function argument lists; Small passes arguments
* to functions from right to left. When arguments are "named" rather than
* positional, the order in the source stream is indeterminate.
* This function calls itself recursively in case it needs to re-order code
* strings, and it uses a private stack (or list) to mark the start and the
* end of expressions in their correct (reversed) order.
* In any case, stgstring() sends a block as large as possible to the
* optimizer stgopt().
*
* In "reorder" mode, each set of code strings must start with the token
* sEXPRSTART, even the first. If the token sSTARTREORDER is represented
* by '[', sENDREORDER by ']' and sEXPRSTART by '|' the following applies:
* '[]...' valid, but useless; no output
* '[|...] valid, but useless; only one string
* '[|...|...] valid and usefull
* '[...|...] invalid, first string doesn't start with '|'
* '[|...|] invalid
*/
static void stgstring(char *start,char *end)
{
char *ptr;
int nest,argc,arg;
argstack *stack;
while (start<end) {
if (*start==sSTARTREORDER) {
start+=1; /* skip token */
/* allocate a argstack with sMAXARGS items */
stack=(argstack *)malloc(sMAXARGS*sizeof(argstack));
if (stack==NULL)
error(103); /* insufficient memory */
nest=1; /* nesting counter */
argc=0; /* argument counter */
arg=-1; /* argument index; no valid argument yet */
do {
switch (*start) {
case sSTARTREORDER:
nest++;
start++;
break;
case sENDREORDER:
nest--;
start++;
break;
default:
if ((*start & sEXPRSTART)==sEXPRSTART) {
if (nest==1) {
if (arg>=0)
stack[arg].end=start-1; /* finish previous argument */
arg=(unsigned char)*start - sEXPRSTART;
stack[arg].start=start+1;
if (arg>=argc)
argc=arg+1;
} /* if */
start++;
} else {
start+=strlen(start)+1;
} /* if */
} /* switch */
} while (nest); /* enddo */
if (arg>=0)
stack[arg].end=start-1; /* finish previous argument */
while (argc>0) {
argc--;
stgstring(stack[argc].start,stack[argc].end);
} /* while */
free(stack);
} else {
ptr=start;
while (ptr<end && *ptr!=sSTARTREORDER)
ptr+=strlen(ptr)+1;
stgopt(start,ptr);
start=ptr;
} /* if */
} /* while */
}
/* stgdel
*
* Scraps code from the staging buffer by resetting "stgidx" to "index".
*
* Global references: stgidx (altered)
* staging (reffered to only)
*/
SC_FUNC void stgdel(int index,cell code_index)
{
if (staging) {
stgidx=index;
code_idx=code_index;
} /* if */
}
SC_FUNC int stgget(int *index,cell *code_index)
{
if (staging) {
*index=stgidx;
*code_index=code_idx;
} /* if */
return staging;
}
/* stgset
*
* Sets staging on or off. If it's turned off, the staging buffer must be
* initialized to an empty string. If it's turned on, the routine makes sure
* the index ("stgidx") is set to 0 (it should already be 0).
*
* Global references: staging (altered)
* stgidx (altered)
* stgbuf (contents altered)
*/
SC_FUNC void stgset(int onoff)
{
staging=onoff;
if (staging){
assert(stgidx==0);
stgidx=0;
CHECK_STGBUFFER(stgidx);
/* write any contents that may be put in the buffer by stgwrite()
* when "staging" was 0
*/
if (strlen(stgbuf)>0)
filewrite(stgbuf);
} /* if */
stgbuf[0]='\0';
}
/* phopt_init
* Initialize all sequence strings of the peehole optimizer. The strings
* are embedded in the .EXE file in compressed format, here we expand
* them (and allocate memory for the sequences).
*/
static SEQUENCE *sequences;
SC_FUNC int phopt_init(void)
{
int number, i, len;
char str[160];
/* count number of sequences */
for (number=0; sequences_cmp[number].find!=NULL; number++)
/* nothing */;
number++; /* include an item for the NULL terminator */
if ((sequences=(SEQUENCE*)malloc(number * sizeof(SEQUENCE)))==NULL)
return FALSE;
/* pre-initialize all to NULL (in case of failure) */
for (i=0; i<number; i++) {
sequences[i].find=NULL;
sequences[i].replace=NULL;
sequences[i].savesize=0;
} /* for */
/* expand all strings */
for (i=0; i<number-1; i++) {
len = strexpand(str,(unsigned char*)sequences_cmp[i].find,sizeof str,SCPACK_TABLE);
assert(len<=sizeof str);
assert(len==(int)strlen(str)+1);
sequences[i].find=(char*)malloc(len);
if (sequences[i].find!=NULL)
strcpy(sequences[i].find,str);
len = strexpand(str,(unsigned char*)sequences_cmp[i].replace,sizeof str,SCPACK_TABLE);
assert(len<=sizeof str);
assert(len==(int)strlen(str)+1);
sequences[i].replace=(char*)malloc(len);
if (sequences[i].replace!=NULL)
strcpy(sequences[i].replace,str);
sequences[i].savesize=sequences_cmp[i].savesize;
if (sequences[i].find==NULL || sequences[i].replace==NULL)
return phopt_cleanup();
} /* for */
return TRUE;
}
SC_FUNC int phopt_cleanup(void)
{
int i;
if (sequences!=NULL) {
i=0;
while (sequences[i].find!=NULL || sequences[i].replace!=NULL) {
if (sequences[i].find!=NULL)
free(sequences[i].find);
if (sequences[i].replace!=NULL)
free(sequences[i].replace);
i++;
} /* while */
free(sequences);
sequences=NULL;
} /* if */
return FALSE;
}
#define _maxoptvars 4
#define _aliasmax 10 /* a 32-bit number can be represented in
* 9 decimal digits */
static int matchsequence(char *start,char *end,char *pattern,
char symbols[_maxoptvars][_aliasmax+1],
int *match_length)
{
int var,i;
char str[_aliasmax+1];
char *start_org=start;
*match_length=0;
for (var=0; var<_maxoptvars; var++)
symbols[var][0]='\0';
while (*start=='\t' || *start==' ')
start++;
while (*pattern) {
if (start>=end)
return FALSE;
switch (*pattern) {
case '%': /* new "symbol" */
pattern++;
assert(isdigit(*pattern));
var=atoi(pattern) - 1;
assert(var>=0 && var<_maxoptvars);
assert(alphanum(*start));
for (i=0; start<end && alphanum(*start); i++,start++) {
assert(i<=_aliasmax);
str[i]=*start;
} /* for */
str[i]='\0';
if (symbols[var][0]!='\0') {
if (strcmp(symbols[var],str)!=0)
return FALSE; /* symbols should be identical */
} else {
strcpy(symbols[var],str);
} /* if */
break;
case ' ':
if (*start!='\t' && *start!=' ')
return FALSE;
while (start<end && *start=='\t' || *start==' ')
start++;
break;
case '!':
while (start<end && *start=='\t' || *start==' ')
start++; /* skip trailing white space */
if (*start!='\n')
return FALSE;
assert(*(start+1)=='\0');
start+=2; /* skip '\n' and '\0' */
if (*(pattern+1)!='\0')
while (start<end && *start=='\t' || *start==' ')
start++; /* skip leading white space of next instruction */
break;
default:
if (tolower(*start) != tolower(*pattern))
return FALSE;
start++;
} /* switch */
pattern++;
} /* while */
*match_length=(int)(start-start_org);
return TRUE;
}
static char *replacesequence(char *pattern,char symbols[_maxoptvars][_aliasmax+1],int *repl_length)
{
char *lptr;
int var;
char *buffer;
/* calculate the length of the new buffer
* this is the length of the pattern plus the length of all symbols (note
* that the same symbol may occur multiple times in the pattern) plus
* line endings and startings ('\t' to start a line and '\n\0' to end one)
*/
assert(repl_length!=NULL);
*repl_length=0;
lptr=pattern;
while (*lptr) {
switch (*lptr) {
case '%':
lptr++; /* skip '%' */
assert(isdigit(*lptr));
var=atoi(lptr) - 1;
assert(var>=0 && var<_maxoptvars);
assert(symbols[var][0]!='\0'); /* variable should be defined */
*repl_length+=strlen(symbols[var]);
break;
case '!':
*repl_length+=3; /* '\t', '\n' & '\0' */
break;
default:
*repl_length+=1;
} /* switch */
lptr++;
} /* while */
/* allocate a buffer to replace the sequence in */
if ((buffer=malloc(*repl_length))==NULL)
return (char*)error(103);
/* replace the pattern into this temporary buffer */
lptr=buffer;
*lptr++='\t'; /* the "replace" patterns do not have tabs */
while (*pattern) {
assert((int)(lptr-buffer)<*repl_length);
switch (*pattern) {
case '%':
/* write out the symbol */
pattern++;
assert(isdigit(*pattern));
var=atoi(pattern) - 1;
assert(var>=0 && var<_maxoptvars);
assert(symbols[var][0]!='\0'); /* variable should be defined */
strcpy(lptr,symbols[var]);
lptr+=strlen(symbols[var]);
break;
case '!':
/* finish the line, optionally start the next line with an indent */
*lptr++='\n';
*lptr++='\0';
if (*(pattern+1)!='\0')
*lptr++='\t';
break;
default:
*lptr++=*pattern;
} /* switch */
pattern++;
} /* while */
assert((int)(lptr-buffer)==*repl_length);
return buffer;
}
static void strreplace(char *dest,char *replace,int sub_length,int repl_length,int dest_length)
{
int offset=sub_length-repl_length;
if (offset>0) /* delete a section */
memmove(dest,dest+offset,dest_length-offset);
else if (offset<0) /* insert a section */
memmove(dest-offset, dest, dest_length);
memcpy(dest, replace, repl_length);
}
/* stgopt
*
* Optimizes the staging buffer by checking for series of instructions that
* can be coded more compact. The routine expects the lines in the staging
* buffer to be separated with '\n' and '\0' characters.
*
* The longest sequences must be checked first.
*/
static void stgopt(char *start,char *end)
{
char symbols[_maxoptvars][_aliasmax+1];
int seq,match_length,repl_length;
assert(sequences!=NULL);
while (start<end) {
if ((sc_debug & sNOOPTIMIZE)!=0 || sc_status!=statWRITE) {
/* do not match anything if debug-level is maximum */
filewrite(start);
} else {
seq=0;
while (sequences[seq].find!=NULL) {
assert(seq>=0);
if (matchsequence(start,end,sequences[seq].find,symbols,&match_length)) {
char *replace=replacesequence(sequences[seq].replace,symbols,&repl_length);
/* If the replacement is bigger than the original section, we may need
* to "grow" the staging buffer. This is quite complex, due to the
* re-ordering of expressions that can also happen in the staging
* buffer. In addition, it should not happen: the peephole optimizer
* must replace sequences with *shorter* sequences, not longer ones.
* So, I simply forbid sequences that are longer than the ones they
* are meant to replace.
*/
assert(match_length>=repl_length);
if (match_length>=repl_length) {
strreplace(start,replace,match_length,repl_length,(int)(end-start));
end-=match_length-repl_length;
free(replace);
code_idx-=sequences[seq].savesize;
seq=0; /* restart search for matches */
} else {
/* actually, we should never get here (match_length<repl_length) */
assert(0);
seq++;
} /* if */
} else {
seq++;
} /* if */
} /* while */
assert(sequences[seq].find==NULL);
filewrite(start);
} /* if */
assert(start < end);
start += strlen(start) + 1; /* to next string */
} /* while (start<end) */
}
#undef SCPACK_TABLE

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
/* expand.c -- Byte Pair Encoding decompression */
/* Copyright 1996 Philip Gage */
/* Byte Pair Compression appeared in the September 1997
* issue of C/C++ Users Journal. The original source code
* may still be found at the web site of the magazine
* (www.cuj.com).
*
* The decompressor has been modified by me (Thiadmer
* Riemersma) to accept a string as input, instead of a
* complete file.
*/
#include <assert.h>
#include <stdio.h>
#include "embryo_cc_sc.h"
#define STACKSIZE 16
SC_FUNC int strexpand(char *dest, unsigned char *source, int maxlen, unsigned char pairtable[128][2])
{
unsigned char stack[STACKSIZE];
short c, top = 0;
int len;
assert(maxlen > 0);
len = 1; /* already 1 byte for '\0' */
for (;;) {
/* Pop byte from stack or read byte from the input string */
if (top)
c = stack[--top];
else if ((c = *(unsigned char *)source++) == '\0')
break;
/* Push pair on stack or output byte to the output string */
if (c > 127) {
assert(top+2 <= STACKSIZE);
stack[top++] = pairtable[c-128][1];
stack[top++] = pairtable[c-128][0];
}
else {
len++;
if (maxlen > 1) { /* reserve one byte for the '\0' */
*dest++ = (char)c;
maxlen--;
}
}
}
*dest = '\0';
return len; /* return number of bytes decoded */
}
#if 0 /*for testing*/
#include "sc5.scp"
int main (int argc, char **argv)
{
int i;
char str[128];
for (i=0; i<58; i++) {
strexpand(str, errmsg[i], sizeof str, SCPACK_TABLE);
printf("%s", str);
} /* for */
return 0;
}
#endif

View File

@ -0,0 +1,218 @@
/* SCLIB.C
*
* This is an example file that shows how to embed the Small compiler into a
* program. This program contains the "default" implementation of all
* functions that the Small compiler calls for I/O.
*
* This program also contains a main(), so it compiles, again, to a
* stand-alone compiler. This is for illustration purposes only
*
* What this file does is (in sequence):
* 1. Declare the NO_MAIN macro, so that the function main() and all
* "callback" functions that are in SC1.C are not compiled.
* 2. Declare SC_FUNC and SC_VDEFINE as "static" so that all functions and
* global variables are "encapsulated" in the object file. This solves
* the global namespace polution problem.
* 3. Declare the SC_SKIP_VDECL macro which is needed to avoid variables to
* be doubly declared when the C files are *not* independently compiled.
* 4. And, the dirtiest trick of all, include the remaining C files. That is,
* the entire Small compiler compiles to a single object file (.OBJ in
* Windows). This is the only way to get rid of the global namespace
* polution.
*
* Note that the interface of the Small compiler is subject to change.
*
* Compilation:
* wcl386 /l=nt sclib.c
*
* Copyright (c) ITB CompuPhase, 2000-2003
* This file may be freely used. No warranties of any kind.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define NO_MAIN
#define SC_FUNC static
#define SC_VDEFINE static
#define SC_SKIP_VDECL /* skip variable "forward declaration" */
#include "sc.h"
#include "scvars.c"
#include "sc1.c"
#include "sc2.c"
#include "sc3.c"
#include "sc4.c"
#include "sc5.c"
#include "sc6.c"
#include "sc7.c"
#include "sclist.c"
#include "scexpand.c"
int main(int argc, char **argv)
{
return sc_compile(argc,argv);
}
/* sc_printf
* Called for general purpose "console" output. This function prints general
* purpose messages; errors go through sc_error(). The function is modelled
* after printf().
*/
int sc_printf(const char *message,...)
{
int ret;
va_list argptr;
va_start(argptr,message);
ret=vprintf(message,argptr);
va_end(argptr);
return ret;
}
/* sc_error
* Called for producing error output.
* number the error number (as documented in the manual)
* message a string describing the error with embedded %d and %s tokens
* filename the name of the file currently being parsed
* firstline the line number at which the expression started on which
* the error was found, or -1 if there is no "starting line"
* lastline the line number at which the error was detected
* argptr a pointer to the first of a series of arguments (for macro
* "va_arg")
* Return:
* If the function returns 0, the parser attempts to continue compilation.
* On a non-zero return value, the parser aborts.
*/
int sc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr)
{
static char *prefix[3]={ "Error", "Fatal", "Warning" };
if (number!=0) {
char *pre;
pre=prefix[number/100];
if (firstline>=0)
printf("%s(%d -- %d) %s [%03d]: ",filename,firstline,lastline,pre,number);
else
printf("%s(%d) %s [%03d]: ",filename,lastline,pre,number);
} /* if */
vprintf(message,argptr);
fflush(stdout);
return 0;
}
/* sc_opensrc
* Opens a source file (or include file) for reading. The "file" does not have
* to be a physical file, one might compile from memory.
* filename the name of the "file" to read from
* Return:
* The function must return a pointer, which is used as a "magic cookie" to
* all I/O functions. When failing to open the file for reading, the
* function must return NULL.
*/
void *sc_opensrc(char *filename)
{
return fopen(filename,"rt");
}
/* sc_closesrc
* Closes a source file (or include file). The "handle" parameter has the
* value that sc_opensrc() returned in an earlier call.
*/
void sc_closesrc(void *handle)
{
assert(handle!=NULL);
fclose((FILE*)handle);
}
/* sc_resetsrc
* "position" may only hold a pointer that was previously obtained from
* sc_getpossrc() */
void sc_resetsrc(void *handle,void *position)
{
assert(handle!=NULL);
fsetpos((FILE*)handle,(fpos_t *)position);
}
char *sc_readsrc(void *handle,char *target,int maxchars)
{
return fgets(target,maxchars,(FILE*)handle);
}
void *sc_getpossrc(void *handle)
{
static fpos_t lastpos;
fgetpos((FILE*)handle,&lastpos);
return &lastpos;
}
int sc_eofsrc(void *handle)
{
return feof((FILE*)handle);
}
/* should return a pointer, which is used as a "magic cookie" to all I/O
* functions; return NULL for failure
*/
void *sc_openasm(char *filename)
{
return fopen(filename,"w+t");
}
void sc_closeasm(void *handle, int deletefile)
{
fclose((FILE*)handle);
if (deletefile)
unlink(outfname);
}
void sc_resetasm(void *handle)
{
fflush((FILE*)handle);
fseek((FILE*)handle,0,SEEK_SET);
}
int sc_writeasm(void *handle,char *st)
{
return fputs(st,(FILE*)handle) >= 0;
}
char *sc_readasm(void *handle, char *target, int maxchars)
{
return fgets(target,maxchars,(FILE*)handle);
}
/* Should return a pointer, which is used as a "magic cookie" to all I/O
* functions; return NULL for failure.
*/
void *sc_openbin(char *filename)
{
return fopen(filename,"wb");
}
void sc_closebin(void *handle,int deletefile)
{
fclose((FILE*)handle);
if (deletefile)
unlink(binfname);
}
void sc_resetbin(void *handle)
{
fflush((FILE*)handle);
fseek((FILE*)handle,0,SEEK_SET);
}
int sc_writebin(void *handle,void *buffer,int size)
{
return fwrite(buffer,1,size,(FILE*)handle) == size;
}
long sc_lengthbin(void *handle)
{
return ftell((FILE*)handle);
}

View File

@ -0,0 +1,47 @@
/*
* Things needed to compile under linux.
*
* Should be reworked totally to use GNU's 'configure'
*/
/*
* Getchar is not a 'cool' replacement for MSDOS getch: Linux/unix depends on the features activated or not about the
* controlling terminal's tty. This means that ioctl(2) calls must be performed, for instance to have the controlling terminal tty's
* in 'raw' mode, if we want to be able to fetch a single character. This also means that everything must be put back
* correctly when the program ends.
*
* For interactive use of SRUN/SDBG if would be much better to use GNU's readline package: the user would be able to have
* a complete emacs/vi like line editing system.
*
* So we stick to getchar at the moment... (one needs to key ctrl-d to terminate input if getch is called with a controlling
* terminal driven by a tty having -raw)
*/
#define getch getchar
#define stricmp(a,b) strcasecmp(a,b)
#define strnicmp(a,b,c) strncasecmp(a,b,c)
/*
* WinWorld wants '\'. Unices do not.
*/
#define DIRECTORY_SEP_CHAR '/'
#define DIRECTORY_SEP_STR "/"
/*
* SC assumes that a computer is Little Endian unless told otherwise. It uses
* (and defines) the macros BYTE_ORDER and BIG_ENDIAN.
* For Linux, we must overrule these settings with those defined in glibc.
*/
#if !defined __BYTE_ORDER
# include <stdlib.h>
#endif
#if defined __OpenBSD__
# define __BYTE_ORDER BYTE_ORDER
# define __LITTLE_ENDIAN LITTLE_ENDIAN
# define __BIG_ENDIAN BIG_ENDIAN
#endif
#if !defined __BYTE_ORDER
# error "Can't figure computer byte order (__BYTE_ORDER macro not found)"
#endif

View File

@ -0,0 +1,279 @@
/* Small compiler - maintenance of various lists
*
* Name list (aliases)
* Include path list
*
* Copyright (c) ITB CompuPhase, 2001-2003
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "embryo_cc_sc.h"
#if defined FORTIFY
#include "fortify.h"
#endif
/* a "private" implementation of strdup(), so that porting
* to other memory allocators becomes easier.
* By Søren Hannibal.
*/
SC_FUNC char* duplicatestring(const char* sourcestring)
{
char* result=malloc(strlen(sourcestring)+1);
strcpy(result,sourcestring);
return result;
}
static stringpair *insert_stringpair(stringpair *root,char *first,char *second,int matchlength)
{
stringpair *cur,*pred;
assert(root!=NULL);
assert(first!=NULL);
assert(second!=NULL);
/* create a new node, and check whether all is okay */
if ((cur=(stringpair*)malloc(sizeof(stringpair)))==NULL)
return NULL;
cur->first=duplicatestring(first);
cur->second=duplicatestring(second);
cur->matchlength=matchlength;
if (cur->first==NULL || cur->second==NULL) {
if (cur->first!=NULL)
free(cur->first);
if (cur->second!=NULL)
free(cur->second);
free(cur);
return NULL;
} /* if */
/* link the node to the tree, find the position */
for (pred=root; pred->next!=NULL && strcmp(pred->next->first,first)<0; pred=pred->next)
/* nothing */;
cur->next=pred->next;
pred->next=cur;
return cur;
}
static void delete_stringpairtable(stringpair *root)
{
stringpair *cur, *next;
assert(root!=NULL);
cur=root->next;
while (cur!=NULL) {
next=cur->next;
assert(cur->first!=NULL);
assert(cur->second!=NULL);
free(cur->first);
free(cur->second);
free(cur);
cur=next;
} /* while */
memset(root,0,sizeof(stringpair));
}
static stringpair *find_stringpair(stringpair *cur,char *first,int matchlength)
{
int result=0;
assert(matchlength>0); /* the function cannot handle zero-length comparison */
assert(first!=NULL);
while (cur!=NULL && result<=0) {
result=(int)*cur->first - (int)*first;
if (result==0 && matchlength==cur->matchlength) {
result=strncmp(cur->first,first,matchlength);
if (result==0)
return cur;
} /* if */
cur=cur->next;
} /* while */
return NULL;
}
static int delete_stringpair(stringpair *root,stringpair *item)
{
stringpair *cur;
assert(root!=NULL);
cur=root;
while (cur->next!=NULL) {
if (cur->next==item) {
cur->next=item->next; /* unlink from list */
assert(item->first!=NULL);
assert(item->second!=NULL);
free(item->first);
free(item->second);
free(item);
return TRUE;
} /* if */
cur=cur->next;
} /* while */
return FALSE;
}
/* ----- alias table --------------------------------------------- */
static stringpair alias_tab = {NULL, NULL, NULL}; /* alias table */
SC_FUNC stringpair *insert_alias(char *name,char *alias)
{
stringpair *cur;
assert(name!=NULL);
assert(strlen(name)<=sNAMEMAX);
assert(alias!=NULL);
assert(strlen(alias)<=sEXPMAX);
if ((cur=insert_stringpair(&alias_tab,name,alias,strlen(name)))==NULL)
error(103); /* insufficient memory (fatal error) */
return cur;
}
SC_FUNC stringpair *find_alias(char *name)
{
return find_stringpair(alias_tab.next,name,strlen(name));
}
SC_FUNC int lookup_alias(char *target,char *name)
{
stringpair *cur=find_stringpair(alias_tab.next,name,strlen(name));
if (cur!=NULL) {
assert(strlen(cur->second)<=sEXPMAX);
strcpy(target,cur->second);
} /* if */
return cur!=NULL;
}
SC_FUNC void delete_aliastable(void)
{
delete_stringpairtable(&alias_tab);
}
/* ----- include paths list -------------------------------------- */
static stringlist includepaths = {NULL, NULL}; /* directory list for include files */
SC_FUNC stringlist *insert_path(char *path)
{
stringlist *cur;
assert(path!=NULL);
if ((cur=(stringlist*)malloc(sizeof(stringlist)))==NULL)
error(103); /* insufficient memory (fatal error) */
if ((cur->line=duplicatestring(path))==NULL)
error(103); /* insufficient memory (fatal error) */
cur->next=includepaths.next;
includepaths.next=cur;
return cur;
}
SC_FUNC char *get_path(int index)
{
stringlist *cur = includepaths.next;
while (cur!=NULL && index-->0)
cur=cur->next;
if (cur!=NULL) {
assert(cur->line!=NULL);
return cur->line;
} /* if */
return NULL;
}
SC_FUNC void delete_pathtable(void)
{
stringlist *cur=includepaths.next, *next;
while (cur!=NULL) {
next=cur->next;
assert(cur->line!=NULL);
free(cur->line);
free(cur);
cur=next;
} /* while */
memset(&includepaths,0,sizeof(stringlist));
}
/* ----- text substitution patterns ------------------------------ */
#if !defined NO_DEFINE
static stringpair substpair = { NULL, NULL, NULL}; /* list of substitution pairs */
static stringpair *substindex['z'-'A'+1]; /* quick index to first character */
static void adjustindex(char c)
{
stringpair *cur;
assert(c>='A' && c<='Z' || c>='a' && c<='z' || c=='_');
assert('A'<'_' && '_'<'z');
for (cur=substpair.next; cur!=NULL && cur->first[0]!=c; cur=cur->next)
/* nothing */;
substindex[(int)c-'A']=cur;
}
SC_FUNC stringpair *insert_subst(char *pattern,char *substitution,int prefixlen)
{
stringpair *cur;
assert(pattern!=NULL);
assert(substitution!=NULL);
if ((cur=insert_stringpair(&substpair,pattern,substitution,prefixlen))==NULL)
error(103); /* insufficient memory (fatal error) */
adjustindex(*pattern);
return cur;
}
SC_FUNC stringpair *find_subst(char *name,int length)
{
stringpair *item;
assert(name!=NULL);
assert(length>0);
assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_');
item=substindex[(int)*name-'A'];
if (item!=NULL)
item=find_stringpair(item,name,length);
return item;
}
SC_FUNC int delete_subst(char *name,int length)
{
stringpair *item;
assert(name!=NULL);
assert(length>0);
assert(*name>='A' && *name<='Z' || *name>='a' && *name<='z' || *name=='_');
item=substindex[(int)*name-'A'];
if (item!=NULL)
item=find_stringpair(item,name,length);
if (item==NULL)
return FALSE;
delete_stringpair(&substpair,item);
adjustindex(*name);
return TRUE;
}
SC_FUNC void delete_substtable(void)
{
int i;
delete_stringpairtable(&substpair);
for (i=0; i<sizeof substindex/sizeof substindex[0]; i++)
substindex[i]=NULL;
}
#endif /* !defined NO_SUBST */

View File

@ -0,0 +1,450 @@
/* compress.c -- Byte Pair Encoding compression */
/* Copyright 1996 Philip Gage */
/* This program appeared in the September 1997 issue of
* C/C++ Users Journal. The original source code may still
* be found at the web site of the magazine (www.cuj.com).
*
* It has been modified by me (Thiadmer Riemersma) to
* compress only a section of the input file and to store
* the compressed output along with the input as "C" strings.
*
* Compiling instructions:
* Borland C++ 16-bit (large memory model is required):
* bcc -ml scpack.c
*
* Watcom C/C++ 32-bit:
* wcl386 scpack.c
*
* GNU C (Linux), 32-bit:
* gcc scpack.c -o scpack
*/
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if UINT_MAX > 0xFFFFU
#define MAXSIZE 1024*1024L
#else
#define MAXSIZE UINT_MAX /* Input file buffer size */
#endif
#define HASHSIZE 8192 /* Hash table size, power of 2 */
#define THRESHOLD 3 /* Increase for speed, min 3 */
#define START_TOKEN "#ifdef SCPACK" /* start reading the buffer here */
#define NAME_TOKEN "#define SCPACK_TABLE"
#define SEP_TOKEN "#define SCPACK_SEPARATOR"
#define TERM_TOKEN "#define SCPACK_TERMINATOR"
#define TEMPFILE "~SCPACK.TMP"
static char tablename[32+1] = "scpack_table";
static char separator[16]=",";
static char terminator[16]="";
int compress(unsigned char *buffer, unsigned buffersize, unsigned char pairtable[128][2])
{
unsigned char *left, *right, *count;
unsigned char a, b, bestcount;
unsigned i, j, index, bestindex, code=128;
/* Dynamically allocate buffers and check for errors */
left = (unsigned char *)malloc(HASHSIZE);
right = (unsigned char *)malloc(HASHSIZE);
count = (unsigned char *)malloc(HASHSIZE);
if (left==NULL || right==NULL || count==NULL) {
printf("Error allocating memory\n");
exit(1);
}
/* Check for errors */
for (i=0; i<buffersize; i++)
if (buffer[i] > 127) {
printf("This program works only on text files (7-bit ASCII)\n");
exit(1);
}
memset(pairtable, 0, 128*2*sizeof(char));
do { /* Replace frequent pairs with bytes 128..255 */
/* Enter counts of all byte pairs into hash table */
memset(count,0,HASHSIZE);
for (i=0; i<buffersize-1; i++) {
a = buffer[i];
b = buffer[i+1];
/* ignore any pair with a '\0' */
if (a == 0 || b == 0)
continue;
index = (a ^ (b << 6)) & (HASHSIZE-1);
while ((left[index] != a || right[index] != b) &&
count[index] != 0)
index = (index + 1) & (HASHSIZE-1);
left[index] = a;
right[index] = b;
if (count[index] < 255)
count[index] += (unsigned char)1;
}
/* Search hash table for most frequent pair */
bestcount = THRESHOLD - 1;
for (i=0; i<HASHSIZE; i++) {
if (count[i] > bestcount) {
bestcount = count[i];
bestindex = i;
}
}
/* Compress if enough occurrences of pair */
if (bestcount >= THRESHOLD) {
/* Add pair to table using code as index */
a = pairtable[code-128][0] = left[bestindex];
b = pairtable[code-128][1] = right[bestindex];
/* Replace all pair occurrences with unused byte */
for (i=0, j=0; i<buffersize; i++, j++)
if (a == buffer[i] && b == buffer[i+1]) {
buffer[j] = (unsigned char)code;
++i;
}
else
buffer[j] = buffer[i];
buffersize = j;
}
else
break;
} while (++code < 255);
/* done */
free(left); free(right); free(count);
return buffersize; /* return adjusted buffersize */
}
static int strmatch(char *str, char *token, int *indent)
{
int i = 0;
/* skip whitespace */
while (*str==' ' || *str=='\t') {
str++;
i++;
} /* while */
if (strncmp(str,token,strlen(token))!=0)
return 0;
if (indent != NULL)
*indent = i;
return 1;
}
static void check_if(char *str,int linenr)
{
if (strmatch(str,"#if",NULL)) {
printf("Error: \"#if...\" preprocessor statement should not be in SCPACK section "
"(line %d)\n", linenr);
exit(1);
} /* if */
}
static int check_tablename(char *str)
{
int i;
if (strmatch(str,NAME_TOKEN,NULL)) {
str += strlen(NAME_TOKEN);
while (*str==' ' || *str=='\t')
str++;
for (i=0; i<(sizeof tablename - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++)
tablename[i] = *str;
tablename[i] = '\0';
return 1;
} /* if */
return 0;
}
static int check_separator(char *str)
{
int i;
if (strmatch(str,SEP_TOKEN,NULL)) {
str += strlen(SEP_TOKEN);
while (*str==' ' || *str=='\t')
str++;
for (i=0; i<(sizeof separator - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++)
separator[i] = *str;
separator[i] = '\0';
return 1;
} /* if */
if (strmatch(str,TERM_TOKEN,NULL)) {
str += strlen(TERM_TOKEN);
while (*str==' ' || *str=='\t')
str++;
for (i=0; i<(sizeof terminator - 1) && *str!='\0' && strchr(" \t\n",*str)==NULL; i++, str++)
terminator[i] = *str;
terminator[i] = '\0';
return 1;
} /* if */
return 0;
}
/* readbuffer
* Reads in the input file and stores all strings in the
* section between "#ifdef SCPACK" and "#else" in a buffer.
* Only text that is between double quotes is added to the
* buffer; the \" escape code is handled. Multiple strings
* on one line are handled.
*/
unsigned readbuffer(FILE *input, unsigned char *buffer)
{
char str[256];
unsigned buffersize;
int i,linenr;
linenr=0;
buffersize=0;
rewind(input);
while (!feof(input)) {
while (fgets(str,sizeof str,input)!=NULL) {
linenr++;
check_tablename(str);
check_separator(str);
if (strmatch(str,START_TOKEN,NULL))
break;
} /* while */
if (!strmatch(str,START_TOKEN,NULL))
return buffersize; /* no (more) section found, quit */
while (fgets(str,sizeof str,input)!=NULL) {
linenr++;
check_if(str,linenr);
if (check_tablename(str))
printf("Error: table name definition should not be in SCPACK section (line %d)\n", linenr);
check_separator(str);
if (strmatch(str,"#else",NULL))
break; /* done */
/* add to the buffer only what is between double quotes */
i=0;
do {
while (str[i]!='\0' && str[i]!='"')
i++;
if (str[i]=='"') {
/* we are in a string */
i++;
while (str[i]!='\0' && str[i]!='"') {
/* handle escape sequences */
if (str[i]=='\\') {
i++;
switch (str[i]) {
case 'a': /* alarm */
buffer[buffersize++]='\a';
i++;
break;
case 'b': /* backspace */
buffer[buffersize++]='\b';
i++;
break;
case 'f': /* form feed */
buffer[buffersize++]='\f';
i++;
break;
case 'n': /* newline */
buffer[buffersize++]='\n';
i++;
break;
case 'r': /* carriage return */
buffer[buffersize++]='\n';
i++;
break;
case 't': /* tab */
buffer[buffersize++]='\t';
i++;
break;
case '\'':
buffer[buffersize++]='\'';
i++;
break;
case '"':
buffer[buffersize++]='"';
i++;
break;
default:
// ??? octal character code escapes and hexadecimal escapes
// not supported
printf("Unknown escape sequence '\\%c' on line %d\n",
str[i], linenr);
} /* switch */
} else {
buffer[buffersize++]=str[i++];
} /* if */
} /* while */
if (str[i]=='"') {
buffer[buffersize++]='\0'; /* terminate each string */
i++;
} else {
printf("Error: unterminated string on line %d\n",linenr);
} /* if */
} /* if */
} while (str[i]!='\0');
} /* while - in SCPACK section */
/* put in another '\0' to terminate the section */
buffer[buffersize++]='\0';
} /* while - !feof(input) */
return buffersize;
}
static void write_pairtable(FILE *output, unsigned char pairtable[128][2], char *tablename)
{
int i;
/* dump the pair table */
fprintf(output, "/*-*SCPACK start of pair table, do not change or remove this line */\n");
fprintf(output, "unsigned char %s[][2] = {", tablename);
for (i=0; i<128 && pairtable[i][0]!=0 && pairtable[i][1]!=0; i++) {
if ((i % 16)==0)
fprintf(output, "\n ");
else
fprintf(output, " ");
fprintf(output, "{%d,%d}", pairtable[i][0], pairtable[i][1]);
/* check if something follows this pair */
if (i+1<128 && pairtable[i+1][0]!=0 && pairtable[i+1][1]!=0)
fprintf(output, ",");
} /* for */
fprintf(output, "\n};\n");
fprintf(output, "/*-*SCPACK end of pair table, do not change or remove this line */\n");
}
void writefile(FILE *input, FILE *output, unsigned char *buffer, unsigned buffersize, unsigned char pairtable[128][2])
{
char str[256];
int insection, indent, needseparator;
unsigned char *bufptr;
bufptr = buffer;
insection = 0;
rewind(input);
while (!feof(input)) {
while (fgets(str,sizeof str,input)!=NULL) {
fprintf(output,"%s",str);
if (check_tablename(str)) {
write_pairtable(output, pairtable, tablename);
/* strip an existing pair table from the file */
if (fgets(str,sizeof str,input)!=NULL) {
if (strmatch(str,"/*-*SCPACK",NULL)) {
while (fgets(str,sizeof str,input)!=NULL)
if (strmatch(str,"/*-*SCPACK",NULL))
break;
} else {
fprintf(output,"%s",str);
} /* if */
} /* if */
} /* if */
if (strmatch(str,START_TOKEN,NULL))
insection = 1;
if (insection && strmatch(str,"#else",NULL))
break;
} /* while */
if (!strmatch(str,"#else",&indent))
return; /* no (more) section found, quit */
insection=0;
/* dump the buffer as strings, separated with commas */
needseparator = 0;
while (*bufptr != '\0') {
assert((unsigned)(bufptr-buffer) < buffersize);
if (needseparator)
fprintf(output, "%s\n",separator);
fprintf(output, "%*c\"",indent+2,' ');
/* loop over string */
while (*bufptr != '\0') {
if (*bufptr<' ' || *bufptr >= 128 || *bufptr == '"' || *bufptr == '\\')
fprintf(output, "\\%03o", *bufptr);
else
fprintf(output, "%c", *bufptr);
bufptr++;
} /* while */
fprintf(output, "\"");
needseparator = 1;
bufptr++; /* skip '\0' */
} /* while */
fprintf(output, "%s\n",terminator);
bufptr++;
/* skip the input file until the #endif section */
while (fgets(str,sizeof str,input)!=NULL) {
if (strmatch(str,"#endif",NULL)) {
fprintf(output,"%s",str);
break; /* done */
} /* if */
} /* while */
} /* while - !feof(input) */
}
static void usage(void)
{
printf("Usage: scpack <filename> [output file]\n");
exit(1);
}
int main(int argc, char **argv)
{
FILE *in, *out;
unsigned char *buffer;
unsigned buffersize, orgbuffersize;
unsigned char pairtable[128][2];
if (argc < 2 || argc > 3)
usage();
if ((in=fopen(argv[1],"rt"))==NULL) {
printf("SCPACK: error opening input %s\n",argv[1]);
usage();
} /* if */
if (argc == 2) {
if ((out=fopen(TEMPFILE,"wt"))==NULL) {
printf("SCPACK: error opening temporary file %s\n",TEMPFILE);
usage();
} /* if */
} else {
if ((out=fopen(argv[2],"wt"))==NULL) {
printf("SCPACK: error opening output file %s\n",argv[2]);
usage();
} /* if */
} /* if */
buffer = (unsigned char *)malloc(MAXSIZE);
if (buffer == NULL) {
printf("SCPACK: error allocating memory\n");
return 1;
} /* if */
/* 1. read the buffer
* 2. compress the buffer
* 3. copy the file, insert the compressed buffer
*/
buffersize = readbuffer(in, buffer);
orgbuffersize = buffersize;
if (buffersize > 0) {
buffersize = compress(buffer, buffersize, pairtable);
writefile(in, out, buffer, buffersize, pairtable);
printf("SCPACK: compression ratio: %ld%% (%d -> %d)\n",
100L-(100L*buffersize)/orgbuffersize, orgbuffersize, buffersize);
} else {
printf("SCPACK: no SCPACK section found, nothing to do\n");
} /* if */
fclose(out);
fclose(in);
/* let the new file replace the old file */
if (buffersize == 0) {
if (argc == 2)
unlink(TEMPFILE);
else
unlink(argv[2]);
} else if (argc == 2) {
unlink(argv[1]);
rename(TEMPFILE,argv[1]);
} /* if */
return 0;
}

View File

@ -0,0 +1,29 @@
#include <process.h>
#include <stdio.h>
#include <string.h>
static char filename[] = "scdos.exe";
int main(int argc, char *argv[])
{
int result;
/* build a command line to pass on to the "DOS" program */
char path[80], *ptr;
strcpy(path,argv[0]);
ptr=strrchr(path,'\\');
if (ptr==NULL)
ptr=strchr(path,':');
if (ptr==NULL) {
strcpy(path,filename);
} else {
strcpy(ptr+1,filename);
} /* if */
/* launch the DOS version of the tool */
result=execv(path,argv);
if (result==-1)
printf("Error launching '%s'\n",path);
return result;
}

View File

@ -0,0 +1,99 @@
/* Small compiler
*
* Global (cross-module) variables.
*
* Copyright (c) ITB CompuPhase, 1997-2003
*
* This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* Version: $Id$
*/
#include <stdio.h>
#include <stdlib.h> /* for _MAX_PATH */
#include "embryo_cc_sc.h"
/* global variables
*
* All global variables that are shared amongst the compiler files are
* declared here.
*/
SC_VDEFINE symbol loctab; /* local symbol table */
SC_VDEFINE symbol glbtab; /* global symbol table */
SC_VDEFINE cell *litq; /* the literal queue */
SC_VDEFINE char pline[sLINEMAX+1]; /* the line read from the input file */
SC_VDEFINE char *lptr; /* points to the current position in "pline" */
SC_VDEFINE constvalue tagname_tab = { NULL, "", 0, 0}; /* tagname table */
SC_VDEFINE constvalue libname_tab = { NULL, "", 0, 0}; /* library table (#pragma library "..." syntax) */
SC_VDEFINE constvalue *curlibrary = NULL;/* current library */
SC_VDEFINE symbol *curfunc; /* pointer to current function */
SC_VDEFINE char *inpfname; /* pointer to name of the file currently read from */
SC_VDEFINE char outfname[_MAX_PATH]; /* output file name */
SC_VDEFINE char errfname[_MAX_PATH]; /* error file name */
SC_VDEFINE char sc_ctrlchar = CTRL_CHAR;/* the control character (or escape character)*/
SC_VDEFINE int litidx = 0; /* index to literal table */
SC_VDEFINE int litmax = sDEF_LITMAX;/* current size of the literal table */
SC_VDEFINE int stgidx = 0; /* index to the staging buffer */
SC_VDEFINE int labnum = 0; /* number of (internal) labels */
SC_VDEFINE int staging = 0; /* true if staging output */
SC_VDEFINE cell declared = 0; /* number of local cells declared */
SC_VDEFINE cell glb_declared=0; /* number of global cells declared */
SC_VDEFINE cell code_idx = 0; /* number of bytes with generated code */
SC_VDEFINE int ntv_funcid= 0; /* incremental number of native function */
SC_VDEFINE int errnum = 0; /* number of errors */
SC_VDEFINE int warnnum = 0; /* number of warnings */
SC_VDEFINE int sc_debug = sCHKBOUNDS; /* by default: bounds checking+assertions */
SC_VDEFINE int charbits = 8; /* a "char" is 8 bits */
SC_VDEFINE int sc_packstr= FALSE; /* strings are packed by default? */
SC_VDEFINE int sc_asmfile= FALSE; /* create .ASM file? */
SC_VDEFINE int sc_listing= FALSE; /* create .LST file? */
SC_VDEFINE int sc_compress=TRUE; /* compress bytecode? */
SC_VDEFINE int sc_needsemicolon=TRUE;/* semicolon required to terminate expressions? */
SC_VDEFINE int sc_dataalign=sizeof(cell);/* data alignment value */
SC_VDEFINE int sc_alignnext=FALSE; /* must frame of the next function be aligned? */
SC_VDEFINE int curseg = 0; /* 1 if currently parsing CODE, 2 if parsing DATA */
SC_VDEFINE cell sc_stksize=sDEF_AMXSTACK;/* default stack size */
SC_VDEFINE int freading = FALSE; /* Is there an input file ready for reading? */
SC_VDEFINE int fline = 0; /* the line number in the current file */
SC_VDEFINE int fnumber = 0; /* the file number in the file table (debugging) */
SC_VDEFINE int fcurrent = 0; /* current file being processed (debugging) */
SC_VDEFINE int intest = 0; /* true if inside a test */
SC_VDEFINE int sideeffect= 0; /* true if an expression causes a side-effect */
SC_VDEFINE int stmtindent= 0; /* current indent of the statement */
SC_VDEFINE int indent_nowarn=FALSE;/* skip warning "217 loose indentation" */
SC_VDEFINE int sc_tabsize=8; /* number of spaces that a TAB represents */
SC_VDEFINE int sc_allowtags=TRUE; /* allow/detect tagnames in lex() */
SC_VDEFINE int sc_status; /* read/write status */
SC_VDEFINE int sc_rationaltag=0; /* tag for rational numbers */
SC_VDEFINE int rational_digits=0; /* number of fractional digits */
SC_VDEFINE FILE *inpf = NULL; /* file read from (source or include) */
SC_VDEFINE FILE *inpf_org= NULL; /* main source file */
SC_VDEFINE FILE *outf = NULL; /* file written to */
SC_VDEFINE jmp_buf errbuf;
#if !defined SC_LIGHT
SC_VDEFINE int sc_makereport=FALSE; /* generate a cross-reference report */
#endif
#if defined __WATCOMC__ && !defined NDEBUG
/* Watcom's CVPACK dislikes .OBJ files without functions */
static int dummyfunc(void)
{
return 0;
}
#endif

View File

@ -0,0 +1,235 @@
#include "Embryo.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <limits.h>
#include <stdarg.h>
#include <string.h>
/* debugging native calls */
static int dochar(Embryo_Program *ep, char ch, Embryo_Cell param);
static int doesc(Embryo_Program *ep, char ch, Embryo_Cell param);
static int printstring(Embryo_Program *ep, Embryo_Cell *cstr, Embryo_Cell *params, int num);
static int
dochar(Embryo_Program * ep, char ch, Embryo_Cell param)
{
Embryo_Cell *cptr;
switch (ch)
{
case '%':
putchar(ch);
return 0;
case 'c':
cptr = embryo_data_address_get(ep, param);
if (cptr)
putchar((int) *cptr);
return 1;
case 'i':
case 'd':
cptr = embryo_data_address_get(ep, param);
if (cptr)
printf("%i", (int) *cptr);
return 1;
case 'x':
cptr = embryo_data_address_get(ep, param);
if (cptr)
printf("%x", (unsigned int) *cptr);
return 1;
case 'f':
cptr = embryo_data_address_get(ep, param);
if (cptr)
printf("%f", (float)(*(float *)cptr));
return 1;
case 'X':
cptr = embryo_data_address_get(ep, param);
if (cptr)
printf("%08x", (unsigned int) *cptr);
return 1;
case 's':
cptr = embryo_data_address_get(ep, param);
if (cptr)
printstring(ep, cptr, NULL, 0);
return 1;
}
putchar(ch);
return 0;
}
static int
doesc(Embryo_Program * ep, char ch, Embryo_Cell param)
{
Embryo_Cell *cptr;
switch (ch)
{
case 'n':
putchar('\n');
return 1;
case 't':
putchar('\t');
return 1;
}
putchar(ch);
return 0;
}
static int
printstring(Embryo_Program * ep, Embryo_Cell *cstr, Embryo_Cell *params, int num)
{
int i;
int informat = 0, paramidx = 0, inesc = 0, len = 0;
int j = sizeof(Embryo_Cell) - sizeof(char);
char c;
char *str;
/* the string is packed */
i = 0;
len = embryo_data_string_length_get(ep, cstr);
str = alloca(len + 1);
embryo_data_string_get(ep, cstr, str);
for (i = 0;; i++) {
c = (char) (str[i]);
if (c == 0)
break;
if (informat) {
paramidx += dochar(ep, c, params[paramidx]);
informat = 0;
} else if (inesc) {
doesc(ep, c, params[paramidx]);
inesc = 0;
} else if (params != NULL && c == '%') {
informat = 1;
} else if (params != NULL && c == '\\') {
inesc = 1;
} else {
putchar(c);
} /* if */
} /* for */
return EMBRYO_ERROR_NONE;
}
static Embryo_Cell
exported_printf(Embryo_Program *ep, Embryo_Cell *params)
{
Embryo_Cell *cptr;
// params[0] = number of bytes params passed
cptr = embryo_data_address_get(ep, params[1]);
printstring(ep, cptr, params + 2, (int) (params[0] / sizeof(Embryo_Cell)) - 1);
fflush(stdout);
return EMBRYO_ERROR_NONE;
}
static Embryo_Cell
exported_call(Embryo_Program *ep, Embryo_Cell *params)
{
Embryo_Cell *cptr;
// params[0] = number of bytes of params passed
cptr = embryo_data_address_get(ep, params[1]);
if (cptr)
{
char buf[4096];
buf[0] = 0;
printf("..");
embryo_data_string_get(ep, cptr, buf);
printf("OUT: \"%s\"", buf);
}
cptr = embryo_data_address_get(ep, params[3]);
if (cptr)
{
char buf[4096];
buf[0] = 0;
embryo_data_string_get(ep, cptr, buf);
printf(" \"%s\"", buf);
}
{
int v;
v = params[3];
printf(" %i", v);
}
printf("\n");
return 10;
}
void
exit_error(Embryo_Program *ep, int errorcode)
{
printf("Run time error %d: \"%s\"\n",
errorcode,
embryo_error_string_get(errorcode));
exit(-1);
}
void PrintUsage(char *program)
{
printf("Usage: %s <filename>\n", program);
exit(1);
}
int
main(int argc,char *argv[])
{
Embryo_Program *ep;
Embryo_Cell val;
Embryo_Function fn;
int r;
int err;
if (argc != 2)
{
printf("Usage: %s <filename>\n", argv[0]);
exit(-1);
}
ep = embryo_program_load(argv[1]);
if (!ep)
{
printf("Cannot load %s\n", argv[1]);
exit(-1);
}
embryo_program_native_call_add(ep, "call", exported_call);
embryo_program_native_call_add(ep, "printf", exported_printf);
embryo_program_vm_push(ep);
val = embryo_program_variable_find(ep, "global1");
if (val != EMBRYO_CELL_NONE)
{
Embryo_Cell *addr;
addr = embryo_data_address_get(ep, val);
if (addr) printf("Global variable value = %i\n", (int)*addr);
}
else
printf("Cannot find variable\n");
fn = embryo_program_function_find(ep, "testfn");
if (fn != EMBRYO_FUNCTION_NONE)
{
printf("Found testfn()\n");
embryo_parameter_cell_push(ep, 9876);
embryo_parameter_string_push(ep, "K is a dirty fish");
embryo_parameter_cell_push(ep, 127);
while ((r = embryo_program_run(ep, fn)) == EMBRYO_PROGRAM_SLEEP);
if (r == EMBRYO_PROGRAM_FAIL) printf("Run failed!\n");
}
else
{
printf("Runing main()\n");
while ((r = embryo_program_run(ep, EMBRYO_FUNCTION_MAIN)) == EMBRYO_PROGRAM_SLEEP);
if (r == EMBRYO_PROGRAM_FAIL) printf("Run failed!\n");
}
embryo_program_vm_pop(ep);
err = embryo_program_error_get(ep);
if (err != EMBRYO_ERROR_NONE) exit_error(ep, err);
printf("Program %s returns %i\n", argv[1], embryo_program_return_value_get(ep));
embryo_program_free(ep);
return 0;
}

View File

@ -0,0 +1,98 @@
#ifndef _EMBRYO_H
#define _EMBRYO_H
/*
* FIXME:
* handle the case where:
* [C] -> [vm] -> [native call] -> [same or other func in same vm]
*/
#ifdef __cplusplus
extern "C" {
#endif
/* potentioal error values */
enum
{
EMBRYO_ERROR_NONE,
/* reserve the first 15 error codes for exit codes of the abstract machine */
EMBRYO_ERROR_EXIT, /* forced exit */
EMBRYO_ERROR_ASSERT, /* assertion failed */
EMBRYO_ERROR_STACKERR, /* stack/heap collision */
EMBRYO_ERROR_BOUNDS, /* index out of bounds */
EMBRYO_ERROR_MEMACCESS, /* invalid memory access */
EMBRYO_ERROR_INVINSTR, /* invalid instruction */
EMBRYO_ERROR_STACKLOW, /* stack underflow */
EMBRYO_ERROR_HEAPLOW, /* heap underflow */
EMBRYO_ERROR_CALLBACK, /* no callback, or invalid callback */
EMBRYO_ERROR_NATIVE, /* native function failed */
EMBRYO_ERROR_DIVIDE, /* divide by zero */
EMBRYO_ERROR_SLEEP, /* go into sleepmode - code can be restarted */
EMBRYO_ERROR_MEMORY = 16, /* out of memory */
EMBRYO_ERROR_FORMAT, /* invalid file format */
EMBRYO_ERROR_VERSION, /* file is for a newer version of the Embryo_Program */
EMBRYO_ERROR_NOTFOUND, /* function not found */
EMBRYO_ERROR_INDEX, /* invalid index parameter (bad entry point) */
EMBRYO_ERROR_DEBUG, /* debugger cannot run */
EMBRYO_ERROR_INIT, /* Embryo_Program not initialized (or doubly initialized) */
EMBRYO_ERROR_USERDATA, /* unable to set user data field (table full) */
EMBRYO_ERROR_INIT_JIT, /* cannot initialize the JIT */
EMBRYO_ERROR_PARAMS, /* parameter error */
EMBRYO_ERROR_DOMAIN, /* domain error, expression result does not fit in range */
};
/* possible function type values that are enumerated */
#define EMBRYO_FUNCTION_NONE 0x7fffffff /* an invalid/non existant function */
#define EMBRYO_FUNCTION_MAIN -1 /* start at program entry point */
#define EMBRYO_FUNCTION_CONT -2 /* continue from last address */
/* an invalid cell reference */
#define EMBRYO_CELL_NONE 0x7fffffff /* an invalid cell reference */
/* program run return values */
#define EMBRYO_PROGRAM_OK 1
#define EMBRYO_PROGRAM_SLEEP 2
#define EMBRYO_PROGRAM_BUSY 3
#define EMBRYO_PROGRAM_FAIL 0
#define EMBRYO_FLOAT_TO_CELL(f) ( *((Embryo_Cell*)&f)) /* float to Embryo_Cell */
#define EMBRYO_CELL_TO_FLOAT(c) ( *((float*)&c)) /* Embryo_Cell to float */
typedef unsigned int Embryo_UCell;
typedef int Embryo_Cell;
typedef struct _Embryo_Program Embryo_Program;
typedef int Embryo_Function;
int embryo_init(void);
int embryo_shutdown(void);
Embryo_Program *embryo_program_new(void *data, int size);
Embryo_Program *embryo_program_const_new(void *data, int size);
Embryo_Program *embryo_program_load(char *file);
void embryo_program_free(Embryo_Program *ep);
void embryo_program_native_call_add(Embryo_Program *ep, char *name, Embryo_Cell (*func) (Embryo_Program *ep, Embryo_Cell *params));
void embryo_program_vm_reset(Embryo_Program *ep);
void embryo_program_vm_push(Embryo_Program *ep);
void embryo_program_vm_pop(Embryo_Program *ep);
void embryo_swap_16(unsigned short *v);
void embryo_swap_32(unsigned int *v);
Embryo_Function embryo_program_function_find(Embryo_Program *ep, char *name);
Embryo_Cell embryo_program_variable_find(Embryo_Program *ep, char *name);
void embryo_program_error_set(Embryo_Program *ep, int error);
int embryo_program_error_get(Embryo_Program *ep);
const char *embryo_error_string_get(int error);
int embryo_data_string_length_get(Embryo_Program *ep, Embryo_Cell *str_cell);
void embryo_data_string_get(Embryo_Program *ep, Embryo_Cell *str_cell, char *dst);
void embryo_data_string_set(Embryo_Program *ep, char *src, Embryo_Cell *str_cell);
Embryo_Cell *embryo_data_address_get(Embryo_Program *ep, Embryo_Cell addr);
Embryo_Cell embryo_data_heap_push(Embryo_Program *ep, int cells);
void embryo_data_heap_pop(Embryo_Program *ep, Embryo_Cell down_to);
int embryo_program_run(Embryo_Program *ep, Embryo_Function func);
Embryo_Cell embryo_program_return_value_get(Embryo_Program *ep);
int embryo_parameter_cell_push(Embryo_Program *ep, Embryo_Cell cell);
int embryo_parameter_string_push(Embryo_Program *ep, char *str);
int embryo_parameter_cell_array_push(Embryo_Program *ep, Embryo_Cell *cells, int num);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,24 @@
## Process this file with automake to produce Makefile.in
AUTOMAKE_OPTIONS = 1.4 foreign
# A list of all the files in the current directory which can be regenerated
MAINTAINERCLEANFILES = Makefile.in
LDFLAGS =
INCLUDES = -I. \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib/include
lib_LTLIBRARIES = libembryo.la
include_HEADERS = Embryo.h
libembryo_la_SOURCES = \
embryo_amx.c \
embryo_float.c \
embryo_main.c \
embryo_private.h
libembryo_la_LIBADD = $(LDFLAGS) -lm
libembryo_la_DEPENDENCIES = $(top_builddir)/config.h
libembryo_la_LDFLAGS = -version-info 1:0:0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,306 @@
/* Float arithmetic for the Small AMX engine
*
* Copyright (c) Artran, Inc. 1999
* Written by Greg Garner (gmg@artran.com)
* This file may be freely used. No warranties of any kind.
* Portions Copyright (c) Carsten Haitzler, 2004 <raster@rasterman.com>
*
* CHANGES -
* 2002-08-27: Basic conversion of source from C++ to C by Adam D. Moss
* <adam@gimp.org> <aspirin@icculus.org>
* 2003-08-29: Removal of the dynamic memory allocation and replacing two
* type conversion functions by macros, by Thiadmer Riemersma
* 2003-09-22: Moved the type conversion macros to AMX.H, and simplifications
* of some routines, by Thiadmer Riemersma
* 2003-11-24: A few more native functions (geometry), plus minor modifications,
* mostly to be compatible with dynamically loadable extension
* modules, by Thiadmer Riemersma
* 2004-03-20: Cleaned up and reduced size for Embryo, Modified to conform to
* E coding style. Added extra parameter checks.
* Carsten Haitzler, <raster@rasterman.com>
*/
#include <math.h>
#include "embryo_private.h"
#define PI 3.1415926535897932384626433832795
/* internally useful calls */
static float
_embryo_fp_degrees_to_radians(float angle, int radix)
{
switch (radix)
{
case 1: /* degrees, sexagesimal system (technically: degrees/minutes/seconds) */
return (float)(angle * PI / 180.0);
case 2: /* grades, centesimal system */
return (float)(angle * PI / 200.0);
default: /* assume already radian */
break;
}
return angle;
}
/* exported float api */
static Embryo_Cell
_embryo_fp(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = long value to convert to a float */
float f;
if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
f = (float)params[1];
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_str(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = virtual string address to convert to a float */
char buf[64];
Embryo_Cell *str;
float f;
int len;
if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
str = embryo_data_address_get(ep, params[1]);
len = embryo_data_string_length_get(ep, str);
if ((len == 0) || (len >= sizeof(buf))) return 0;
embryo_data_string_get(ep, str, buf);
f = (float)atof(buf);
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_mul(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand 1 */
/* params[2] = float operand 2 */
float f;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]) * EMBRYO_CELL_TO_FLOAT(params[2]);
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_div(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float dividend (top) */
/* params[2] = float divisor (bottom) */
float f;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]) / EMBRYO_CELL_TO_FLOAT(params[2]);
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_add(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand 1 */
/* params[2] = float operand 2 */
float f;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]) + EMBRYO_CELL_TO_FLOAT(params[2]);
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_sub(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand 1 */
/* params[2] = float operand 2 */
float f;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]) - EMBRYO_CELL_TO_FLOAT(params[2]);
return EMBRYO_FLOAT_TO_CELL(f);
}
/* Return fractional part of float */
static Embryo_Cell
_embryo_fp_fract(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand */
float f;
if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]);
f -= (float)(floor((double)f));
return EMBRYO_FLOAT_TO_CELL(f);
}
/* Return integer part of float, rounded */
static Embryo_Cell
_embryo_fp_round(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand */
/* params[2] = Type of rounding (cell) */
float f;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]);
switch (params[2])
{
case 1: /* round downwards (truncate) */
f = (float)(floor((double)f));
break;
case 2: /* round upwards */
f = (float)(ceil((double)f));
break;
case 3: /* round towards zero */
if (f >= 0.0) f = (float)(floor((double)f));
else f = (float)(ceil((double)f));
break;
default: /* standard, round to nearest */
f = (float)(floor((double)f + 0.5));
break;
}
return (Embryo_Cell)f;
}
static Embryo_Cell
_embryo_fp_cmp(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand 1 */
/* params[2] = float operand 2 */
float f, ff;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]);
ff = EMBRYO_CELL_TO_FLOAT(params[2]);
if (f == ff) return 0;
else if (f > ff) return 1;
return -1;
}
static Embryo_Cell
_embryo_fp_sqroot(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand */
float f;
if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]);
f = (float)sqrt(f);
if (f < 0)
{
embryo_program_error_set(ep, EMBRYO_ERROR_DOMAIN);
return 0;
}
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_power(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand 1 */
/* params[2] = float operand 2 */
float f, ff;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]);
ff = EMBRYO_CELL_TO_FLOAT(params[2]);
f = (float)pow(f, ff);
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_log(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand 1 (value) */
/* params[2] = float operand 2 (base) */
float f, ff;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]);
ff = EMBRYO_CELL_TO_FLOAT(params[2]);
if ((f <= 0.0) || (ff <= 0.0))
{
embryo_program_error_set(ep, EMBRYO_ERROR_DOMAIN);
return 0;
}
if (ff == 10.0) f = (float)log10(f);
else f = (float)(log(f) / log(ff));
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_sin(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand 1 (angle) */
/* params[2] = float operand 2 (radix) */
float f;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]);
f = _embryo_fp_degrees_to_radians(f, params[2]);
f = sin(f);
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_cos(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand 1 (angle) */
/* params[2] = float operand 2 (radix) */
float f;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]);
f = _embryo_fp_degrees_to_radians(f, params[2]);
f = cos(f);
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_tan(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand 1 (angle) */
/* params[2] = float operand 2 (radix) */
float f;
if (params[0] != (2 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]);
f = _embryo_fp_degrees_to_radians(f, params[2]);
f = tan(f);
return EMBRYO_FLOAT_TO_CELL(f);
}
static Embryo_Cell
_embryo_fp_abs(Embryo_Program *ep, Embryo_Cell *params)
{
/* params[1] = float operand */
float f;
if (params[0] != (1 * sizeof(Embryo_Cell))) return 0;
f = EMBRYO_CELL_TO_FLOAT(params[1]);
f = (f >= 0) ? f : -f;
return EMBRYO_FLOAT_TO_CELL(f);
}
/* functions used by the rest of embryo */
void
_embryo_fp_init(Embryo_Program *ep)
{
embryo_program_native_call_add(ep, "float", _embryo_fp);
embryo_program_native_call_add(ep, "atof", _embryo_fp_str);
embryo_program_native_call_add(ep, "float_mul", _embryo_fp_mul);
embryo_program_native_call_add(ep, "float_div", _embryo_fp_div);
embryo_program_native_call_add(ep, "float_add", _embryo_fp_add);
embryo_program_native_call_add(ep, "float_sub", _embryo_fp_sub);
embryo_program_native_call_add(ep, "fract", _embryo_fp_fract);
embryo_program_native_call_add(ep, "round", _embryo_fp_round);
embryo_program_native_call_add(ep, "float_cmp", _embryo_fp_cmp);
embryo_program_native_call_add(ep, "sqrt", _embryo_fp_sqroot);
embryo_program_native_call_add(ep, "pow", _embryo_fp_power);
embryo_program_native_call_add(ep, "log", _embryo_fp_log);
embryo_program_native_call_add(ep, "sin", _embryo_fp_sin);
embryo_program_native_call_add(ep, "cos", _embryo_fp_cos);
embryo_program_native_call_add(ep, "tan", _embryo_fp_tan);
embryo_program_native_call_add(ep, "abs", _embryo_fp_abs);
}

View File

@ -0,0 +1,23 @@
#include "embryo_private.h"
static int _embryo_init_count = 0;
/*** EXPORTED CALLS ***/
int
embryo_init(void)
{
_embryo_init_count++;
if (_embryo_init_count > 1) return _embryo_init_count;
return _embryo_init_count;
}
int
embryo_shutdown(void)
{
_embryo_init_count--;
if (_embryo_init_count > 0) return _embryo_init_count;
return _embryo_init_count;
}

View File

@ -0,0 +1,266 @@
#ifndef _EMBRYO_PRIVATE_H
#define _EMBRYO_PRIVATE_H
#include "Embryo.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <limits.h>
#include <stdarg.h>
#include <string.h>
typedef enum _Embryo_Opcode Embryo_Opcode;
enum _Embryo_Opcode
{
EMBRYO_OP_NONE,
EMBRYO_OP_LOAD_PRI,
EMBRYO_OP_LOAD_ALT,
EMBRYO_OP_LOAD_S_PRI,
EMBRYO_OP_LOAD_S_ALT,
EMBRYO_OP_LREF_PRI,
EMBRYO_OP_LREF_ALT,
EMBRYO_OP_LREF_S_PRI,
EMBRYO_OP_LREF_S_ALT,
EMBRYO_OP_LOAD_I,
EMBRYO_OP_LODB_I,
EMBRYO_OP_CONST_PRI,
EMBRYO_OP_CONST_ALT,
EMBRYO_OP_ADDR_PRI,
EMBRYO_OP_ADDR_ALT,
EMBRYO_OP_STOR_PRI,
EMBRYO_OP_STOR_ALT,
EMBRYO_OP_STOR_S_PRI,
EMBRYO_OP_STOR_S_ALT,
EMBRYO_OP_SREF_PRI,
EMBRYO_OP_SREF_ALT,
EMBRYO_OP_SREF_S_PRI,
EMBRYO_OP_SREF_S_ALT,
EMBRYO_OP_STOR_I,
EMBRYO_OP_STRB_I,
EMBRYO_OP_LIDX,
EMBRYO_OP_LIDX_B,
EMBRYO_OP_IDXADDR,
EMBRYO_OP_IDXADDR_B,
EMBRYO_OP_ALIGN_PRI,
EMBRYO_OP_ALIGN_ALT,
EMBRYO_OP_LCTRL,
EMBRYO_OP_SCTRL,
EMBRYO_OP_MOVE_PRI,
EMBRYO_OP_MOVE_ALT,
EMBRYO_OP_XCHG,
EMBRYO_OP_PUSH_PRI,
EMBRYO_OP_PUSH_ALT,
EMBRYO_OP_PUSH_R,
EMBRYO_OP_PUSH_C,
EMBRYO_OP_PUSH,
EMBRYO_OP_PUSH_S,
EMBRYO_OP_POP_PRI,
EMBRYO_OP_POP_ALT,
EMBRYO_OP_STACK,
EMBRYO_OP_HEAP,
EMBRYO_OP_PROC,
EMBRYO_OP_RET,
EMBRYO_OP_RETN,
EMBRYO_OP_CALL,
EMBRYO_OP_CALL_PRI,
EMBRYO_OP_JUMP,
EMBRYO_OP_JREL,
EMBRYO_OP_JZER,
EMBRYO_OP_JNZ,
EMBRYO_OP_JEQ,
EMBRYO_OP_JNEQ,
EMBRYO_OP_JLESS,
EMBRYO_OP_JLEQ,
EMBRYO_OP_JGRTR,
EMBRYO_OP_JGEQ,
EMBRYO_OP_JSLESS,
EMBRYO_OP_JSLEQ,
EMBRYO_OP_JSGRTR,
EMBRYO_OP_JSGEQ,
EMBRYO_OP_SHL,
EMBRYO_OP_SHR,
EMBRYO_OP_SSHR,
EMBRYO_OP_SHL_C_PRI,
EMBRYO_OP_SHL_C_ALT,
EMBRYO_OP_SHR_C_PRI,
EMBRYO_OP_SHR_C_ALT,
EMBRYO_OP_SMUL,
EMBRYO_OP_SDIV,
EMBRYO_OP_SDIV_ALT,
EMBRYO_OP_UMUL,
EMBRYO_OP_UDIV,
EMBRYO_OP_UDIV_ALT,
EMBRYO_OP_ADD,
EMBRYO_OP_SUB,
EMBRYO_OP_SUB_ALT,
EMBRYO_OP_AND,
EMBRYO_OP_OR,
EMBRYO_OP_XOR,
EMBRYO_OP_NOT,
EMBRYO_OP_NEG,
EMBRYO_OP_INVERT,
EMBRYO_OP_ADD_C,
EMBRYO_OP_SMUL_C,
EMBRYO_OP_ZERO_PRI,
EMBRYO_OP_ZERO_ALT,
EMBRYO_OP_ZERO,
EMBRYO_OP_ZERO_S,
EMBRYO_OP_SIGN_PRI,
EMBRYO_OP_SIGN_ALT,
EMBRYO_OP_EQ,
EMBRYO_OP_NEQ,
EMBRYO_OP_LESS,
EMBRYO_OP_LEQ,
EMBRYO_OP_GRTR,
EMBRYO_OP_GEQ,
EMBRYO_OP_SLESS,
EMBRYO_OP_SLEQ,
EMBRYO_OP_SGRTR,
EMBRYO_OP_SGEQ,
EMBRYO_OP_EQ_C_PRI,
EMBRYO_OP_EQ_C_ALT,
EMBRYO_OP_INC_PRI,
EMBRYO_OP_INC_ALT,
EMBRYO_OP_INC,
EMBRYO_OP_INC_S,
EMBRYO_OP_INC_I,
EMBRYO_OP_DEC_PRI,
EMBRYO_OP_DEC_ALT,
EMBRYO_OP_DEC,
EMBRYO_OP_DEC_S,
EMBRYO_OP_DEC_I,
EMBRYO_OP_MOVS,
EMBRYO_OP_CMPS,
EMBRYO_OP_FILL,
EMBRYO_OP_HALT,
EMBRYO_OP_BOUNDS,
EMBRYO_OP_SYSREQ_PRI,
EMBRYO_OP_SYSREQ_C,
EMBRYO_OP_FILE,
EMBRYO_OP_LINE,
EMBRYO_OP_SYMBOL,
EMBRYO_OP_SRANGE,
EMBRYO_OP_JUMP_PRI,
EMBRYO_OP_SWITCH,
EMBRYO_OP_CASETBL,
EMBRYO_OP_SWAP_PRI,
EMBRYO_OP_SWAP_ALT,
EMBRYO_OP_PUSHADDR,
EMBRYO_OP_NOP,
EMBRYO_OP_SYSREQ_D,
EMBRYO_OP_SYMTAG,
/* ----- */
EMBRYO_OP_NUM_OPCODES
};
#define NUMENTRIES(hdr,field,nextfield) \
(int)(((hdr)->nextfield - (hdr)->field) / (hdr)->defsize)
#define GETENTRY(hdr,table,index) \
(Embryo_Func_Stub *)((unsigned char*)(hdr) + \
(int)(hdr)->table + index * (hdr)->defsize)
#define GETENTRYNAME(hdr,entry) \
(((hdr)->defsize == 2 * sizeof(unsigned int)) \
? (char *)((unsigned char*)(hdr) + *((unsigned int *)(entry) + 1)) \
: (entry)->name)
#define CUR_FILE_VERSION 7 /* current file version; also the current Embryo_Program version */
#define MIN_FILE_VERSION 7 /* lowest supported file format version for the current Embryo_Program version */
#define MIN_AMX_VERSION 7 /* minimum Embryo_Program version needed to support the current file format */
#define sEXPMAX 19 /* maximum name length for file version <= 6 */
#define sNAMEMAX 31 /* maximum name length of symbol name */
#define EMBRYO_MAGIC 0xf1e0 /* magic byte pattern */
#define EMBRYO_FLAG_COMPACT 0x04 /* compact encoding */
#define EMBRYO_FLAG_RELOC 0x8000 /* jump/call addresses relocated */
#define GETPARAM(v) (v = *(Embryo_Cell *)cip++)
#define PUSH(v) (stk -= sizeof(Embryo_Cell), *(Embryo_Cell *)(data + (int)stk) = v)
#define POP(v) (v = *(Embryo_Cell *)(data + (int)stk), stk += sizeof(Embryo_Cell))
#define ABORT(ep,v) {(ep)->stk = reset_stk; (ep)->hea = reset_hea; ep->run_count--; ep->error = v; return 0;}
#define OK(ep,v) {(ep)->stk = reset_stk; (ep)->hea = reset_hea; ep->run_count--; ep->error = v; return 1;}
#define STKMARGIN ((Embryo_Cell)(16 * sizeof(Embryo_Cell)))
#define CHKMARGIN() if ((hea + STKMARGIN) > stk) {ep->error = EMBRYO_ERROR_STACKERR; return 0;}
#define CHKSTACK() if (stk > ep->stp) {ep->run_count--; ep->error = EMBRYO_ERROR_STACKLOW; return 0;}
#define CHKHEAP() if (hea < ep->hlw) {ep->run_count--; ep->error = EMBRYO_ERROR_HEAPLOW; return 0;}
typedef struct _Embryo_Param Embryo_Param;
typedef struct _Embryo_Header Embryo_Header;
typedef struct _Embryo_Func_Stub Embryo_Func_Stub;
typedef Embryo_Cell (*Embryo_Native)(Embryo_Program *ep, Embryo_Cell *params);
struct _Embryo_Param
{
char *string;
Embryo_Cell *cell_array;
int cell_array_size;
Embryo_Cell cell;
};
struct _Embryo_Program
{
unsigned char *base; /* points to the Embryo_Program header ("ephdr") plus the code, optionally also the data */
/* for external functions a few registers must be accessible from the outside */
Embryo_Cell cip; /* instruction pointer: relative to base + ephdr->cod */
Embryo_Cell frm; /* stack frame base: relative to base + ephdr->dat */
Embryo_Cell hea; /* top of the heap: relative to base + ephdr->dat */
Embryo_Cell hlw; /* bottom of the heap: relative to base + ephdr->dat */
Embryo_Cell stk; /* stack pointer: relative to base + ephdr->dat */
Embryo_Cell stp; /* top of the stack: relative to base + ephdr->dat */
int flags; /* current status */
/* native functions can raise an error */
int error;
/* the sleep opcode needs to store the full Embryo_Program status */
Embryo_Cell pri;
Embryo_Cell alt;
Embryo_Cell reset_stk;
Embryo_Cell reset_hea;
Embryo_Cell *syscall_d; /* relocated value/address for the SYSCALL.D opcode */
/* extended stuff */
Embryo_Native *native_calls;
int native_calls_size;
int native_calls_alloc;
unsigned char *code;
unsigned char dont_free_code : 1;
Embryo_Cell retval;
Embryo_Param *params;
int params_size;
int params_alloc;
int run_count;
};
#pragma pack(push, 1)
struct _Embryo_Func_Stub
{
int address;
char name[sEXPMAX+1];
};
struct _Embryo_Header
{
unsigned int size; /* size of the "file" */
unsigned short magic; /* signature */
char file_version; /* file format version */
char ep_version; /* required version of the Embryo_Program */
short flags;
short defsize; /* size of a definition record */
int cod; /* initial value of COD - code block */
int dat; /* initial value of DAT - data block */
int hea; /* initial value of HEA - start of the heap */
int stp; /* initial value of STP - stack top */
int cip; /* initial value of CIP - the instruction pointer */
int publics; /* offset to the "public functions" table */
int natives; /* offset to the "native functions" table */
int libraries; /* offset to the table of libraries */
int pubvars; /* the "public variables" table */
int tags; /* the "public tagnames" table */
int nametable; /* name table, file version 7 only */
};
void _embryo_fp_init(Embryo_Program *ep);
#endif