diff options
author | neonloop | 2021-10-20 14:54:27 +0000 |
---|---|---|
committer | neonloop | 2021-10-20 14:54:27 +0000 |
commit | ea1947ffcc606d757357398b24e74a3f4ecefa07 (patch) | |
tree | 2031b8d4fc4c61063c710a7148378f57e662efbd /core/bgdc/src | |
download | bennugd-ea1947ffcc606d757357398b24e74a3f4ecefa07.tar.gz bennugd-ea1947ffcc606d757357398b24e74a3f4ecefa07.tar.bz2 bennugd-ea1947ffcc606d757357398b24e74a3f4ecefa07.zip |
Initial commit from steward-fu releasemain
Diffstat (limited to 'core/bgdc/src')
-rw-r--r-- | core/bgdc/src/Makefile | 680 | ||||
-rw-r--r-- | core/bgdc/src/Makefile.am | 26 | ||||
-rw-r--r-- | core/bgdc/src/Makefile.in | 680 | ||||
-rw-r--r-- | core/bgdc/src/bgdc.ico | bin | 0 -> 19230 bytes | |||
-rw-r--r-- | core/bgdc/src/bgdc.rc | 118 | ||||
-rw-r--r-- | core/bgdc/src/c_code.c | 4164 | ||||
-rw-r--r-- | core/bgdc/src/c_data.c | 960 | ||||
-rw-r--r-- | core/bgdc/src/c_debug.c | 84 | ||||
-rw-r--r-- | core/bgdc/src/c_main.c | 1285 | ||||
-rw-r--r-- | core/bgdc/src/codeblock.c | 426 | ||||
-rw-r--r-- | core/bgdc/src/constants.c | 110 | ||||
-rw-r--r-- | core/bgdc/src/dcbw.c | 1258 | ||||
-rw-r--r-- | core/bgdc/src/error.c | 204 | ||||
-rw-r--r-- | core/bgdc/src/identifier.c | 255 | ||||
-rw-r--r-- | core/bgdc/src/main.c | 496 | ||||
-rw-r--r-- | core/bgdc/src/main_core.c | 134 | ||||
-rw-r--r-- | core/bgdc/src/procedure.c | 192 | ||||
-rw-r--r-- | core/bgdc/src/resource.h | 16 | ||||
-rw-r--r-- | core/bgdc/src/segment.c | 233 | ||||
-rw-r--r-- | core/bgdc/src/strings.c | 241 | ||||
-rw-r--r-- | core/bgdc/src/sysstub.c | 239 | ||||
-rw-r--r-- | core/bgdc/src/token.c | 1424 | ||||
-rw-r--r-- | core/bgdc/src/typedef.c | 242 | ||||
-rw-r--r-- | core/bgdc/src/varspace.c | 256 |
24 files changed, 13723 insertions, 0 deletions
diff --git a/core/bgdc/src/Makefile b/core/bgdc/src/Makefile new file mode 100644 index 0000000..35d93ab --- /dev/null +++ b/core/bgdc/src/Makefile @@ -0,0 +1,680 @@ +# Makefile.in generated by automake 1.12.1 from Makefile.am. +# bgdc/src/Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/bennu +pkgincludedir = $(includedir)/bennu +pkglibdir = $(libdir)/bennu +pkglibexecdir = $(libexecdir)/bennu +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = x86_64-pc-none +host_triplet = arm-unknown-linux-gnu +target_triplet = arm-unknown-linux-gnu +bin_PROGRAMS = bgdc$(EXEEXT) +subdir = bgdc/src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__bgdc_SOURCES_DIST = main.c main_core.c token.c identifier.c \ + segment.c constants.c strings.c varspace.c procedure.c \ + codeblock.c c_main.c c_data.c c_code.c c_debug.c dcbw.c \ + error.c sysstub.c typedef.c ../../common/debug.c \ + ../../common/b_crypt.c ../../common/files.c \ + ../../common/xctype.c bgdc.rc +am__objects_1 = main.$(OBJEXT) main_core.$(OBJEXT) token.$(OBJEXT) \ + identifier.$(OBJEXT) segment.$(OBJEXT) constants.$(OBJEXT) \ + strings.$(OBJEXT) varspace.$(OBJEXT) procedure.$(OBJEXT) \ + codeblock.$(OBJEXT) c_main.$(OBJEXT) c_data.$(OBJEXT) \ + c_code.$(OBJEXT) c_debug.$(OBJEXT) dcbw.$(OBJEXT) \ + error.$(OBJEXT) sysstub.$(OBJEXT) typedef.$(OBJEXT) \ + debug.$(OBJEXT) b_crypt.$(OBJEXT) files.$(OBJEXT) \ + xctype.$(OBJEXT) +am_bgdc_OBJECTS = $(am__objects_1) +#am_bgdc_OBJECTS = $(am__objects_1) bgdc.$(OBJEXT) +bgdc_OBJECTS = $(am_bgdc_OBJECTS) +am__DEPENDENCIES_1 = +bgdc_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +bgdc_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(bgdc_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I. +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(bgdc_SOURCES) +DIST_SOURCES = $(am__bgdc_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = ${SHELL} /home/steward/Github/miyoo_src/bennugd/core/missing --run aclocal-1.12 +AMTAR = $${TAR-tar} +AR = /opt/miyoo/usr/bin/arm-linux-ar +AS = as +AUTOCONF = ${SHELL} /home/steward/Github/miyoo_src/bennugd/core/missing --run autoconf +AUTOHEADER = ${SHELL} /home/steward/Github/miyoo_src/bennugd/core/missing --run autoheader +AUTOMAKE = ${SHELL} /home/steward/Github/miyoo_src/bennugd/core/missing --run automake-1.12 +AWK = mawk +CC = /opt/miyoo/usr/bin/arm-linux-gcc +CCDEPMODE = depmode=gcc3 +CFLAGS = -DTARGET_MIYOO -mcpu=arm926ej-s -mtune=arm926ej-s -O3 -DARM -D_ARM_ASSEM_ -I/opt/miyoo/arm-miyoo-linux-uclibcgnueabi/sysroot/usr/include/SDL -finline-functions -fno-strict-aliasing +COMMON_CFLAGS = -DTARGET_MIYOO -mcpu=arm926ej-s -mtune=arm926ej-s -O3 -DARM -D_ARM_ASSEM_ -I/opt/miyoo/arm-miyoo-linux-uclibcgnueabi/sysroot/usr/include/SDL -finline-functions -fno-strict-aliasing -Wall -DTARGET_LINUX -DUSE_LIBDES -DTARGET_MIYOO -mcpu=arm926ej-s -mtune=arm926ej-s -O3 -DARM -D_ARM_ASSEM_ -I/opt/miyoo/arm-miyoo-linux-uclibcgnueabi/sysroot/usr/include/SDL -I/home/steward/Github/miyoo_src/bennugd/core/../3rdparty/des-4.04b +COMMON_LDFLAGS = -D_REENTRANT -lc -ldl -D_REENTRANT -L/home/steward/Github/miyoo_src/bennugd/core/../3rdparty/des-4.04b -ldes +CPP = /opt/miyoo/usr/bin/arm-linux-gcc -E +CPPFLAGS = +CRYPT_LDFLAGS = +CYGPATH_W = echo +DEFS = -DPACKAGE_NAME=\"bennu\" -DPACKAGE_TARNAME=\"bennu\" -DPACKAGE_VERSION=\"1.0.0\" -DPACKAGE_STRING=\"bennu\ 1.0.0\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DPACKAGE=\"bennu\" -DVERSION=\"1.0.0\" +DEPDIR = .deps +DLLTOOL = false +DSYMUTIL = +DUMPBIN = +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /bin/grep -E +EXEEXT = +FGREP = /bin/grep -F +GREP = /bin/grep +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +LD = /opt/miyoo/usr/bin/arm-linux-ld +LDFLAGS = -D_REENTRANT +LIBOBJS = +LIBS = +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIPO = +LN_S = ln -s +LTLIBOBJS = +MAINT = # +MAKEINFO = ${SHELL} /home/steward/Github/miyoo_src/bennugd/core/missing --run makeinfo +MANIFEST_TOOL = : +MKDIR_P = /bin/mkdir -p +NM = /opt/miyoo/bin//arm-linux-nm -B +NMEDIT = +OBJDUMP = arm-linux-objdump +OBJEXT = o +OTOOL = +OTOOL64 = +PACKAGE = bennu +PACKAGE_BUGREPORT = +PACKAGE_NAME = bennu +PACKAGE_STRING = bennu 1.0.0 +PACKAGE_TARNAME = bennu +PACKAGE_URL = +PACKAGE_VERSION = 1.0.0 +PATH_SEPARATOR = : +PKG_CONFIG = /usr/bin/pkg-config +PKG_CONFIG_LIBDIR = /opt/miyoo/arm-miyoo-linux-uclibcgnueabi/sysroot/usr/lib/pkgconfig +PKG_CONFIG_PATH = /opt/miyoo/arm-miyoo-linux-uclibcgnueabi/sysroot/usr/lib/pkgconfig +RANLIB = /opt/miyoo/usr/bin/arm-linux-ranlib +SED = /bin/sed +SET_MAKE = +SHELL = /bin/bash +STRIP = /opt/miyoo/usr/bin/arm-linux-strip +VERSION = 1.0.0 +WINDRES = +ZLIB_CFLAGS = +ZLIB_LIBS = -lz +abs_builddir = /home/steward/Github/miyoo_src/bennugd/core/bgdc/src +abs_srcdir = /home/steward/Github/miyoo_src/bennugd/core/bgdc/src +abs_top_builddir = /home/steward/Github/miyoo_src/bennugd/core +abs_top_srcdir = /home/steward/Github/miyoo_src/bennugd/core +ac_ct_AR = +ac_ct_CC = +ac_ct_DUMPBIN = +am__include = include +am__leading_dot = . +am__quote = +am__tar = $${TAR-tar} chof - "$$tardir" +am__untar = $${TAR-tar} xf - +bindir = ${exec_prefix}/bin +build = x86_64-pc-none +build_alias = x86_64 +build_cpu = x86_64 +build_os = none +build_vendor = pc +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +exec_prefix = ${prefix} +host = arm-unknown-linux-gnu +host_alias = arm-linux +host_cpu = arm +host_os = linux-gnu +host_vendor = unknown +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /home/steward/Github/miyoo_src/bennugd/core/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = /bin/mkdir -p +oldincludedir = /usr/include +pdfdir = ${docdir} +prefix = /opt/miyoo/usr +program_transform_name = s&^&arm-linux-& +psdir = ${docdir} +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target = arm-unknown-linux-gnu +target_alias = arm-linux +target_cpu = arm +target_os = linux-gnu +target_vendor = unknown +top_build_prefix = ../../ +top_builddir = ../.. +top_srcdir = ../.. +INCLUDES = $(COMMON_CFLAGS) $(ZLIB_CFLAGS) -I../../include -I../include -D__BGDC__ ${EXTRA_STATIC_CFLAGS} +bgdc_LDADD = $(COMMON_LDFLAGS) $(ZLIB_LIBS) $(CRYPT_LDFLAGS) +bgdc_LDFLAGS = +SOURCE_FILES = main.c main_core.c token.c identifier.c segment.c \ + constants.c strings.c varspace.c procedure.c codeblock.c \ + c_main.c c_data.c c_code.c c_debug.c dcbw.c \ + error.c \ + sysstub.c typedef.c \ + ../../common/debug.c \ + ../../common/b_crypt.c \ + ../../common/files.c \ + ../../common/xctype.c + +bgdc_SOURCES = $(SOURCE_FILES) +#bgdc_SOURCES = $(SOURCE_FILES) bgdc.rc +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj .rc +$(srcdir)/Makefile.in: # $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu bgdc/src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu bgdc/src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: # $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): # $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +bgdc$(EXEEXT): $(bgdc_OBJECTS) $(bgdc_DEPENDENCIES) $(EXTRA_bgdc_DEPENDENCIES) + @rm -f bgdc$(EXEEXT) + $(bgdc_LINK) $(bgdc_OBJECTS) $(bgdc_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +include ./$(DEPDIR)/b_crypt.Po +include ./$(DEPDIR)/c_code.Po +include ./$(DEPDIR)/c_data.Po +include ./$(DEPDIR)/c_debug.Po +include ./$(DEPDIR)/c_main.Po +include ./$(DEPDIR)/codeblock.Po +include ./$(DEPDIR)/constants.Po +include ./$(DEPDIR)/dcbw.Po +include ./$(DEPDIR)/debug.Po +include ./$(DEPDIR)/error.Po +include ./$(DEPDIR)/files.Po +include ./$(DEPDIR)/identifier.Po +include ./$(DEPDIR)/main.Po +include ./$(DEPDIR)/main_core.Po +include ./$(DEPDIR)/procedure.Po +include ./$(DEPDIR)/segment.Po +include ./$(DEPDIR)/strings.Po +include ./$(DEPDIR)/sysstub.Po +include ./$(DEPDIR)/token.Po +include ./$(DEPDIR)/typedef.Po +include ./$(DEPDIR)/varspace.Po +include ./$(DEPDIR)/xctype.Po + +.c.o: + $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(COMPILE) -c $< + +.c.obj: + $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +# source='$<' object='$@' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: + $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< + $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +# source='$<' object='$@' libtool=yes \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(LTCOMPILE) -c -o $@ $< + +debug.o: ../../common/debug.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT debug.o -MD -MP -MF $(DEPDIR)/debug.Tpo -c -o debug.o `test -f '../../common/debug.c' || echo '$(srcdir)/'`../../common/debug.c + $(am__mv) $(DEPDIR)/debug.Tpo $(DEPDIR)/debug.Po +# source='../../common/debug.c' object='debug.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o debug.o `test -f '../../common/debug.c' || echo '$(srcdir)/'`../../common/debug.c + +debug.obj: ../../common/debug.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT debug.obj -MD -MP -MF $(DEPDIR)/debug.Tpo -c -o debug.obj `if test -f '../../common/debug.c'; then $(CYGPATH_W) '../../common/debug.c'; else $(CYGPATH_W) '$(srcdir)/../../common/debug.c'; fi` + $(am__mv) $(DEPDIR)/debug.Tpo $(DEPDIR)/debug.Po +# source='../../common/debug.c' object='debug.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o debug.obj `if test -f '../../common/debug.c'; then $(CYGPATH_W) '../../common/debug.c'; else $(CYGPATH_W) '$(srcdir)/../../common/debug.c'; fi` + +b_crypt.o: ../../common/b_crypt.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT b_crypt.o -MD -MP -MF $(DEPDIR)/b_crypt.Tpo -c -o b_crypt.o `test -f '../../common/b_crypt.c' || echo '$(srcdir)/'`../../common/b_crypt.c + $(am__mv) $(DEPDIR)/b_crypt.Tpo $(DEPDIR)/b_crypt.Po +# source='../../common/b_crypt.c' object='b_crypt.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o b_crypt.o `test -f '../../common/b_crypt.c' || echo '$(srcdir)/'`../../common/b_crypt.c + +b_crypt.obj: ../../common/b_crypt.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT b_crypt.obj -MD -MP -MF $(DEPDIR)/b_crypt.Tpo -c -o b_crypt.obj `if test -f '../../common/b_crypt.c'; then $(CYGPATH_W) '../../common/b_crypt.c'; else $(CYGPATH_W) '$(srcdir)/../../common/b_crypt.c'; fi` + $(am__mv) $(DEPDIR)/b_crypt.Tpo $(DEPDIR)/b_crypt.Po +# source='../../common/b_crypt.c' object='b_crypt.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o b_crypt.obj `if test -f '../../common/b_crypt.c'; then $(CYGPATH_W) '../../common/b_crypt.c'; else $(CYGPATH_W) '$(srcdir)/../../common/b_crypt.c'; fi` + +files.o: ../../common/files.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT files.o -MD -MP -MF $(DEPDIR)/files.Tpo -c -o files.o `test -f '../../common/files.c' || echo '$(srcdir)/'`../../common/files.c + $(am__mv) $(DEPDIR)/files.Tpo $(DEPDIR)/files.Po +# source='../../common/files.c' object='files.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o files.o `test -f '../../common/files.c' || echo '$(srcdir)/'`../../common/files.c + +files.obj: ../../common/files.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT files.obj -MD -MP -MF $(DEPDIR)/files.Tpo -c -o files.obj `if test -f '../../common/files.c'; then $(CYGPATH_W) '../../common/files.c'; else $(CYGPATH_W) '$(srcdir)/../../common/files.c'; fi` + $(am__mv) $(DEPDIR)/files.Tpo $(DEPDIR)/files.Po +# source='../../common/files.c' object='files.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o files.obj `if test -f '../../common/files.c'; then $(CYGPATH_W) '../../common/files.c'; else $(CYGPATH_W) '$(srcdir)/../../common/files.c'; fi` + +xctype.o: ../../common/xctype.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xctype.o -MD -MP -MF $(DEPDIR)/xctype.Tpo -c -o xctype.o `test -f '../../common/xctype.c' || echo '$(srcdir)/'`../../common/xctype.c + $(am__mv) $(DEPDIR)/xctype.Tpo $(DEPDIR)/xctype.Po +# source='../../common/xctype.c' object='xctype.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xctype.o `test -f '../../common/xctype.c' || echo '$(srcdir)/'`../../common/xctype.c + +xctype.obj: ../../common/xctype.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xctype.obj -MD -MP -MF $(DEPDIR)/xctype.Tpo -c -o xctype.obj `if test -f '../../common/xctype.c'; then $(CYGPATH_W) '../../common/xctype.c'; else $(CYGPATH_W) '$(srcdir)/../../common/xctype.c'; fi` + $(am__mv) $(DEPDIR)/xctype.Tpo $(DEPDIR)/xctype.Po +# source='../../common/xctype.c' object='xctype.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xctype.obj `if test -f '../../common/xctype.c'; then $(CYGPATH_W) '../../common/xctype.c'; else $(CYGPATH_W) '$(srcdir)/../../common/xctype.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS + + +.rc.o: + $(WINDRES) $< -I../../include -o $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/core/bgdc/src/Makefile.am b/core/bgdc/src/Makefile.am new file mode 100644 index 0000000..f173b6f --- /dev/null +++ b/core/bgdc/src/Makefile.am @@ -0,0 +1,26 @@ +bin_PROGRAMS = bgdc + +.rc.o: + $(WINDRES) $< -I../../include -o $@ + +INCLUDES = $(COMMON_CFLAGS) $(ZLIB_CFLAGS) -I../../include -I../include -D__BGDC__ ${EXTRA_STATIC_CFLAGS} + +bgdc_LDADD = $(COMMON_LDFLAGS) $(ZLIB_LIBS) $(CRYPT_LDFLAGS) + +bgdc_LDFLAGS = + +SOURCE_FILES = main.c main_core.c token.c identifier.c segment.c \ + constants.c strings.c varspace.c procedure.c codeblock.c \ + c_main.c c_data.c c_code.c c_debug.c dcbw.c \ + error.c \ + sysstub.c typedef.c \ + ../../common/debug.c \ + ../../common/b_crypt.c \ + ../../common/files.c \ + ../../common/xctype.c + +if HAVE_WINDRES +bgdc_SOURCES = $(SOURCE_FILES) bgdc.rc +else +bgdc_SOURCES = $(SOURCE_FILES) +endif diff --git a/core/bgdc/src/Makefile.in b/core/bgdc/src/Makefile.in new file mode 100644 index 0000000..27f73a8 --- /dev/null +++ b/core/bgdc/src/Makefile.in @@ -0,0 +1,680 @@ +# Makefile.in generated by automake 1.12.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = bgdc$(EXEEXT) +subdir = bgdc/src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__bgdc_SOURCES_DIST = main.c main_core.c token.c identifier.c \ + segment.c constants.c strings.c varspace.c procedure.c \ + codeblock.c c_main.c c_data.c c_code.c c_debug.c dcbw.c \ + error.c sysstub.c typedef.c ../../common/debug.c \ + ../../common/b_crypt.c ../../common/files.c \ + ../../common/xctype.c bgdc.rc +am__objects_1 = main.$(OBJEXT) main_core.$(OBJEXT) token.$(OBJEXT) \ + identifier.$(OBJEXT) segment.$(OBJEXT) constants.$(OBJEXT) \ + strings.$(OBJEXT) varspace.$(OBJEXT) procedure.$(OBJEXT) \ + codeblock.$(OBJEXT) c_main.$(OBJEXT) c_data.$(OBJEXT) \ + c_code.$(OBJEXT) c_debug.$(OBJEXT) dcbw.$(OBJEXT) \ + error.$(OBJEXT) sysstub.$(OBJEXT) typedef.$(OBJEXT) \ + debug.$(OBJEXT) b_crypt.$(OBJEXT) files.$(OBJEXT) \ + xctype.$(OBJEXT) +@HAVE_WINDRES_FALSE@am_bgdc_OBJECTS = $(am__objects_1) +@HAVE_WINDRES_TRUE@am_bgdc_OBJECTS = $(am__objects_1) bgdc.$(OBJEXT) +bgdc_OBJECTS = $(am_bgdc_OBJECTS) +am__DEPENDENCIES_1 = +bgdc_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +bgdc_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(bgdc_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(bgdc_SOURCES) +DIST_SOURCES = $(am__bgdc_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +COMMON_CFLAGS = @COMMON_CFLAGS@ +COMMON_LDFLAGS = @COMMON_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYPT_LDFLAGS = @CRYPT_LDFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WINDRES = @WINDRES@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = $(COMMON_CFLAGS) $(ZLIB_CFLAGS) -I../../include -I../include -D__BGDC__ ${EXTRA_STATIC_CFLAGS} +bgdc_LDADD = $(COMMON_LDFLAGS) $(ZLIB_LIBS) $(CRYPT_LDFLAGS) +bgdc_LDFLAGS = +SOURCE_FILES = main.c main_core.c token.c identifier.c segment.c \ + constants.c strings.c varspace.c procedure.c codeblock.c \ + c_main.c c_data.c c_code.c c_debug.c dcbw.c \ + error.c \ + sysstub.c typedef.c \ + ../../common/debug.c \ + ../../common/b_crypt.c \ + ../../common/files.c \ + ../../common/xctype.c + +@HAVE_WINDRES_FALSE@bgdc_SOURCES = $(SOURCE_FILES) +@HAVE_WINDRES_TRUE@bgdc_SOURCES = $(SOURCE_FILES) bgdc.rc +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj .rc +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu bgdc/src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu bgdc/src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +bgdc$(EXEEXT): $(bgdc_OBJECTS) $(bgdc_DEPENDENCIES) $(EXTRA_bgdc_DEPENDENCIES) + @rm -f bgdc$(EXEEXT) + $(bgdc_LINK) $(bgdc_OBJECTS) $(bgdc_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/b_crypt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c_code.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c_data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c_debug.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/codeblock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constants.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dcbw.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/identifier.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main_core.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procedure.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/segment.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strings.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysstub.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/token.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/typedef.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/varspace.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xctype.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +debug.o: ../../common/debug.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT debug.o -MD -MP -MF $(DEPDIR)/debug.Tpo -c -o debug.o `test -f '../../common/debug.c' || echo '$(srcdir)/'`../../common/debug.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/debug.Tpo $(DEPDIR)/debug.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../common/debug.c' object='debug.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o debug.o `test -f '../../common/debug.c' || echo '$(srcdir)/'`../../common/debug.c + +debug.obj: ../../common/debug.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT debug.obj -MD -MP -MF $(DEPDIR)/debug.Tpo -c -o debug.obj `if test -f '../../common/debug.c'; then $(CYGPATH_W) '../../common/debug.c'; else $(CYGPATH_W) '$(srcdir)/../../common/debug.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/debug.Tpo $(DEPDIR)/debug.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../common/debug.c' object='debug.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o debug.obj `if test -f '../../common/debug.c'; then $(CYGPATH_W) '../../common/debug.c'; else $(CYGPATH_W) '$(srcdir)/../../common/debug.c'; fi` + +b_crypt.o: ../../common/b_crypt.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT b_crypt.o -MD -MP -MF $(DEPDIR)/b_crypt.Tpo -c -o b_crypt.o `test -f '../../common/b_crypt.c' || echo '$(srcdir)/'`../../common/b_crypt.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/b_crypt.Tpo $(DEPDIR)/b_crypt.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../common/b_crypt.c' object='b_crypt.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o b_crypt.o `test -f '../../common/b_crypt.c' || echo '$(srcdir)/'`../../common/b_crypt.c + +b_crypt.obj: ../../common/b_crypt.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT b_crypt.obj -MD -MP -MF $(DEPDIR)/b_crypt.Tpo -c -o b_crypt.obj `if test -f '../../common/b_crypt.c'; then $(CYGPATH_W) '../../common/b_crypt.c'; else $(CYGPATH_W) '$(srcdir)/../../common/b_crypt.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/b_crypt.Tpo $(DEPDIR)/b_crypt.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../common/b_crypt.c' object='b_crypt.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o b_crypt.obj `if test -f '../../common/b_crypt.c'; then $(CYGPATH_W) '../../common/b_crypt.c'; else $(CYGPATH_W) '$(srcdir)/../../common/b_crypt.c'; fi` + +files.o: ../../common/files.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT files.o -MD -MP -MF $(DEPDIR)/files.Tpo -c -o files.o `test -f '../../common/files.c' || echo '$(srcdir)/'`../../common/files.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/files.Tpo $(DEPDIR)/files.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../common/files.c' object='files.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o files.o `test -f '../../common/files.c' || echo '$(srcdir)/'`../../common/files.c + +files.obj: ../../common/files.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT files.obj -MD -MP -MF $(DEPDIR)/files.Tpo -c -o files.obj `if test -f '../../common/files.c'; then $(CYGPATH_W) '../../common/files.c'; else $(CYGPATH_W) '$(srcdir)/../../common/files.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/files.Tpo $(DEPDIR)/files.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../common/files.c' object='files.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o files.obj `if test -f '../../common/files.c'; then $(CYGPATH_W) '../../common/files.c'; else $(CYGPATH_W) '$(srcdir)/../../common/files.c'; fi` + +xctype.o: ../../common/xctype.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xctype.o -MD -MP -MF $(DEPDIR)/xctype.Tpo -c -o xctype.o `test -f '../../common/xctype.c' || echo '$(srcdir)/'`../../common/xctype.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xctype.Tpo $(DEPDIR)/xctype.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../common/xctype.c' object='xctype.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xctype.o `test -f '../../common/xctype.c' || echo '$(srcdir)/'`../../common/xctype.c + +xctype.obj: ../../common/xctype.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xctype.obj -MD -MP -MF $(DEPDIR)/xctype.Tpo -c -o xctype.obj `if test -f '../../common/xctype.c'; then $(CYGPATH_W) '../../common/xctype.c'; else $(CYGPATH_W) '$(srcdir)/../../common/xctype.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xctype.Tpo $(DEPDIR)/xctype.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../common/xctype.c' object='xctype.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xctype.obj `if test -f '../../common/xctype.c'; then $(CYGPATH_W) '../../common/xctype.c'; else $(CYGPATH_W) '$(srcdir)/../../common/xctype.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS + + +.rc.o: + $(WINDRES) $< -I../../include -o $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/core/bgdc/src/bgdc.ico b/core/bgdc/src/bgdc.ico Binary files differnew file mode 100644 index 0000000..675a60f --- /dev/null +++ b/core/bgdc/src/bgdc.ico diff --git a/core/bgdc/src/bgdc.rc b/core/bgdc/src/bgdc.rc new file mode 100644 index 0000000..5112bbb --- /dev/null +++ b/core/bgdc/src/bgdc.rc @@ -0,0 +1,118 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Spanish (Modern) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ESN) +#ifdef _WIN32 +LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "bgdc.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "0c0a04b0" + BEGIN + VALUE "Comments", "Distributed under GNU General Public License\0" + VALUE "CompanyName", "SplinterGU 2006-2009\0" + VALUE "FileDescription", "BGDC - Bennu Game Development Compiler\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "BGDC\0" + VALUE "LegalCopyright", "Copyright © 2006-2009 SplinterGU\0" + VALUE "LegalTrademarks", "Distributed under GNU General Public License\0" + VALUE "OriginalFilename", "BGDC.exe\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "Bennu Game Development Compiler\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0xc0a, 1200 + END +END + +#endif // !_MAC + +#endif // Spanish (Modern) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/core/bgdc/src/c_code.c b/core/bgdc/src/c_code.c new file mode 100644 index 0000000..2e4ca1e --- /dev/null +++ b/core/bgdc/src/c_code.c @@ -0,0 +1,4164 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "bgdc.h" + +extern int autodeclare ; + +int reduce_arrays = 1; + +/* ---------------------------------------------------------------------- */ +/* Compilador de expresiones y sentencias. En este módulo están todas las */ +/* funciones de compilado que generan código efectivo. */ +/* ---------------------------------------------------------------------- */ + +PROCDEF * proc ; +CODEBLOCK * code ; + +/* Comprueba que los parámetros de una expresión binaria sean datos + * numéricos. Devuelve el tipo de operación(MN_FLOAT o MN_DWORD) */ + +static int check_integer_type( expresion_result *exp ) +{ + if ( typedef_is_pointer( exp->type ) || typedef_base( exp->type ) == TYPE_CHAR ) + { +/* codeblock_add(code, MN_POINTER2BOL, 0) ; */ + exp->type = typedef_new( TYPE_DWORD ) ; + } + + if ( typedef_is_integer( exp->type ) ) + { + BASETYPE t = typedef_base( exp->type ) ; + switch (t) + { + case TYPE_SHORT : + case TYPE_WORD : + return MN_WORD ; + + case TYPE_SBYTE : + case TYPE_BYTE : + return MN_BYTE ; + + case TYPE_UNDEFINED : + case TYPE_INT : + case TYPE_DWORD : + case TYPE_CHAR : + case TYPE_FLOAT : + case TYPE_STRING : + case TYPE_ARRAY : + case TYPE_STRUCT : + case TYPE_POINTER : + break; + } + return MN_DWORD ; + } + + compile_error( MSG_INTEGER_REQUIRED ) ; + return 0; +} + +static int check_integer_types( expresion_result *left, expresion_result *right ) +{ + if ( typedef_is_pointer( left->type ) || typedef_base( left->type ) == TYPE_CHAR ) + { +/* codeblock_add(code, MN_POINTER2BOL, 1) ; */ + left->type = typedef_new( TYPE_DWORD ) ; + } + + if ( typedef_is_pointer( right->type ) || typedef_base( right->type ) == TYPE_CHAR ) + { +/* codeblock_add(code, MN_POINTER2BOL, 0) ; */ + right->type = typedef_new( TYPE_DWORD ) ; + } + + if ( typedef_is_integer( left->type ) ) + { + if ( typedef_is_integer( right->type ) ) + { + if ( typedef_base( left->type ) == typedef_base( right->type ) ) + { + BASETYPE t = typedef_base( left->type ) ; + switch (t) + { + case TYPE_SHORT : + case TYPE_WORD : + return MN_WORD ; + + case TYPE_SBYTE : + case TYPE_BYTE : + return MN_BYTE ; + + case TYPE_UNDEFINED : + case TYPE_INT : + case TYPE_DWORD : + case TYPE_CHAR : + case TYPE_FLOAT : + case TYPE_STRING : + case TYPE_ARRAY : + case TYPE_STRUCT : + case TYPE_POINTER : + break; + } + } + return MN_DWORD ; + } + } + + compile_error( MSG_INTEGER_REQUIRED ) ; + return 0; +} + +static int check_numeric_types( expresion_result *left, expresion_result *right ) +{ + if ( typedef_base( left->type ) == TYPE_FLOAT ) + { + if ( typedef_base( right->type ) == TYPE_FLOAT ) return MN_FLOAT ; + + if ( typedef_is_integer( right->type ) ) + { + codeblock_add( code, MN_INT2FLOAT | mntype( right->type, 0 ), 0 ) ; + right->fvalue = ( float )right->value ; + return MN_FLOAT ; + } + } + + if ( typedef_is_integer( left->type ) || typedef_is_pointer( left->type ) ) + { + if ( typedef_is_integer( right->type ) || typedef_is_pointer( right->type ) ) + { + if ( typedef_base( left->type ) == typedef_base( right->type ) ) return mntype( left->type, 0 ); + if ( typedef_base( left->type ) < typedef_base( right->type ) ) return mntype( left->type, 0 ) ; + return mntype( right->type, 0 ) ; + } + + if ( typedef_base( right->type ) == TYPE_FLOAT ) + { + codeblock_add( code, MN_INT2FLOAT, 1 ) ; + left->fvalue = ( float )left->value ; + return MN_FLOAT ; + } + } + + if ( typedef_base( left->type ) == TYPE_CHAR ) + { + if ( typedef_base( right->type ) == TYPE_STRING ) + { + codeblock_add( code, MN_STR2CHR, 0 ); + if ( right->constant == 1 ) right->value = ( unsigned char ) * ( string_get( right->value ) ); + right->type = typedef_new( TYPE_CHAR ); + return MN_BYTE; + } + if ( typedef_base( right->type ) == TYPE_CHAR || typedef_is_integer( right->type ) ) return MN_BYTE; + } + + if ( typedef_base( right->type ) == TYPE_CHAR ) + { + if ( typedef_base( left->type ) == TYPE_STRING ) + { + codeblock_add( code, MN_STR2CHR, 1 ); + if ( left->constant == 1 ) left->value = ( unsigned char ) * ( string_get( left->value ) ); + left->type = typedef_new( TYPE_CHAR ); + return MN_BYTE; + } + if ( typedef_base( left->type ) == TYPE_CHAR || typedef_is_integer( left->type ) ) return MN_BYTE; + } + + compile_error( MSG_INCOMP_TYPES ) ; + return 0 ; +} + +/* Comprueba que los parámetros de una expresión binaria sean cadenas + * o datos numéricos. Devuelve MN_STRING o el tipo de dato numérico */ + +static int check_numeric_or_string_types( expresion_result * left, expresion_result * right ) +{ + if ( typedef_is_array( left->type ) && left->type.chunk[1].type == TYPE_CHAR && typedef_is_string( right->type ) ) + { + left->type = typedef_new( TYPE_STRING ); + left->lvalue = 0; + codeblock_add( code, MN_A2STR, 1 ) ; + return MN_STRING; + } + if ( typedef_is_array( right->type ) && right->type.chunk[1].type == TYPE_CHAR && typedef_is_string( left->type ) ) + { + right->type = typedef_new( TYPE_STRING ); + right->lvalue = 0; + codeblock_add( code, MN_A2STR, 0 ) ; + return MN_STRING; + } + if ( + typedef_is_array( right->type ) && right->type.chunk[1].type == TYPE_CHAR && + typedef_is_array( left->type ) && left->type.chunk[1].type == TYPE_CHAR ) + { + left->type = typedef_new( TYPE_STRING ); + right->type = typedef_new( TYPE_STRING ); + left->lvalue = 0; + right->lvalue = 0; + codeblock_add( code, MN_A2STR, 0 ) ; + codeblock_add( code, MN_A2STR, 1 ) ; + return MN_STRING; + } + + if ( typedef_base( left->type ) == TYPE_CHAR && typedef_base( right->type ) == TYPE_STRING ) + { + codeblock_add( code, MN_CHR2STR, 1 ); + left->lvalue = 0; + left->type = typedef_new( TYPE_STRING ); + return MN_STRING; + } + + if ( typedef_base( right->type ) == TYPE_CHAR && typedef_base( left->type ) == TYPE_STRING ) + { + codeblock_add( code, MN_CHR2STR, 0 ); + right->lvalue = 0; + right->type = typedef_new( TYPE_STRING ); + return MN_STRING; + } + + if ( typedef_is_string( left->type ) && typedef_is_string( right->type ) ) return MN_STRING ; + if ( typedef_is_string( left->type ) || typedef_is_string( right->type ) ) compile_error( MSG_INCOMP_TYPES ) ; + + return check_numeric_types( left, right ) ; +} + +/* Devuelve el código que hay que adjuntar a un mnemónico para producir + * una variante del mismo, adecuada al tipo de dato concreto */ + +int mntype( TYPEDEF type, int accept_structs ) +{ + BASETYPE t ; + + while ( typedef_is_array( type ) ) type = typedef_reduce( type ) ; + + t = typedef_base( type ) ; + switch (t) + { + case TYPE_DWORD : return MN_DWORD | MN_UNSIGNED; + case TYPE_INT : return MN_DWORD; + case TYPE_WORD : return MN_WORD | MN_UNSIGNED; + case TYPE_SHORT : return MN_WORD ; + case TYPE_BYTE : return MN_BYTE | MN_UNSIGNED; + case TYPE_SBYTE : return MN_BYTE ; + case TYPE_CHAR : return MN_BYTE ; + case TYPE_FLOAT : return MN_FLOAT ; + case TYPE_STRING : return MN_STRING; + case TYPE_POINTER : return MN_DWORD ; + case TYPE_UNDEFINED : + case TYPE_ARRAY : + case TYPE_STRUCT : + break; + } + + if ( t == TYPE_STRUCT && accept_structs ) return 0; + + compile_error( MSG_INCOMP_TYPE ) ; + return 0; +} + +/* Compila el acceso a una VARIABLE global, local, privada o publica */ + +expresion_result compile_sublvalue( VARSPACE * from, int base_offset, VARSPACE * remote ) +{ + VARIABLE * var = NULL ; + VARSPACE * here = from ; + VARSPACE * privars = ( proc ? proc->privars : NULL ) ; + VARSPACE * pubvars = ( proc ? proc->pubvars : NULL ) ; + expresion_result res, ind ; + + if ( here ) token_next() ; + + if ( token.type != IDENTIFIER ) compile_error( MSG_IDENTIFIER_EXP ) ; + + if ( !here && !remote ) + { + /* Splinter, se agrega localidad... */ + if ( proc ) + { + here = privars ; + var = varspace_search( here, token.code ) ; + if ( !var ) + { + here = pubvars ; + var = varspace_search( here, token.code ) ; + } + } + if ( !var ) + { + here = &local ; + var = varspace_search( here, token.code ) ; + } + if ( !var ) + { + here = &global ; + var = varspace_search( here, token.code ) ; + } + } + else + { + if ( remote ) + { + here = remote ; + var = varspace_search( here, token.code ) ; + } + + if ( !var ) + { + here = from; + var = varspace_search( here, token.code ) ; + } + } + if ( !var ) compile_error( MSG_UNKNOWN_IDENTIFIER ) ; + + if ( var->offset - base_offset != 0 || + here == &global || + here == &local || + ( privars && ( here == privars ) ) || + ( pubvars && ( here == pubvars ) ) || + ( remote && ( here == remote ) ) + ) + { + codeblock_add( code, ( + ( remote && ( here == remote ) ) ? MN_REMOTE_PUBLIC : + here == &global ? MN_GLOBAL : + (( here == &local ) && ( here == from ) ) ? MN_REMOTE : + here == &local ? MN_LOCAL : + ( privars && ( here == privars ) ) ? MN_PRIVATE : + ( pubvars && ( here == pubvars ) ) ? MN_PUBLIC : + MN_INDEX + ) | mntype( var->type, 1 ), var->offset - base_offset ) ; + + + if (( pubvars && ( here == pubvars ) ) || ( remote && ( here == remote ) ) ) /* Tambien las locales remotas ? */ + { + proc->flags |= PROC_USES_PUBLICS; + } + + if ( here == &local ) + { + proc->flags |= PROC_USES_LOCALS; + } + } + + token_next() ; + + res.type = var->type ; + res.lvalue = 1 ; + res.asignation = 0 ; + res.constant = 0 ; + res.call = 0 ; + res.value = 0 ; + res.count = 1 ; + + /* Indexado vía [...] */ + + while ( token.type == IDENTIFIER && token.code == identifier_leftb ) /* "[" */ + { + /* De estructuras o arrays */ + if ( typedef_is_struct( res.type ) && typedef_count( res.type ) == 1 ) compile_error( MSG_NOT_AN_ARRAY ) ; + + /* Cadenas y punteros se indexan en otro nivel */ + if ( typedef_is_pointer( res.type ) || typedef_is_string( res.type ) ) break ; + + if ( !typedef_is_struct( res.type ) && !typedef_is_array( res.type ) ) compile_error( MSG_NOT_AN_ARRAY ) ; + + ind = compile_expresion( 0, 0, 0, TYPE_DWORD ) ; + if ( ind.lvalue ) codeblock_add( code, MN_PTR | mntype( ind.type, 0 ), 0 ) ; + + if ( ind.constant && ( ind.value < 0 || ind.value >= typedef_count( res.type ) ) ) compile_error( MSG_BOUND ) ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ; /* "]" */ + + if ( typedef_is_array( res.type ) ) + { + res.type = typedef_reduce( res.type ) ; + codeblock_add( code, MN_ARRAY, typedef_size( res.type ) ) ; + } + else /* estructura */ + { + codeblock_add( code, MN_ARRAY, typedef_size( res.type ) / typedef_count( res.type ) ) ; + } + + token_next() ; + } + + /* Un acceso a un array es un acceso a su primer elemento */ +/* + res.count = 1; + if ( reduce_arrays == 1 && typedef_is_array( res.type ) ) + { + if ( res.type.chunk[1].type != TYPE_CHAR ) + { + while ( typedef_is_array( res.type ) ) + { + res.count *= ( typedef_count( res.type ) ? typedef_count( res.type ) : 1 ); + res.type = typedef_reduce( res.type ) ; + } + } + } +*/ + + token_back() ; + + return res ; +} + +/* Compila el tamaño de una VARIABLE o estructura local, global, privada o publica */ + +#define MAX_EXPR_LEVEL 256 + +int compile_sizeof( VARSPACE * here, int * content_size, char * content_type, int * parent_count ) +{ + VARIABLE * var = NULL ; + expresion_result ind ; + int base = 0 ; + TYPEDEF type, * usertype ; + int _content_size = 0; + char * _content_type = NULL; + int _parent_count = 0; + int check_datatype = 0; + int tcode; + int index_pointer = 0; + + if ( !content_size ) content_size = &_content_size; + if ( !content_type ) content_type = _content_type = (char *)calloc( MAX_EXPR_LEVEL, sizeof( int ) ); + if ( !parent_count ) parent_count = &_parent_count; + + /* Basics datatypes */ + + token_next() ; + if ( token.type != IDENTIFIER && ( token.code == identifier_unsigned || token.code == identifier_signed ) ) /* "UNSIGNED" or "SIGNED" */ + { + check_datatype = 1; + token_next(); + } + + if ( token.type != IDENTIFIER ) compile_error( MSG_INCOMP_TYPE ) ; + + /* Base datatypes */ + + if ( token.code == identifier_dword ) base = 4 ; + else if ( token.code == identifier_int ) base = 4 ; + else if ( token.code == identifier_string ) base = 4 ; + else if ( token.code == identifier_float ) base = 4 ; + else if ( token.code == identifier_short ) base = 2 ; + else if ( token.code == identifier_word ) base = 2 ; + else if ( token.code == identifier_char ) base = 1 ; + else if ( token.code == identifier_byte ) base = 1 ; + else + { + usertype = typedef_by_name( token.code ) ; + if ( usertype ) base = typedef_size( *usertype ) ; + } + + if ( base ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code != identifier_point ) + { + token_back() ; + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && ( token.code == identifier_pointer || token.code == identifier_multiply ) ) /* "POINTER" */ + { + base = 4 ; + continue ; + } + token_back() ; + break ; + } + return base ; + } + token_back() ; + } + + if ( check_datatype ) compile_error( MSG_INVALID_TYPE ) ; + + /* Expressions datatypes */ + + /* Count "*" or "[" */ + + while ( token.type == IDENTIFIER && ( token.code == identifier_multiply || token.code == identifier_leftb || token.code == identifier_leftp ) ) + { + if ( *content_size == MAX_EXPR_LEVEL ) compile_error( MSG_TOO_COMPLEX ); + if ( token.code == identifier_leftp )( *parent_count )++; + content_type[( *content_size )++] = token.code; + token_next() ; + } + + if ( !here ) + { + /* Splinter, se agrega localidad... */ + here = proc->privars ; + var = varspace_search( here, token.code ) ; + if ( !var ) + { + here = proc->pubvars ; + var = varspace_search( here, token.code ) ; + } + if ( !var ) + { + here = &local ; + var = varspace_search( here, token.code ) ; + } + if ( !var ) + { + here = &global ; + var = varspace_search( here, token.code ) ; + } + } + else + { + var = varspace_search( here, token.code ) ; + } + + if ( !var ) compile_error( MSG_UNKNOWN_IDENTIFIER ) ; + + type = var->type; + + token_next() ; + + /* Indexado de arrays */ + + while ( token.type == IDENTIFIER && token.code == identifier_leftb ) /* "[" */ + { + CODEBLOCK_POS p = codeblock_pos( code ); + + /* Cadenas y punteros se indexan en otro nivel */ + if ( typedef_is_pointer( type ) || typedef_is_string( type ) ) break ; + + /* De estructuras o arrays */ + if ( typedef_is_struct( type ) && typedef_count( type ) == 1 ) compile_error( MSG_NOT_AN_ARRAY ) ; + + if ( !typedef_is_struct( type ) && !typedef_is_array( type ) ) compile_error( MSG_NOT_AN_ARRAY ) ; + + ind = compile_expresion( 0, 0, 0, TYPE_DWORD ) ; + if ( !ind.constant || ( ind.value < 0 || ind.value >= typedef_count( type ) ) ) compile_error( MSG_BOUND ) ; + + codeblock_setpos( code, p ); + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ; /* "]" */ + + if ( typedef_is_array( type ) ) + type = typedef_reduce( type ) ; + else + break ; + + token_next() ; + + } + + if ( token.type == IDENTIFIER && token.code == identifier_leftb && + ( typedef_is_pointer( type ) || typedef_is_string( type ) ) ) /* Indexado de punteros ptr[0] o cadenas */ + { + /* Ningun array entra por aca */ + CODEBLOCK_POS p = codeblock_pos( code ); + + ind = compile_subexpresion() ; + if ( !typedef_is_integer( ind.type ) ) compile_error( MSG_INTEGER_REQUIRED ) ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ; /* "]" */ + + codeblock_setpos( code, p ); + + if ( typedef_is_pointer( type ) ) + { + type = typedef_reduce( type ); + token_next(); + index_pointer = 1; + } + else if ( typedef_is_string( type ) ) + return 1; /* Indexado de cadenas */ + } + + /* Check for pointer by ']' or ')' */ + while ( token.type == IDENTIFIER && ( token.code == identifier_rightb || token.code == identifier_rightp ) ) + { + if ( token.code == identifier_rightp ) /* ')' */ + { + if ( !*content_size || !*parent_count ) break; + + while (( *content_size ) && content_type[( *content_size )-1] == identifier_multiply ) /* only '*', '[]' must be already process */ + { + if ( !typedef_is_pointer( type ) ) compile_error( MSG_NOT_A_POINTER ) ; + type = typedef_reduce( type ); + ( *content_size )--; + } + + if ( content_type[--( *content_size )] != identifier_leftp ) compile_error( MSG_INVALID_EXP ); + ( *parent_count )--; + token_next() ; + } + else + { + if ( !*content_size ) compile_error( MSG_EXTRA_CHAR ); + + while ( *content_size && + ( + ( tcode = content_type[( *content_size )-1] ) == identifier_leftb || + tcode == identifier_multiply + ) + ) + { + /* '[' or '*' */ + if ( !typedef_is_pointer( type ) ) compile_error( MSG_NOT_A_POINTER ) ; + + type = typedef_reduce( type ); + ( *content_size )--; + if ( tcode == identifier_leftb ) + { + token_next() ; + break ; + } + } + } + } + + if ( index_pointer && ( token.type != IDENTIFIER || token.code != identifier_point ) ) /* "." */ + { + token_back(); + return typedef_size( type ); /* Indexado de punteros ptr[0] */ + } + + if ( token.type == IDENTIFIER && token.code == identifier_point ) /* "." */ + { + if ( typedef_is_pointer( type ) ) type = typedef_reduce( type ) ; + if ( !typedef_is_struct( type ) && + typedef_base( type ) != TYPE_DWORD && typedef_base( type ) != TYPE_INT /* Soporte de process type para publicas */ + ) + compile_error( MSG_STRUCT_REQUIRED ) ; + + if ( typedef_is_struct( type ) || typedef_is_pointer( type ) || + typedef_base( type ) == TYPE_DWORD || typedef_base( type ) == TYPE_INT ) + return compile_sizeof( typedef_members( type ), content_size, content_type, parent_count ) ; + + return compile_sizeof( &local, content_size, content_type, parent_count ) ; + } + + /* Process "*ptr|**ptr|***ptr|..." */ + while (( *content_size )-- ) + { + if ( content_type[*content_size] != identifier_multiply ) compile_error( MSG_INVALID_EXP ); + if ( !typedef_is_pointer( type ) ) compile_error( MSG_NOT_A_POINTER ) ; + type = typedef_reduce( type ); + } + + if ( _content_type ) free( _content_type ); + + token_back() ; + return typedef_size( type ) ; + +} + +/* Static utility function for compile_bestproc */ + +static void strdelchars( char * str, char * chars ) +{ + while ( *str ) + { + if ( strchr( chars, *str ) ) + strcpy( str, str + 1 ) ; + else + str++ ; + } +} + +/* + * FUNCTION : compile_bestproc + * + * Compile a system call, given a list of system functions + * with the same name + * + * PARAMS: + * procs List of system functions + * + * RETURN VALUE: + * Identifier code allocated for the function + */ + +SYSPROC * compile_bestproc( SYSPROC ** procs ) +{ + int n, proc_count = 0 ; + expresion_result res ; + int count = 0 ; + char validtypes[32] ; + char type = -1 ; + int min_params = 0 ; + const char * proc_name = procs[0]->name ; + + int param_diff, params = 0; + CODEBLOCK_POS code_pos_code; + tok_pos token_save; + + /* --------------------------------------------------- */ + + while ( procs[proc_count] ) proc_count++ ; + + /* Get the minimum number of parameters */ + + for ( n = 0 ; n < proc_count ; n++ ) + if ( procs[n]->params > min_params ) + min_params = procs[n]->params ; + + /* --------------------------------------------------- */ + + /* count function params */ + + code_pos_code = codeblock_pos( code ); + token_save = token_pos(); + + params = 0; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_rightp ) /* ")" */ + { + token_back() ; + break ; + } + token_back() ; + + params++ ; + + res = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ) ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_comma ) /* "," */ + { + token_back() ; + break ; + } + } + + codeblock_setpos(code, code_pos_code); + token_set_pos(token_save); + + /* Eliminate any process that has not as many parameters */ + + param_diff = 0; + for ( n = 0 ; n < proc_count ; n++ ) + { + char * p = procs[n]->paramtypes; + + param_diff = 0; + + while( ( *p ) ) if ( *(p++) == '+' ) param_diff++; + + if ( procs[n]->params - param_diff != params ) + { + memmove( &procs[n], &procs[n+1], sizeof( SYSPROC* ) *( proc_count - n ) ) ; + proc_count-- ; + n-- ; + } + } + + count = 0; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_rightp ) /* ")" */ + { + token_back() ; + break ; + } + token_back() ; + + count++ ; + + /* Eliminate any process that has not as many parameters */ +/* + for ( n = 0 ; n < proc_count ; n++ ) + { + if ( procs[n]->params < count ) + { + memmove( &procs[n], &procs[n+1], sizeof( SYSPROC* ) *( proc_count - n ) ) ; + proc_count-- ; + n-- ; + } + } +*/ + if ( proc_count == 0 ) compile_error( MSG_INCORRECT_PARAMC, proc_name, min_params ) ; + + /* Find all the available types */ + + validtypes[0] = 0 ; + for ( n = 0 ; n < proc_count ; n++ ) + { + if ( !strchr( validtypes, procs[n]->paramtypes[count-1] ) ) + { + validtypes[strlen( validtypes )+1] = 0 ; + validtypes[strlen( validtypes )] = procs[n]->paramtypes[count-1]; + } + } + + if ( strlen( validtypes ) == 1 ) + { + /* Same type for any function variant */ + + if ( validtypes[0] == 'V' ) + { + /* Function will receive a varspace struct */ + reduce_arrays = 0; + res = compile_expresion( 0, 1, 0, TYPE_UNDEFINED ); + reduce_arrays = 1; + /* + while ( typedef_is_pointer( res.type ) ) + { + codeblock_add( code, MN_PTR, 0 ); + res.type = typedef_reduce( res.type ); + } + */ + if ( typedef_is_struct( res.type ) ) + { + int size = res.type.varspace->count * sizeof( DCB_TYPEDEF ); + int nvar; + + segment_alloc( globaldata, size ); + codeblock_add( code, MN_GLOBAL, globaldata->current ) ; + for ( nvar = 0 ; nvar < res.type.varspace->count ; nvar++ ) + { + DCB_TYPEDEF type; + dcb_settype( &type, &res.type.varspace->vars[nvar].type ); + memcpy(( uint8_t* )globaldata->bytes + globaldata->current, &type, sizeof( DCB_TYPEDEF ) ); + globaldata->current += sizeof( DCB_TYPEDEF ); + } + codeblock_add( code, MN_PUSH, res.type.varspace->count ); + count += 2; + } + else + { + DCB_TYPEDEF type; + dcb_settype( &type, &res.type ); + segment_alloc( globaldata, sizeof( TYPEDEF ) ); + codeblock_add( code, MN_GLOBAL, globaldata->current ) ; + memcpy(( uint8_t* )globaldata->bytes + globaldata->current, &type, sizeof( DCB_TYPEDEF ) ); + globaldata->current += sizeof( DCB_TYPEDEF ); + codeblock_add( code, MN_PUSH, 1 ); + count += 2; + } + } + else + { + switch ( validtypes[0] ) + { + case 'I': + type = TYPE_DWORD ; + break ; + case 'B': + type = TYPE_BYTE ; + break ; + case 'W': + type = TYPE_WORD ; + break ; + case 'S': + type = TYPE_STRING ; + break ; + case 'P': + type = TYPE_POINTER ; + break ; + case 'F': + type = TYPE_FLOAT ; + break ; + default: + compile_error( MSG_INVALID_PARAMT ) ; + } + + res = compile_expresion( 0, 0, 0, (BASETYPE)type ) ; + if ( res.lvalue ) codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ) ; + } + } + else + { + /* Different types availables */ + + res = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ) ; + if ( res.lvalue ) codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ) ; + + /* Eliminate any incompatible data type, but allow some + * conversions if no exact match is available */ + + switch ( typedef_base( res.type ) ) + { + case TYPE_DWORD: + case TYPE_SHORT: + case TYPE_BYTE: + case TYPE_SBYTE: + case TYPE_WORD: + case TYPE_INT: + strdelchars( validtypes, "SFP" ) ; + break ; + case TYPE_FLOAT: + if ( strchr( validtypes, 'F' ) ) + strdelchars( validtypes, "SPIWB" ) ; + else + strdelchars( validtypes, "SP" ) ; + break ; + case TYPE_STRING: + if ( strchr( validtypes, 'S' ) ) + strdelchars( validtypes, "FPIWB" ) ; + else + strdelchars( validtypes, "P" ) ; + break ; + case TYPE_POINTER: + strdelchars( validtypes, "SFIWB" ) ; + break ; + default: + break ; + } + + if ( strlen( validtypes ) != 1 ) compile_error( MSG_INVALID_PARAMT ) ; + + /* Eliminate all functions that are not selected */ + + for ( n = 0 ; n < proc_count ; n++ ) + { + if ( procs[n]->paramtypes[count-1] != validtypes[0] ) + { + memmove( &procs[n], &procs[n+1], sizeof( SYSPROC* ) *( proc_count - n ) ) ; + proc_count-- ; + n-- ; + } + } + + if ( strlen( validtypes ) > 1 ) continue ; + + /* Convert the result to the appropiate type, if needed */ + + switch ( validtypes[0] ) + { + case 'I': + type = TYPE_DWORD ; + break ; + case 'B': + type = TYPE_BYTE ; + break ; + case 'W': + type = TYPE_WORD ; + break ; + case 'S': + type = TYPE_STRING ; + break ; + case 'P': + type = TYPE_POINTER ; + break ; + case 'F': + type = TYPE_FLOAT ; + break ; + default: + compile_error( MSG_INVALID_PARAMT ) ; + } + res = convert_result_type( res, (BASETYPE)type ) ; + } + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_comma ) /* "," */ + { + token_back() ; + break ; + } + } + + /* Eliminate any process that has too many parameters */ + + for ( n = 0 ; n < proc_count ; n++ ) + { + if ( procs[n]->params != count ) + { + memmove( &procs[n], &procs[n+1], sizeof( SYSPROC* ) *( proc_count - n ) ) ; + proc_count-- ; + n-- ; + } + } + + if ( proc_count > 1 ) compile_error( MSG_MULTIPLE_PROCS_FOUND, proc_name ); + if ( proc_count == 0 ) compile_error( MSG_INCORRECT_PARAMC, proc_name, min_params ) ; + codeblock_add( code, MN_SYSCALL, procs[0]->code ) ; + + return procs[0] ; +} + +/* Compila una lista de parámetros */ + +int compile_paramlist( BASETYPE * types, const char * paramtypes ) +{ + expresion_result res ; + int count = 0, type ; + + for ( ;; ) + { + type = types ? *types : TYPE_UNDEFINED ; + if ( paramtypes ) + { + switch ( *paramtypes++ ) + { + case 'I': + type = TYPE_DWORD ; + break ; + case 'B': + type = TYPE_BYTE ; + break ; + case 'W': + type = TYPE_WORD ; + break ; + case 'S': + type = TYPE_STRING ; + break ; + case 'P': + type = TYPE_POINTER ; + break ; + case 'F': + type = TYPE_FLOAT ; + break ; + default: + compile_error( MSG_INVALID_PARAMT ) ; + } + } + + res = compile_expresion( 0, 0, 0, (BASETYPE)type ) ; + + if ( types ) + { + if ( *types == TYPE_UNDEFINED ) + *types = typedef_base( res.type ) ; + types++ ; + } + if ( res.lvalue ) codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ) ; + count++ ; + + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_comma ) continue ; /* "," */ + token_back() ; + break ; + } + return count ; +} + +/* + * FUNCTION : compile_cast + * + * Compiles a cast operator(c-like type conversion:([type])value) + * + * PARAMS : + * None + * + * RETURN VALUE : + * Returns the expression result + * + */ + +expresion_result compile_cast() +{ + TYPEDEF type; + BASETYPE basetype = TYPE_INT; + int tokens = 0; + + int signed_prefix = 0; + int unsigned_prefix = 0; + + expresion_result res; + + token_next(); + + /* Check for signed/unsigned prefix */ + + if ( token.type == IDENTIFIER ) + { + if ( token.code == identifier_signed ) + { + signed_prefix = 1; + tokens++; + token_next(); + } + else if ( token.code == identifier_unsigned ) + { + unsigned_prefix = 1; + tokens++; + token_next(); + } + } + + /* Create the data type definition */ + + if ( token.type == IDENTIFIER ) + { + if ( token.code == identifier_dword ) + { + basetype = signed_prefix ? TYPE_INT : TYPE_DWORD; + signed_prefix = unsigned_prefix = 0; + tokens++; + token_next() ; + } + else if ( token.code == identifier_word ) + { + basetype = signed_prefix ? TYPE_SHORT : TYPE_WORD; + signed_prefix = unsigned_prefix = 0; + tokens++; + token_next() ; + } + else if ( token.code == identifier_byte ) + { + basetype = signed_prefix ? TYPE_SBYTE : TYPE_BYTE; + signed_prefix = unsigned_prefix = 0; + tokens++; + token_next() ; + } + else if ( token.code == identifier_int ) + { + basetype = unsigned_prefix ? TYPE_DWORD : TYPE_INT; + signed_prefix = unsigned_prefix = 0; + tokens++; + token_next() ; + } + else if ( token.code == identifier_short ) + { + basetype = unsigned_prefix ? TYPE_WORD : TYPE_SHORT; + signed_prefix = unsigned_prefix = 0; + tokens++; + token_next() ; + } + else if ( token.code == identifier_char ) + { + basetype = TYPE_CHAR; + tokens++; + token_next() ; + } + else if ( token.code == identifier_float ) + { + basetype = TYPE_FLOAT ; + tokens++; + token_next() ; + } + else if ( token.code == identifier_string ) + { + basetype = TYPE_STRING ; + tokens++; + token_next() ; + } + } + + /* Don't allow a signed/unsigned prefix in non-integer types */ + + if ( signed_prefix || unsigned_prefix ) compile_error( MSG_INVALID_TYPE ); + + /* If type is not a basic one: check for user-defined types */ + + if ( tokens == 0 ) + { + TYPEDEF * typep = typedef_by_name( token.code ); + if ( typep == NULL ) + { +/* type = typedef_new(TYPE_INT); */ + compile_error( MSG_INVALID_TYPE ); + } + type = *typep; + token_next(); + } + else + type = typedef_new( basetype ); + + /* Check for pointers to defined types */ + + while ( token.type == IDENTIFIER && ( token.code == identifier_pointer || token.code == identifier_multiply ) ) /* "POINTER" or "*" */ + { + type = typedef_pointer( type ); +/* tokens++; */ + token_next() ; + } + + /* Check for the right parent */ + + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ); /* ")" */ + + /* Do the cast */ + + res = compile_value(); + + if ( typedef_is_equal( res.type, type ) ) return res; + + if ( typedef_is_pointer( type ) ) + { + /* Conversion of pointer to pointer of another type */ + + if ( typedef_is_pointer( res.type ) || typedef_is_integer( res.type ) ) + { + res.type = type; + return res; + } + else if ( typedef_is_float( res.type ) ) + { + codeblock_add( code, MN_FLOAT2INT, 0 ); + res.type = type; + return res; + } + compile_error( MSG_PTR_CONVERSION ); + } + else if ( typedef_is_float( type ) ) + { + /* Conversion of integer to float */ + + if ( typedef_is_integer( res.type ) ) + { + if ( res.lvalue ) + { + codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ); + res.lvalue = 0; + } + codeblock_add( code, MN_INT2FLOAT, 0 ); + res.type = type; + } + else + compile_error( MSG_CONVERSION ); + } + else if ( typedef_base( type ) == TYPE_CHAR ) + { + if ( typedef_is_string( res.type ) ) + { + if ( res.lvalue ) + { + codeblock_add( code, MN_PTR | MN_STRING, 0 ); + res.lvalue = 0; + } + /* + codeblock_add(code, MN_STR2INT, 0); + res.type = typedef_new(TYPE_INT); + */ + codeblock_add( code, MN_STR2CHR, 0 ); + res.type = typedef_new( TYPE_CHAR ); + } + else if ( typedef_is_array( res.type ) && res.type.chunk[1].type == TYPE_CHAR ) + { + codeblock_add( code, MN_A2STR, 0 ); + codeblock_add( code, MN_STR2CHR, 0 ); + res.type = typedef_new( TYPE_CHAR ); + } + else + { + compile_error( MSG_CONVERSION ); + } + } + else if ( typedef_is_integer( type ) ) + { + /* Conversion of float, string or integer to integer */ + + if ( typedef_is_float( res.type ) ) + { + if ( res.lvalue ) + { + codeblock_add( code, MN_PTR | MN_FLOAT, 0 ); + res.lvalue = 0; + } + codeblock_add( code, MN_FLOAT2INT, 0 ); + res.type = typedef_new( TYPE_INT ); + } + else if ( typedef_is_string( res.type ) ) + { + if ( res.lvalue ) + { + codeblock_add( code, MN_PTR | MN_STRING, 0 ); + res.lvalue = 0; + } + codeblock_add( code, MN_STR2INT, 0 ); + res.type = typedef_new( TYPE_INT ); + } + else if ( typedef_is_array( res.type ) && res.type.chunk[1].type == TYPE_CHAR ) + { + codeblock_add( code, MN_A2STR, 0 ); + codeblock_add( code, MN_STR2INT, 0 ); + res.type = typedef_new( TYPE_INT ); + } + else if ( typedef_is_integer( res.type ) || typedef_is_pointer( res.type ) || typedef_base( res.type ) == TYPE_CHAR ) + { + if ( res.lvalue ) + { + codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ); + res.lvalue = 0; + } + } + else + { + compile_error( MSG_CONVERSION ); + } + + if ( type.chunk[0].type == TYPE_BYTE && typedef_is_integer( res.type ) ) + { + codeblock_add( code, MN_INT2BYTE, 0 ); + res.type = type; + } + else if ( type.chunk[0].type == TYPE_SBYTE && typedef_is_integer( res.type ) ) + { + codeblock_add( code, MN_INT2BYTE, 0 ); + res.type = type; + } + else if ( type.chunk[0].type == TYPE_WORD && typedef_is_integer( res.type ) ) + { + codeblock_add( code, MN_INT2WORD, 0 ); + res.type = type; + } + else if ( type.chunk[0].type == TYPE_SHORT && typedef_is_integer( res.type ) ) + { + codeblock_add( code, MN_INT2WORD, 0 ); + res.type = type; + } + } + else if ( typedef_is_string( type ) ) + { + /* Conversión de puntero, float, entero o cadena de ancho fijo a cadena */ + + if ( typedef_is_array( res.type ) && res.type.chunk[1].type == TYPE_CHAR ) + { + codeblock_add( code, MN_A2STR, 0 ); + res.type = typedef_new( TYPE_STRING ); + } + else if ( typedef_is_pointer( res.type ) ) + { + if ( res.lvalue ) + { + codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ); + res.lvalue = 0; + } + codeblock_add( code, MN_A2STR, 0 ); + res.type = typedef_new( TYPE_STRING ); + } + else if ( res.type.chunk[0].type == TYPE_CHAR ) + { + if ( res.lvalue ) + { + codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ); + res.lvalue = 0; + } + codeblock_add( code, MN_CHR2STR, 0 ); + res.type = typedef_new( TYPE_STRING ); + } + else if ( typedef_is_integer( res.type ) ) + { + if ( res.lvalue ) + { + codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ); + res.lvalue = 0; + } + codeblock_add( code, MN_INT2STR | mntype( res.type, 0 ), 0 ); + res.type = typedef_new( TYPE_STRING ); + } + else if ( typedef_is_float( res.type ) ) + { + if ( res.lvalue ) + { + codeblock_add( code, MN_PTR, 0 ); + res.lvalue = 0; + } + codeblock_add( code, MN_FLOAT2STR, 0 ); + res.type = typedef_new( TYPE_STRING ); + } + else + compile_error( MSG_CONVERSION ); + } + else if ( typedef_is_struct( type ) ) + { + res.type = type; + } + else + compile_error( MSG_CONVERSION ); + + return res; +} + +/* Compila un valor (elemento más pequeño del lenguaje) */ + +expresion_result compile_value() +{ + CONSTANT * c ; + SYSPROC * sysproc ; + PROCDEF * cproc ; + int param_count, id ; + + expresion_result res ; + + token_next() ; + + /* ( ... ) */ + + if ( token.type == IDENTIFIER ) + { + + if ( token.code == identifier_leftp ) /* "(" */ + { + /* Check for cast-type expressions */ + + token_next(); + if ( token.type == IDENTIFIER && identifier_is_type( token.code ) ) + { + token_back(); + return compile_cast(); + } + token_back(); + + res = compile_subexpresion() ; + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ) ; /* ")" */ + return res ; + } + + if ( token.code == identifier_type ) /* "TYPE" */ + { + token_next( ); + /* "TYPE mouse" */ + if ( token.type == IDENTIFIER && token.code == identifier_mouse ) /* "MOUSE" - Hack */ + { + codeblock_add( code, MN_PUSH, -1 ) ; + res.value = -1 ; + res.fvalue = 0.0 ; + res.lvalue = 0 ; + res.constant = 1 ; + res.asignation = 0 ; + res.call = 0 ; + res.type = typedef_new( TYPE_INT ) ; + return res ; + } + if ( token.type != IDENTIFIER || token.code < reserved_words ) compile_error( MSG_PROCESS_NAME_EXP ) ; + + codeblock_add( code, MN_TYPE, token.code ) ; + res.fvalue = 0.0 ; + res.value = 0 ; + res.lvalue = 0 ; + res.constant = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.type = typedef_new( TYPE_INT ) ; + return res ; + } + + if ( token.code == identifier_offset || token.code == identifier_bandoffset ) /* "OFFSET" or "&" */ + { + res = compile_factor() ; /* Para permitir &a.b */ + if ( !res.lvalue ) compile_error( MSG_NOT_AN_LVALUE ) ; + + res.lvalue = 0 ; + res.type = typedef_pointer( res.type ) ; + return res ; + } + + if ( token.code == identifier_leftb ) /* "[" */ /* POINTER */ + { + res = compile_subexpresion() ; + if ( !typedef_is_pointer( res.type ) ) compile_error( MSG_NOT_A_POINTER ) ; + + if ( res.lvalue ) codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ) ; + + res.type = typedef_reduce( res.type ) ; + token_next() ; + + if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ; /* "]" */ + + res.lvalue = 1 ; + return res ; + } + + if ( token.code == identifier_multiply ) /* "*" */ + { + res = compile_factor() ; /* Para aceptar *ptr++ */ + if ( !typedef_is_pointer( res.type ) ) compile_error( MSG_NOT_A_POINTER ) ; + + if ( res.lvalue ) codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ) ; + + res.type = typedef_reduce( res.type ) ; + res.lvalue = 1 ; + return res ; + } + + /* SIZEOF */ + + if ( token.code == identifier_sizeof ) /* "SIZEOF" */ + { + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_leftp ) compile_error( MSG_EXPECTED, "(" ) ; /* "(" */ + + res.value = compile_sizeof( 0, NULL, NULL, NULL ) ; + res.fvalue = 0.0 ; + res.lvalue = 0 ; + res.constant = 1 ; + res.asignation = 0 ; + res.call = 0 ; + res.type = typedef_new( TYPE_DWORD ) ; + codeblock_add( code, MN_PUSH, res.value ) ; + token_next() ; + + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ) ; /* ")" */ + + return res ; + } + } + + switch ( token.type ) + { + case NUMBER: /* Numbers */ + codeblock_add( code, MN_PUSH, token.code ) ; + res.fvalue = 0.0 ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.constant = 1 ; + res.call = 0 ; + res.value = token.code ; + res.type = typedef_new( TYPE_INT ) ; + return res ; + + case FLOAT: + codeblock_add( code, MN_PUSH, *( int * )&token.value ) ; + res.value = 0 ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.constant = 1 ; + res.call = 0 ; + res.fvalue = token.value ; + res.type = typedef_new( TYPE_FLOAT ) ; + return res ; + + case STRING: /* Strings */ + codeblock_add( code, MN_PUSH | MN_STRING, token.code ) ; + res.fvalue = 0.0 ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.constant = 1 ; + res.call = 0 ; + res.value = token.code ; + res.type = typedef_new( TYPE_STRING ) ; + return res ; + + case IDENTIFIER: /* Constants */ + c = constants_search( token.code ) ; + if ( c ) + { + if ( typedef_is_string( c->type ) ) + codeblock_add( code, MN_PUSH | MN_STRING, c->value ) ; + else + codeblock_add( code, MN_PUSH, c->value ) ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.constant = 1 ; + res.call = 0 ; + res.value = c->value ; + res.fvalue = *( float * ) & c->value; + res.type = c->type ; + return res ; + } + break; + + default: + compile_error( MSG_UNKNOWN_IDENTIFIER ) ; + break; + } + + /* Llamada a un procedimiento o función del sistema */ + + id = token.code ; + + token_next() ; + + if ( token.type == IDENTIFIER && token.code == identifier_leftp ) /* "(" */ + { + SYSPROC ** sysproc_list = sysproc_getall( id ) ; + + if ( sysproc_list ) + { + sysproc = compile_bestproc( sysproc_list ); + free( sysproc_list ); + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ) ; /* ")" */ + + res.fvalue = 0.0 ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.constant = 0 ; + res.call = 1 ; + res.value = 0 ; + res.type = typedef_new( sysproc->type ) ; + return res ; + } + + /* Llama a un procedimiento del usuario */ + + cproc = procdef_search( id ) ; + if ( !cproc ) + { + if ( autodeclare ) + cproc = procdef_new( procdef_getid(), id ) ; + else + { + token_back() ; + compile_error( MSG_UNDEFINED_PROC ) ; + } + } + + token_next() ; + + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) /* ")" */ + { + token_back() ; + param_count = compile_paramlist( cproc->paramtype, 0 ) ; + token_next() ; + } + else + { + param_count = 0 ; + } + + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ) ; /* ")" */ + + if ( cproc->params == -1 ) + { + cproc->params = param_count ; + } + else if ( cproc->params != param_count ) + { + compile_error( MSG_INCORRECT_PARAMC, identifier_name( cproc->identifier ), cproc->params ) ; + } + + codeblock_add( code, MN_CALL, id ) ; + res.fvalue = 0.0 ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.constant = 0 ; + res.call = 1 ; + res.value = 0 ; + res.type = typedef_new( cproc->type ) ; + return res ; + } + + token_back() ; + + /* Valor asignable */ + + return compile_sublvalue( 0, 0, NULL ) ; + +} + +expresion_result compile_factor() +{ + expresion_result res, part ; + + token_next() ; + + res.value = 0 ; + res.fvalue = 0 ; + res.lvalue = 0 ; + res.call = 0 ; + res.constant = 0 ; + res.asignation = 0 ; + + /* "+2" (Positivo) */ + if ( token.type == IDENTIFIER && token.code == identifier_plus ) token_next() ; /* "+" */ + + if ( token.type == IDENTIFIER ) + { + if ( token.code == identifier_minus ) /* "-" */ /* "-2" (Negativo) */ + { + part = compile_factor() ; + if ( part.lvalue ) codeblock_add( code, mntype( part.type, 0 ) | MN_PTR, 0 ) ; + codeblock_add( code, ( mntype( part.type, 0 ) == MN_FLOAT ? MN_FLOAT : 0 ) | MN_NEG, 0 ) ; + res.type = part.type ; + if ( typedef_is_numeric( part.type ) ) + { + res.constant = part.constant ; + res.value = -part.value ; + res.fvalue = -part.fvalue ; + return res ; + } + compile_error( MSG_NUMBER_REQUIRED ) ; + } + else if ( token.code == identifier_not ) /* "NOT" or "!" */ + { + part = compile_factor() ; + if ( part.lvalue ) codeblock_add( code, mntype( part.type, 0 ) | MN_PTR, 0 ) ; + if ( typedef_is_pointer( part.type ) ) + { + /* codeblock_add (code, mntype(part.type, 0) | MN_POINTER2BOL, 0) ; */ + part.type = typedef_new( TYPE_DWORD ) ; + } + codeblock_add( code, ( mntype( part.type, 0 ) == MN_FLOAT ? MN_FLOAT : 0 ) | MN_NOT, 0 ) ; + if ( typedef_is_numeric( part.type ) || typedef_is_pointer( part.type ) ) + { + res.constant = part.constant ; + res.value = !part.value ; + res.fvalue = ( float )!part.fvalue ; + res.type = part.type ; + return res ; + } + compile_error( MSG_NUMBER_REQUIRED ) ; + return res ; + } + else if ( token.code == identifier_bnot ) /* "BNOT" or "~" */ + { + part = compile_factor() ; + if ( part.lvalue ) codeblock_add( code, mntype( part.type, 0 ) | MN_PTR, 0 ) ; + if ( typedef_is_pointer( part.type ) ) + { + /* codeblock_add (code, mntype(part.type, 0) | MN_POINTER2BOL, 0) ; */ + part.type = typedef_new( TYPE_DWORD ) ; + } + + if ( mntype( part.type, 0 ) == MN_FLOAT ) compile_error( MSG_INTEGER_REQUIRED ); + + codeblock_add( code, mntype( part.type, 0 ) | MN_BNOT, 0 ) ; + if ( typedef_is_numeric( part.type ) ) + { + res.constant = part.constant ; + res.value = ~part.value ; + res.type = part.type /*typedef_new( TYPE_INT )*/ ; + return res ; + } + compile_error( MSG_NUMBER_REQUIRED ) ; + return res ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_plusplus ) /* "++" */ + { + part = compile_factor() ; + if ( !part.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + if ( typedef_is_string( part.type ) ) compile_error( MSG_INCOMP_TYPE ) ; + if ( typedef_is_pointer( part.type ) ) + codeblock_add( code, MN_INC, typedef_size( typedef_reduce( part.type ) ) ) ; + else + codeblock_add( code, mntype( part.type, 0 ) | MN_INC, 1 ) ; + res.asignation = 1 ; + res.lvalue = 1 ; + res.type = part.type ; + return res ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_minusminus ) /* "--" */ + { + part = compile_factor() ; + if ( !part.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + if ( typedef_is_string( part.type ) ) compile_error( MSG_INCOMP_TYPE ) ; + if ( typedef_is_pointer( part.type ) ) + codeblock_add( code, MN_DEC, typedef_size( typedef_reduce( part.type ) ) ) ; + else + codeblock_add( code, mntype( part.type, 0 ) | MN_DEC, 1 ) ; + res.asignation = 1 ; + res.lvalue = 1 ; + res.type = part.type ; + return res ; + } + } + token_back() ; + + part = compile_value() ; + + /* Sufijos (operadores ., [], etc) */ + + for ( ;; ) + { + token_next() ; + + if ( token.type == IDENTIFIER ) + { + if ( token.code == identifier_point ) /* "." */ /* Operador "." */ + { + if ( typedef_is_array( part.type ) ) + { + while ( typedef_is_array ( part.type = typedef_reduce( part.type ) ) ) ; + } + + if ( typedef_is_pointer( part.type ) ) + { + part.type = typedef_reduce( part.type ) ; + if ( !typedef_is_struct( part.type ) ) compile_error( MSG_STRUCT_REQUIRED ) ; + codeblock_add( code, MN_PTR, 0 ) ; + } + + if ( typedef_is_struct( part.type ) ) + { + VARSPACE * v = typedef_members( part.type ) ; + if ( !v->vars ) compile_error( MSG_STRUCT_REQUIRED ) ; + + part = compile_sublvalue( v, v->vars[0].offset, NULL ) ; + } + else + { + VARSPACE * v = typedef_members( part.type ) ; + if ( typedef_base( part.type ) != TYPE_DWORD && typedef_base( part.type ) != TYPE_INT ) compile_error( MSG_INTEGER_REQUIRED ) ; + if ( part.lvalue ) codeblock_add( code, mntype( part.type, 0 ) | MN_PTR, 0 ) ; + + part = compile_sublvalue( &local, 0, v ) ; /* referenciada REMOTA por proceso (Splinter) */ + } + continue ; + } + else if ( token.code == identifier_plusplus ) /* Operador ++ posterior */ + { + if ( !part.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + if ( typedef_is_string( part.type ) ) compile_error( MSG_INCOMP_TYPE ) ; + if ( typedef_is_pointer( part.type ) ) + codeblock_add( code, MN_POSTINC, typedef_size( typedef_reduce( part.type ) ) ) ; + else + codeblock_add( code, mntype( part.type, 0 ) | MN_POSTINC, 1 ) ; + part.asignation = 1 ; + part.lvalue = 0 ; + continue ; + } + else if ( token.code == identifier_minusminus ) /* Operador -- posterior */ + { + if ( !part.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + if ( typedef_is_string( part.type ) ) compile_error( MSG_INCOMP_TYPE ) ; + if ( typedef_is_pointer( part.type ) ) + codeblock_add( code, MN_POSTDEC, typedef_size( typedef_reduce( part.type ) ) ) ; + else + codeblock_add( code, mntype( part.type, 0 ) | MN_POSTDEC, 1 ) ; + part.asignation = 1 ; + part.lvalue = 0 ; + continue ; + } + } + + /* Indexado vía [...] */ + + if ( token.type == IDENTIFIER && token.code == identifier_leftb ) /* "[" */ + { + if ( typedef_is_pointer( part.type ) ) /* De punteros */ + { + if ( part.lvalue ) codeblock_add( code, mntype( part.type, 0 ) | MN_PTR, 0 ) ; + part.type = typedef_reduce( part.type ) ; + + res = compile_subexpresion() ; + if ( !typedef_is_integer( res.type ) ) compile_error( MSG_INTEGER_REQUIRED ) ; + if ( res.lvalue ) codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ) ; + + codeblock_add( code, MN_ARRAY, typedef_size( part.type ) ) ; + part.lvalue = 1 ; + + token_next() ; + + if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ; /* "]" */ + continue ; + } + + if ( typedef_is_string( part.type ) ) /* De cadenas */ + { + if ( part.lvalue ) codeblock_add( code, MN_STRING | MN_PTR, 0 ) ; + + res = compile_subexpresion() ; + if ( !typedef_is_integer( res.type ) ) compile_error( MSG_INTEGER_REQUIRED ) ; + if ( res.lvalue ) codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ) ; + + codeblock_add( code, MN_STRI2CHR, 0 ) ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ; /* "]" */ +/* part.type = typedef_new( TYPE_STRING ) ; */ + part.type = typedef_new( TYPE_CHAR ) ; + part.lvalue = 0 ; + } + continue ; + } + + break ; + } + + token_back() ; + + return part ; +} + +/* Paso 7 */ +expresion_result compile_operand() +{ + expresion_result left = compile_factor(), right, res ; + int op, t ; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_multiply ) /* "*" */ + { + if ( left.lvalue ) codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + + right = compile_factor(); + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + + t = check_numeric_types( &left, &right ) ; + codeblock_add( code, MN_MUL | t, 0 ) ; + + res.constant = ( right.constant && left.constant ) ; + + if ( t == MN_FLOAT ) + { + res.value = 0 ; + res.fvalue = left.fvalue * right.fvalue ; + res.type = typedef_new( TYPE_FLOAT ) ; + } + else + { + res.fvalue = 0.0 ; + res.type = typedef_new( TYPE_INT ) ; + res.value = left.value * right.value ; + } + + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + + left = res ; + continue ; + } + else if ( token.type == IDENTIFIER && ( token.code == identifier_divide || token.code == identifier_mod ) ) /* "/" or "%" */ + { + op = token.code == identifier_mod ? MN_MOD : MN_DIV ; + if ( op == MN_MOD && typedef_base( left.type ) == TYPE_FLOAT ) compile_error( MSG_INTEGER_REQUIRED ) ; + + if ( left.lvalue ) codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + + right = compile_factor(); + if ( op == MN_MOD && typedef_base( right.type ) == TYPE_FLOAT ) compile_error( MSG_INTEGER_REQUIRED ) ; + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + + t = check_numeric_types( &left, &right ) ; + codeblock_add( code, op | t, 0 ) ; + res.constant = ( right.constant && left.constant ) ; + res.value = 0 ; + res.fvalue = 0.0 ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.type = typedef_new( t == MN_FLOAT ? TYPE_FLOAT : TYPE_INT ) ; + + if ( res.constant ) + { + if ( t == MN_FLOAT ) + { + if ( op == MN_MOD ) compile_error( MSG_NUMBER_REQUIRED ) ; + res.fvalue = left.fvalue / right.fvalue ; + res.type = typedef_new( TYPE_FLOAT ) ; + res.value = 0 ; + } + else + { + if ( right.value == 0 ) compile_error( MSG_DIVIDE_BY_ZERO ) ; + res.value = op == MN_MOD ? left.value % right.value : left.value / right.value ; + res.type = typedef_new( TYPE_INT ) ; + res.fvalue = 0.0 ; + } + } + + left = res ; + continue ; + } + + token_back() ; + break ; + } + + return left ; +} + +/* Paso 6 */ +expresion_result compile_operation() +{ + expresion_result left = compile_operand(), right, res ; + int op, t ; + + for ( ;; ) + { + token_next() ; + + /* Suma(o resta) de un entero a un puntero */ + + if ( + typedef_is_pointer( left.type ) && token.type == IDENTIFIER && + ( token.code == identifier_plus || token.code == identifier_minus ) ) /* "+" o "-" */ + { + TYPEDEF ptr_t = typedef_reduce( left.type ) ; + + op = token.code == identifier_plus ? MN_ADD : MN_SUB ; + if ( left.lvalue ) codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + + right = compile_operand() ; + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + + if ( !typedef_is_integer( right.type ) && !typedef_is_pointer( right.type )) compile_error( MSG_INCOMP_TYPES ) ; + + if ( typedef_size( ptr_t ) > 1 ) + codeblock_add( code, MN_ARRAY, ( op == MN_ADD ? 1 : -1 ) * typedef_size( ptr_t ) ) ; + else + codeblock_add( code, op, 0 ) ; + + res.value = 0 ; + res.fvalue = 0.0 ; + res.constant = 0 ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.type = left.type ; + + left = res ; + continue ; + } + + /* Suma de cadenas */ + + if ( typedef_is_array( left.type ) && left.lvalue && + token.type == IDENTIFIER && token.code == identifier_plus && left.type.chunk[1].type == TYPE_CHAR ) /* "+" */ + { + codeblock_add( code, MN_A2STR, 0 ) ; + left.lvalue = 0 ; + left.type = typedef_new( TYPE_STRING ) ; + } + + /* Suma/resta de valores numéricos */ + + if ( token.type == IDENTIFIER && ( token.code == identifier_plus || token.code == identifier_minus ) ) /* "+" or "-" */ + { + op = token.code == identifier_plus ? MN_ADD : MN_SUB ; + if ( left.lvalue ) codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + right = compile_operand() ; + + /* Concatenación de cadenas */ + + if (( typedef_is_string( left.type ) || typedef_is_string( right.type ) ) && op == MN_ADD ) + { + if ( typedef_is_array( right.type ) && right.lvalue && right.type.chunk[1].type == TYPE_CHAR ) + { + codeblock_add( code, MN_A2STR, 0 ) ; + right.type = typedef_new( TYPE_STRING ) ; + right.lvalue = 0 ; + } + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + + if ( typedef_is_integer( right.type ) ) + codeblock_add( code, MN_INT2STR | mntype( right.type, 0 ), 0 ) ; + else if ( typedef_is_float( right.type ) ) + codeblock_add( code, MN_FLOAT2STR, 0 ) ; + else if ( typedef_is_pointer( right.type ) ) + codeblock_add( code, MN_POINTER2STR, 0 ) ; + else if ( typedef_base( right.type ) == TYPE_CHAR ) + codeblock_add( code, MN_CHR2STR, 0 ); + else if ( !typedef_is_string( right.type ) ) + compile_error( MSG_INCOMP_TYPES ) ; + + if ( typedef_is_integer( left.type ) ) + codeblock_add( code, MN_INT2STR | mntype( left.type, 0 ), 1 ) ; + else if ( typedef_is_float( left.type ) ) + codeblock_add( code, MN_FLOAT2STR, 1 ) ; + else if ( typedef_is_pointer( left.type ) ) + codeblock_add( code, MN_POINTER2STR, 1 ) ; + else if ( typedef_base( left.type ) == TYPE_CHAR ) + codeblock_add( code, MN_CHR2STR, 1 ); + else if ( !typedef_is_string( left.type ) ) + compile_error( MSG_INCOMP_TYPES ) ; + + codeblock_add( code, MN_STRING | MN_ADD, 0 ) ; + res.fvalue = 0.0 ; + res.value = 0 ; + res.constant = 0 ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.type = typedef_new( TYPE_STRING ) ; + + left = res ; + continue ; + } + + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + + t = check_numeric_types( &left, &right ) ; + if ( t != MN_FLOAT ) t = MN_DWORD ; + + codeblock_add( code, op | t, 0 ) ; + res.constant = ( right.constant && left.constant ) ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + if ( t == MN_FLOAT ) + { + res.value = 0.0 ; + res.type = typedef_new( TYPE_FLOAT ) ; + res.fvalue = op == MN_ADD ? left.fvalue + right.fvalue : left.fvalue - right.fvalue ; + } + else + { + res.fvalue = 0.0 ; + res.type = left.type /*typedef_new( TYPE_INT )*/ ; + res.value = op == MN_ADD ? left.value + right.value : left.value - right.value ; + } + + left = res ; + continue ; + } + token_back() ; + break ; + } + + return left ; +} + +/* Paso 5 */ +expresion_result compile_rotation() +{ + expresion_result left = compile_operation(), right, res ; + int op ; + BASETYPE t ; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && ( token.code == identifier_ror || token.code == identifier_rol ) ) /* ">>" or "<<" */ + { + op = token.code == identifier_ror ? MN_ROR : MN_ROL ; + if ( left.lvalue ) codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + + right = compile_operation() ; + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + + t = check_numeric_types( &left, &right ) ; + codeblock_add( code, op | mntype( left.type, 0 ), 0 ) ; + + res.constant = ( right.constant && left.constant ) ; + + if ( t == MN_FLOAT ) compile_error( MSG_INTEGER_REQUIRED ) ; + + res.type = left.type /*typedef_new( TYPE_DWORD ) */; + res.value = ( op == MN_ROR ? ( left.value >> right.value ) : ( left.value << right.value ) ) ; + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + + left = res ; + continue ; + } + + token_back() ; + break; + } + + return left ; +} + +/* Paso 4 */ +expresion_result compile_comparison_1() +{ + expresion_result left = compile_rotation(), right, res ; + int op, t ; + + for ( ;; ) + { + token_next() ; + if (token.type == IDENTIFIER && ( + token.code == identifier_gt || /* ">" */ + token.code == identifier_lt || /* "<" */ + token.code == identifier_gte || /* ">=" or "=>" */ + token.code == identifier_lte ) ) /* "<=" or "=<" */ + { + int is_unsigned = 0; + + op = token.code ; + if ( left.lvalue && ( left.type.chunk[0].type != TYPE_ARRAY || left.type.chunk[1].type != TYPE_CHAR ) ) + codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + + right = compile_rotation() ; + if ( right.lvalue && ( right.type.chunk[0].type != TYPE_ARRAY || right.type.chunk[1].type != TYPE_CHAR ) ) + codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + + t = check_numeric_or_string_types( &left, &right ) ; + if ( t != MN_FLOAT && t != MN_STRING ) t = MN_DWORD ; + + if ( + ( typedef_is_unsigned( left.type ) || typedef_is_unsigned( right.type ) ) && + ( typedef_is_integer( left.type ) && typedef_is_integer( right.type ) ) + ) + is_unsigned = MN_UNSIGNED; + + res.value = 0 ; + if ( op == identifier_gt ) /* ">" */ + { + codeblock_add( code, t | MN_GT | is_unsigned, 0 ) ; + if ( left.constant && right.constant ) + { + if ( t == MN_DWORD ) + res.value = left.value > right.value; + else if ( t == MN_FLOAT ) + res.value = ( left.fvalue > right.fvalue ); + else + res.value = strcmp( string_get( left.value ), string_get( right.value ) ) > 0; + } + } + else if ( op == identifier_lt ) /* "<" */ + { + codeblock_add( code, t | MN_LT | is_unsigned, 0 ) ; + if ( left.constant && right.constant ) + { + if ( t == MN_DWORD ) + res.value = left.value < right.value; + else if ( t == MN_FLOAT ) + res.value = ( left.fvalue < right.fvalue ); + else + res.value = strcmp( string_get( left.value ), string_get( right.value ) ) < 0; + } + } + else if ( op == identifier_gte ) /* ">=" or "=>" */ + { + codeblock_add( code, t | MN_GTE | is_unsigned, 0 ) ; + if ( left.constant && right.constant ) + { + if ( t == MN_DWORD ) + res.value = left.value >= right.value; + else if ( t == MN_FLOAT ) + res.value = ( left.fvalue >= right.fvalue ); + else + res.value = strcmp( string_get( left.value ), string_get( right.value ) ) >= 0; + } + } + else if ( op == identifier_lte ) /* "<=" or "=<" */ + { + codeblock_add( code, t | MN_LTE | is_unsigned, 0 ) ; + if ( left.constant && right.constant ) + { + if ( t == MN_DWORD ) + res.value = left.value <= right.value; + else if ( t == MN_FLOAT ) + res.value = ( left.fvalue <= right.fvalue ); + else + res.value = strcmp( string_get( left.value ), string_get( right.value ) ) <= 0; + } + } + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.constant = ( right.constant && left.constant ) ; + res.type = typedef_new( TYPE_INT ) ; + left = res; + continue; + } + token_back() ; + break; + } + + return left ; +} + +expresion_result compile_comparison_2() +{ + expresion_result left = compile_comparison_1(), right, res ; + int op, t ; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && ( token.code == identifier_eq || /* "==" */ + token.code == identifier_ne ) ) /* "!=" or "<>" */ + { + int is_unsigned = 0; + + op = token.code ; + if ( left.lvalue && ( left.type.chunk[0].type != TYPE_ARRAY || left.type.chunk[1].type != TYPE_CHAR ) ) + codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + + right = compile_comparison_1(); + if ( right.lvalue && ( right.type.chunk[0].type != TYPE_ARRAY || right.type.chunk[1].type != TYPE_CHAR ) ) + codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + + t = check_numeric_or_string_types( &left, &right ) ; + if ( t != MN_FLOAT && t != MN_STRING ) t = MN_DWORD ; + + if ( typedef_is_unsigned( left.type ) && typedef_is_unsigned( right.type ) ) is_unsigned = MN_UNSIGNED; + + res.value = 0 ; + + if ( op == identifier_eq ) /* "==" */ + { + codeblock_add( code, t | MN_EQ, 0 ) ; + if ( left.constant && right.constant ) + { + if ( t == MN_DWORD ) + res.value = left.value == right.value; + else if ( t == MN_FLOAT ) + res.value = ( left.fvalue == right.fvalue ); + else + res.value = strcmp( string_get( left.value ), string_get( right.value ) ) == 0; + } + } + else if ( op == identifier_ne ) /* "!=" or "<>" */ + { + codeblock_add( code, t | MN_NE, 0 ) ; + if ( left.constant && right.constant ) + { + if ( t == MN_DWORD ) + res.value = left.value != right.value; + else if ( t == MN_FLOAT ) + res.value = ( left.fvalue != right.fvalue ); + else + res.value = strcmp( string_get( left.value ), string_get( right.value ) ) != 0; + } + } + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.constant = ( right.constant && left.constant ) ; + res.type = typedef_new( TYPE_INT ) ; + + left = res ; + continue; + } + token_back() ; + break; + } + + return left ; +} + +expresion_result compile_bitwise_and() +{ + expresion_result left = compile_comparison_2(), right, res ; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && ( token.code == identifier_band || token.code == identifier_bandoffset ) ) /* "BAND" or "&" */ + { + if ( left.lvalue ) codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + right = compile_comparison_2() ; + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + check_integer_types( &left, &right ) ; + + codeblock_add( code, MN_BAND, 0 ) ; + + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.constant = ( right.constant && left.constant ) ; + res.value = ( left.value & right.value ) ; + res.type = left.type /* typedef_new( TYPE_INT )*/ ; + + left = res ; + continue ; + } + + token_back() ; + break; + } + + return left ; +} + +expresion_result compile_bitwise_xor() +{ + expresion_result left = compile_bitwise_and(), right, res ; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_bxor ) /* "BXOR" or "^" */ + { + if ( left.lvalue ) codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + right = compile_bitwise_and() ; + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + check_integer_types( &left, &right ) ; + + codeblock_add( code, MN_BXOR, 0 ) ; + + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.constant = ( right.constant && left.constant ) ; + res.value = ( left.value ^ right.value ) ; + res.type = left.type /* typedef_new( TYPE_INT )*/ ; + + left = res ; + continue ; + } + + token_back() ; + break; + } + + return left ; +} + +/* Paso 3 */ +expresion_result compile_bitwise_or() +{ + expresion_result left = compile_bitwise_xor(), right, res ; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_bor ) /* "BOR" or "|" */ + { + if ( left.lvalue ) codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + right = compile_bitwise_xor() ; + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + check_integer_types( &left, &right ) ; + + codeblock_add( code, MN_BOR, 0 ) ; + + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.constant = ( right.constant && left.constant ) ; + res.value = ( left.value | right.value ) ; + res.type = left.type /*typedef_new( TYPE_INT )*/ ; + + left = res ; + continue ; + } + + token_back() ; + break; + } + return left ; +} + + +/* Paso 2 */ +expresion_result compile_logical_and() +{ + expresion_result left = compile_bitwise_or(), right, res ; + int et1; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_and ) /* "AND" or "&&" */ + { + et1 = codeblock_label_add( code, -1 ); + + if ( left.lvalue ) codeblock_add( code, MN_PTR | mntype( left.type, 0 ), 0 ) ; + check_integer_type( &left ) ; + codeblock_add( code, MN_JTFALSE, et1 ) ; + right = compile_bitwise_or() ; + if ( right.lvalue ) codeblock_add( code, MN_PTR | mntype( right.type, 0 ), 0 ) ; + check_integer_type( &right ) ; + + codeblock_add( code, MN_AND, 0 ) ; + + codeblock_label_set( code, et1, code->current ) ; + + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.constant = ( right.constant && left.constant ) ; + res.value = ( left.value && right.value ) ; + res.type = typedef_new( TYPE_INT ) ; + + left = res ; + continue ; + } + + token_back() ; + break; + } + + return left ; +} + +/* Paso 2 */ +expresion_result compile_logical_xor() +{ + expresion_result left = compile_logical_and(), right, res ; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_xor ) /* "XOR" or "^^" */ + { + if ( left.lvalue ) codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + right = compile_logical_and() ; + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + check_integer_types( &left, &right ) ; + + codeblock_add( code, MN_XOR, 0 ) ; + + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.constant = ( right.constant && left.constant ) ; + res.value = (( left.value != 0 ) ^( right.value != 0 ) ) ; + res.type = typedef_new( TYPE_INT ) ; + + left = res ; + continue ; + } + + token_back() ; + break; + } + + return left ; +} + +/* Paso 2 */ +expresion_result compile_logical_or() +{ + expresion_result left = compile_logical_xor(), right, res ; + int et1; + int et2; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_or ) /* "OR" or "||" */ + { + et1 = codeblock_label_add( code, -1 ); + et2 = codeblock_label_add( code, -1 ); + + if ( left.lvalue ) codeblock_add( code, mntype( left.type, 0 ) | MN_PTR, 0 ) ; + check_integer_type( &left ) ; + codeblock_add( code, MN_JTFALSE, et1 ) ; + + codeblock_add( code, MN_POP, 0 ); + codeblock_add( code, MN_PUSH, 1 ); + codeblock_add( code, MN_JUMP, et2 ); + + codeblock_label_set( code, et1, code->current ) ; + + right = compile_logical_xor() ; + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + check_integer_type( &right ) ; + + codeblock_add( code, MN_OR, 0 ) ; + + codeblock_label_set( code, et2, code->current ) ; + + res.lvalue = 0 ; + res.asignation = 0 ; + res.call = 0 ; + res.constant = ( right.constant && left.constant ) ; + res.value = ( left.value || right.value ) ; + res.type = typedef_new( TYPE_INT ) ; + + left = res ; + continue; + } + + token_back() ; + break ; + } + return left ; +} + +/* Paso 1 */ +expresion_result compile_ternarycond() +{ + CODEBLOCK_POS pos ; + + if ( code ) pos = codeblock_pos( code ); + + expresion_result base = compile_logical_or(), right, res ; + int et1, et2 ; + + token_next() ; + /* Operador EXPR ? TRUE : FALSE */ + if ( token.type == IDENTIFIER && token.code == identifier_question ) /* "?" */ + { + if ( base.lvalue ) codeblock_add( code, mntype( base.type, 0 ) | MN_PTR, 0 ) ; + + if ( base.constant ) + { + codeblock_setpos( code, pos ); + + if ( + ( typedef_is_integer( base.type ) && base.value ) || + ( typedef_is_float( base.type ) && base.fvalue ) + ) + { + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ); + if ( code ) pos = codeblock_pos( code ); + token_next(); + if ( token.type != IDENTIFIER || token.code != identifier_colon ) compile_error( MSG_EXPECTED, ":" ); /* ":" */ + res = compile_expresion( 0, 0, 0, right.type.chunk[0].type ); + codeblock_setpos( code, pos ); + + } + else + { + if ( code ) pos = codeblock_pos( code ); + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ); + codeblock_setpos( code, pos ); + token_next(); + if ( token.type != IDENTIFIER || token.code != identifier_colon ) compile_error( MSG_EXPECTED, ":" ); /* ":" */ + res = compile_expresion( 0, 0, 0, right.type.chunk[0].type ); + } + } + else + { + et1 = codeblock_label_add( code, -1 ); + et2 = codeblock_label_add( code, -1 ); + codeblock_add( code, MN_JFALSE, et1 ); + + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ); + codeblock_add( code, MN_JUMP, et2 ); + + codeblock_label_set( code, et1, code->current ); + token_next(); + + if ( token.type != IDENTIFIER || token.code != identifier_colon ) compile_error( MSG_EXPECTED, ":" ); /* ":" */ + + res = compile_expresion( 0, 0, 0, right.type.chunk[0].type ); + codeblock_label_set( code, et2, code->current ); + } + + if ( base.constant && res.constant && right.constant ) + { + if ( typedef_is_integer( base.type ) ) + { + return base.value ? right : res; + } + else if ( typedef_is_float( base.type ) ) + { + return base.fvalue ? right : res; + } + } + + res.constant = 0; + res.lvalue = ( right.lvalue && res.lvalue ); + + return res; + } + + token_back() ; + return base; +} + + +/* Paso 1 */ +expresion_result compile_subexpresion() +{ + expresion_result base = compile_ternarycond(), right, res ; + int op, type ; + + token_next() ; + if ( token.type == IDENTIFIER ) + { + /* Asignaciones */ + if ( token.code == identifier_equal ) /* "=" */ + { + if ( typedef_is_array( base.type ) && base.lvalue && base.type.chunk[1].type == TYPE_CHAR ) /* Asignaciones a cadenas de ancho fijo */ + { + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ) ; + if ( typedef_is_integer( right.type ) ) + { + compile_warning( 1, "implicit conversion (INTEGER to CHAR[])" ); + codeblock_add( code, MN_INT2STR | mntype( right.type, 0 ), 0 ) ; + } + else if ( typedef_is_float( right.type ) ) + { + compile_warning( 1, "implicit conversion (FLOAT to CHAR[])" ); + codeblock_add( code, MN_FLOAT2STR, 0 ) ; + } + else if ( !typedef_is_string( right.type ) ) + { + compile_error( MSG_INCOMP_TYPE ) ; + } + codeblock_add( code, MN_STR2A, base.type.chunk[0].count - 1 ) ; + right.asignation = 1 ; + + return right ; + } + + if ( typedef_is_pointer( base.type ) ) /* Asignaciones a punteros */ + { + TYPEDEF pointer_type ; + + pointer_type = typedef_reduce( base.type ) ; + if ( !base.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ) ; + + if (( typedef_base( right.type ) == TYPE_DWORD || typedef_base( right.type ) == TYPE_INT ) && right.constant && right.value == 0 ) + { + right.type = base.type ; + } + + if ( typedef_base( right.type ) == TYPE_FLOAT ) + { + compile_warning( 1, "implicit conversion (FLOAT to POINTER)" ); + codeblock_add( code, MN_FLOAT2INT, 0 ); + right.type = base.type; + } + + /* Un puntero "void" puede asignarse a otro cualquiera */ + right.type = typedef_pointer( pointer_type ) ; + if ( typedef_base( typedef_reduce( right.type ) ) != typedef_base( pointer_type ) ) compile_error( MSG_TYPES_NOT_THE_SAME ) ; + + codeblock_add( code, MN_DWORD | MN_LET, 0 ) ; + + res.lvalue = 1 ; + res.asignation = 1 ; + res.call = 0 ; + res.constant = 0 ; + res.value = 0 ; + res.type = base.type ; + + return res ; + } + + if ( typedef_base( base.type ) == TYPE_CHAR ) /* Asignaciones a chars */ + { + if ( !base.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ) ; + + if ( typedef_is_string( right.type ) ) + { + compile_warning( 1, "implicit conversion (STRING to CHAR)" ); + codeblock_add( code, MN_STR2CHR, 0 ) ; + } + else if ( typedef_base( right.type ) == TYPE_FLOAT ) + { + compile_warning( 1, "implicit conversion (FLOAT to CHAR)" ); + codeblock_add( code, MN_FLOAT2INT, 0 ) ; + } + else if ( !typedef_is_numeric( right.type ) ) + { + compile_error( MSG_INCOMP_TYPE ) ; + } + + codeblock_add( code, MN_LET | MN_BYTE, 0 ) ; + + res.lvalue = 1 ; + res.asignation = 1 ; + res.call = 0 ; + res.constant = 0 ; + res.value = 0 ; + res.type = typedef_new( TYPE_CHAR ) ; + + return res ; + } + + if ( typedef_is_string( base.type ) ) /* Asignaciones a cadenas */ + { + if ( !base.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ) ; + + if ( typedef_base( right.type ) == TYPE_CHAR ) + { + compile_warning( 1, "implicit conversion (CHAR to STRING)" ); + codeblock_add( code, MN_CHR2STR, 0 ) ; + } + else if ( typedef_is_integer( right.type ) ) + { + compile_warning( 1, "implicit conversion (INTEGER to STRING)" ); + codeblock_add( code, MN_INT2STR | mntype( right.type, 0 ), 0 ) ; + } + else if ( typedef_is_float( right.type ) ) + { + compile_warning( 1, "implicit conversion (FLOAT to STRING)" ); + codeblock_add( code, MN_FLOAT2STR, 0 ) ; + } + else if ( typedef_is_pointer( right.type ) ) + { + compile_warning( 1, "implicit conversion (POINTER to STRING)" ); + codeblock_add( code, MN_POINTER2STR, 0 ) ; + } + else if ( !typedef_is_string( right.type ) ) + { + compile_error( MSG_INCOMP_TYPE ) ; + } + codeblock_add( code, MN_STRING | MN_LET, 0 ) ; + + res.lvalue = 1 ; + res.asignation = 1 ; + res.call = 0 ; + res.constant = 0 ; + res.value = 0 ; + res.type = typedef_new( TYPE_STRING ) ; + + return res ; + } + } + + /* Puntero += entero */ + + if ( typedef_is_pointer( base.type ) && ( token.code == identifier_plusequal || token.code == identifier_minusequal ) ) /* "+=" or "-=" */ + { + TYPEDEF pointer_type ; + + op = ( token.code == identifier_plusequal ? MN_VARADD : MN_VARSUB ) ; + pointer_type = typedef_reduce( base.type ) ; + if ( !base.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ) ; + + if ( !typedef_is_integer( right.type ) ) compile_error( MSG_INCOMP_TYPES ) ; + + if ( typedef_size( pointer_type ) > 1 ) + codeblock_add( code, MN_ARRAY, ( op == MN_VARADD ? 1 : -1 ) * typedef_size( pointer_type ) ) ; + else + codeblock_add( code, op, 0 ) ; + + res.lvalue = 1 ; + res.asignation = 1 ; + res.call = 0 ; + res.constant = 0 ; + res.value = 0 ; + res.type = typedef_new( TYPE_STRING ) ; + + return res ; + } + + /* Increment and assign */ + + if ( token.code == identifier_plusequal ) /* "+=" */ + { + if ( typedef_is_array( base.type ) && base.lvalue && base.type.chunk[1].type == TYPE_CHAR ) /* Cadena += cadena fija */ + { + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ) ; + if ( typedef_is_integer( right.type ) ) + { + compile_warning( 1, "implicit conversion (INTEGER to CHAR[])" ); + codeblock_add( code, MN_INT2STR | mntype( right.type, 0 ), 0 ) ; + } + else if ( typedef_is_float( right.type ) ) + { + compile_warning( 1, "implicit conversion (FLOAT to CHAR[])" ); + codeblock_add( code, MN_FLOAT2STR, 0 ) ; + } + else if ( typedef_base( right.type ) == TYPE_CHAR ) + { + compile_warning( 1, "implicit conversion (CHAR to CHAR[])" ); + codeblock_add( code, MN_CHR2STR, 0 ); + } + else if ( !typedef_is_string( right.type ) ) + { + compile_error( MSG_INCOMP_TYPE ) ; + } + codeblock_add( code, MN_STRACAT, base.type.chunk[0].count ) ; + right.asignation = 1 ; + + return right ; + } + + if ( typedef_is_string( base.type ) ) + { + if ( !base.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ) ; + if ( typedef_is_integer( right.type ) ) + { + compile_warning( 1, "implicit conversion (INTEGER to STRING)" ); + codeblock_add( code, MN_INT2STR | mntype( right.type, 0 ), 0 ) ; + } + else if ( typedef_is_float( right.type ) ) + { + compile_warning( 1, "implicit conversion (FLOAT to STRING)" ); + codeblock_add( code, MN_FLOAT2STR, 0 ) ; + } + else if ( typedef_base( right.type ) == TYPE_CHAR ) + { + compile_warning( 1, "implicit conversion (CHAR to STRING)" ); + codeblock_add( code, MN_CHR2STR, 0 ); + } + else if ( !typedef_is_string( right.type ) ) + { + compile_error( MSG_INCOMP_TYPE ) ; + } + codeblock_add( code, MN_STRING | MN_VARADD, 0 ) ; + + res.lvalue = 1 ; + res.asignation = 1 ; + res.call = 0 ; + res.constant = 0 ; + res.value = 0 ; + res.type = typedef_new( TYPE_STRING ) ; + + return res ; + } + } + + /* Otra posible combinación(for not string/char[]/pointers) */ + + if ( token.code == identifier_plusequal /* "+=" */ + || token.code == identifier_minusequal /* "-=" */ + || token.code == identifier_multequal /* "*=" */ + || token.code == identifier_divequal /* "/=" */ + || token.code == identifier_modequal /* "%=" */ + || token.code == identifier_andequal /* "&=" */ + || token.code == identifier_xorequal /* "^=" */ + || token.code == identifier_orequal /* "|=" */ + || token.code == identifier_rolequal /* "<<=" */ + || token.code == identifier_rorequal /* ">>=" */ + || token.code == identifier_equal ) /* "=" */ + { + SYSPROC * proc_copy = sysproc_get( identifier_search_or_add( "#COPY#" ) ); + SYSPROC * proc_memcopy = sysproc_get( identifier_search_or_add( "#MEMCOPY#" ) ); + SYSPROC * proc_copy_string_array = sysproc_get( identifier_search_or_add( "#COPYSTRA#" ) ); + int size, nvar; + + op = token.code ; + + /* Assignation to struct: struct copy */ + if ( typedef_is_struct( base.type ) ) + { + if ( token.code != identifier_equal ) compile_error( MSG_EXPECTED, "=" ) ; /* "=" */ + + right = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ); + while ( typedef_is_array( right.type ) ) right.type = typedef_reduce( right.type ); + + if ( typedef_base( right.type ) != TYPE_POINTER ) compile_error( MSG_STRUCT_REQUIRED ); + + if ( !typedef_is_struct( typedef_reduce( right.type ) ) ) + { + compile_error( MSG_STRUCT_REQUIRED ); + } + else if ( right.type.varspace != base.type.varspace ) + { + compile_error( MSG_TYPES_NOT_THE_SAME ); + } + else + { + /* + * Struct copy operator + */ + + while ( typedef_is_pointer( base.type ) ) + { + codeblock_add( code, MN_PTR, 0 ); + res.type = typedef_reduce( base.type ); + } + + if ( typedef_base( base.type ) != TYPE_STRUCT ) + compile_error( MSG_STRUCT_REQUIRED ); + else + { + size = right.type.varspace->count * sizeof( DCB_TYPEDEF ); + + if ( right.type.varspace->stringvar_count > 0 ) + { + /* True struct copy version */ + + segment_alloc( globaldata, size ); + codeblock_add( code, MN_GLOBAL, globaldata->current ) ; + for ( nvar = 0 ; nvar < right.type.varspace->count ; nvar++ ) + { + DCB_TYPEDEF type; + dcb_settype( &type, &right.type.varspace->vars[nvar].type ); + memcpy(( uint8_t* )globaldata->bytes + globaldata->current, &type, sizeof( DCB_TYPEDEF ) ); + globaldata->current += sizeof( DCB_TYPEDEF ); + } + codeblock_add( code, MN_PUSH, right.type.varspace->count ); + codeblock_add( code, MN_PUSH, right.count ? right.count : 1 ); + codeblock_add( code, MN_SYSCALL, proc_copy->code ); + } + else + { + /* Optimized fast memcopy version */ + codeblock_add( code, MN_PUSH, right.type.varspace->size*( right.count ? right.count : 1 ) ); + codeblock_add( code, MN_SYSCALL, proc_memcopy->code ); + } + } + base.type = right.type; + base.constant = 0; + base.lvalue = 0; + base.call = 1; + } + return base; + } + + if ( op != identifier_equal && typedef_is_array( base.type ) ) compile_error( MSG_EXPECTED, "[" ) ; + + if ( !base.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + right = compile_expresion( 0, 0, 0, typedef_base( base.type ) ) ; + + /* Array copy */ + if ( op == identifier_equal && typedef_is_array( base.type ) && typedef_is_array( right.type ) ) + { + int size; + + if ( !typedef_is_equal( base.type, right.type ) ) compile_error( MSG_TYPES_NOT_THE_SAME ); + + size = typedef_size( base.type ); + + while ( typedef_is_array( base.type ) ) + { + base.type = typedef_reduce( base.type ) ; + right.type = typedef_reduce( right.type ) ; + } + + /* Optimized fast memcopy version */ + if ( typedef_is_string( base.type ) ) + { + codeblock_add( code, MN_PUSH, size / sizeof( int ) ); + codeblock_add( code, MN_SYSCALL, proc_copy_string_array->code ); + } + else + { + codeblock_add( code, MN_PUSH, size ); + codeblock_add( code, MN_SYSCALL, proc_memcopy->code ); + } + + base.type = right.type; + base.constant = 0; + base.lvalue = 0; + base.call = 1; + + return base; + } + + if ( right.lvalue ) codeblock_add( code, mntype( right.type, 0 ) | MN_PTR, 0 ) ; + + type = check_numeric_types( &base, &right ) ; + + if ( op == identifier_plusequal ) /* "+=" */ + codeblock_add( code, type | MN_VARADD, 0 ) ; + else if ( op == identifier_minusequal ) /* "-=" */ + codeblock_add( code, type | MN_VARSUB, 0 ) ; + else if ( op == identifier_multequal ) /* "*=" */ + codeblock_add( code, type | MN_VARMUL, 0 ) ; + else if ( op == identifier_divequal ) /* "/=" */ + codeblock_add( code, type | MN_VARDIV, 0 ) ; + else if ( op == identifier_modequal ) /* "%=" */ + codeblock_add( code, type | MN_VARMOD, 0 ) ; + else if ( op == identifier_orequal ) /* "|=" */ + codeblock_add( code, type | MN_VAROR, 0 ) ; + else if ( op == identifier_andequal ) /* "&=" */ + codeblock_add( code, type | MN_VARAND, 0 ) ; + else if ( op == identifier_xorequal ) /* "^=" */ + codeblock_add( code, type | MN_VARXOR, 0 ) ; + else if ( op == identifier_rorequal ) /* ">>=" */ + codeblock_add( code, type | MN_VARROR, 0 ) ; + else if ( op == identifier_rolequal ) /* "<<=" */ + codeblock_add( code, type | MN_VARROL, 0 ) ; + else if ( op == identifier_equal ) /* "=" */ + codeblock_add( code, type | MN_LET, 0 ) ; + + res.lvalue = 1 ; + res.asignation = 1 ; + res.call = 0 ; + res.constant = 0 ; + res.value = 0 ; + res.type = right.type ; + + return res ; + } + else + { + token_back() ; + } + } + else + { + token_back() ; + } + + return base ; +} + +expresion_result compile_expresion( int need_constant, int need_lvalue, int discart_code, BASETYPE t ) +{ + expresion_result res ; + + CODEBLOCK_POS pos ; + + if ( code ) pos = codeblock_pos( code ); + + res = compile_subexpresion() ; + + /* Interpreta una estructura tal cual como un puntero a la misma */ + + if ( res.lvalue && typedef_base( res.type ) == TYPE_STRUCT && !need_lvalue ) + { + res.type = typedef_pointer( res.type ) ; + res.lvalue = 0 ; + res.constant = 0 ; + } + + /* Interpretar arrays de byte como cadenas */ + + if ( typedef_base( res.type ) == TYPE_ARRAY && res.type.chunk[1].type == TYPE_CHAR && res.lvalue && !need_lvalue ) + { + codeblock_add( code, MN_A2STR, 0 ) ; + res.type = typedef_new( TYPE_STRING ) ; /* Array 2 String */ + res.lvalue = 0 ; + } + + /* Quita los lvalue */ + + if ( !need_lvalue && res.lvalue && !typedef_is_array( res.type ) ) + { + res.lvalue = 0 ; + codeblock_add( code, mntype( res.type, 0 ) | MN_PTR, 0 ) ; + } + + /* Conversiones de tipo */ + + if ( t != TYPE_UNDEFINED ) res = convert_result_type( res, t ) ; + + /* Optimización de datos constantes */ + + if ( res.constant ) + { + if ( code ) codeblock_setpos( code, pos ); + if ( typedef_base( res.type ) == TYPE_FLOAT ) + codeblock_add( code, MN_PUSH, *( int * )&res.fvalue ) ; + else if ( typedef_base( res.type ) == TYPE_STRING ) + codeblock_add( code, MN_PUSH | MN_STRING, res.value ) ; + else + codeblock_add( code, MN_PUSH, res.value ) ; + } + + if ( need_lvalue && !res.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + + if ( need_constant && !res.constant ) compile_error( MSG_CONSTANT_EXP ) ; + + if ( discart_code && code ) codeblock_setpos( code, pos ); + + return res ; +} + +/* + * FUNCTION : convert_result_type + * + * Given an expresion result in the current context, convert it + * if possible to the basic type given(and emit the necessary code) + * + * PARAMS: + * res Result of expression at current context + * t Basic type required + * + * RETURN VALUE: + * The converted type result + */ + +expresion_result convert_result_type( expresion_result res, BASETYPE t ) +{ + /* Conversiones de tipo */ + + if ( t < 9 && typedef_is_integer( res.type ) ) + { + res.type = typedef_new( t ); + } + else if ( typedef_base( res.type ) == TYPE_POINTER && t == TYPE_STRING ) + { + codeblock_add( code, MN_POINTER2STR, 0 ) ; + res.type = typedef_new( t ) ; /* Pointer 2 String */ + } + else if ( typedef_is_integer( res.type ) /*&& res.constant && res.value == 0*/ && t == TYPE_POINTER ) + { + res.type = typedef_new( t ) ; /* pointer */ + } + else if ( typedef_base( res.type ) == TYPE_POINTER && t < 8 ) + { + res.type = typedef_new( t ) ; /* Pointer 2 Int */ + } + else if ( typedef_base( res.type ) == TYPE_FLOAT && t < 8 ) + { + codeblock_add( code, MN_FLOAT2INT, 0 ) ; + + res.type = typedef_new( t ) ; + res.value = ( int )res.fvalue ; + } + else if ( t == TYPE_FLOAT && typedef_is_integer( res.type ) ) + { + codeblock_add( code, MN_INT2FLOAT, 0 ) ; + res.type = typedef_new( TYPE_FLOAT ) ; + res.fvalue = ( float )res.value ; + } + else if (( t == TYPE_BYTE || t == TYPE_WORD || t == TYPE_DWORD ) && typedef_is_integer( res.type ) ) + { + res.type = typedef_new( t ) ; + } + else if ( t == TYPE_STRING && typedef_is_integer( res.type ) ) + { + codeblock_add( code, MN_INT2STR | mntype( res.type, 0 ), 0 ) ; + if ( res.constant ) + { + char buffer[32] ; + switch ( res.type.chunk[0].type ) + { + case TYPE_INT: + sprintf( buffer, "%d", res.value ) ; + break; + + case TYPE_WORD: + sprintf( buffer, "%d", ( uint16_t )res.value ) ; + break; + + case TYPE_BYTE: + sprintf( buffer, "%d", ( uint8_t )res.value ) ; + break; + + case TYPE_SHORT: + sprintf( buffer, "%d", ( int16_t )res.value ) ; + break; + + case TYPE_SBYTE: + sprintf( buffer, "%d", ( int8_t )res.value ) ; + break; + + case TYPE_DWORD: + sprintf( buffer, "%u", ( int32_t )res.value ) ; + break; + + case TYPE_UNDEFINED : + case TYPE_CHAR : + case TYPE_FLOAT : + case TYPE_STRING : + case TYPE_ARRAY : + case TYPE_STRUCT : + case TYPE_POINTER : + break; + } + res.value = string_new( buffer ) ; + } + res.type = typedef_new( t ) ; + } + else if ( t == TYPE_STRING && typedef_base( res.type ) == TYPE_CHAR ) + { + codeblock_add( code, MN_CHR2STR, 0 ) ; + if ( res.constant ) + { + char buffer[2] ; + buffer[0] = res.value; + buffer[1] = 0; + res.value = string_new( buffer ) ; + } + res.type = typedef_new( t ) ; + } + else if ( t != TYPE_UNDEFINED && typedef_base( res.type ) != t ) + { + switch ( t ) + { + case TYPE_CHAR: + + /* Allow string-to-char conversions */ + + if ( typedef_is_string( res.type ) ) + { + codeblock_add( code, MN_STR2CHR, 0 ) ; + if ( res.constant == 1 ) res.value = ( unsigned char ) * ( string_get( res.value ) ); + } + else + compile_error( MSG_INTEGER_REQUIRED ) ; + break ; + + case TYPE_DWORD: + case TYPE_INT: + case TYPE_WORD: + case TYPE_SHORT: + case TYPE_BYTE: + case TYPE_SBYTE: + if ( typedef_is_array( res.type ) && res.lvalue && + res.type.chunk[1].type == TYPE_CHAR ) + { + codeblock_add( code, MN_A2STR, 0 ) ; + codeblock_add( code, MN_STR2INT, 0 ) ; + res.lvalue = 0 ; + res.constant = 0; + } + else if ( typedef_is_string( res.type ) ) + { + codeblock_add( code, MN_STR2INT, 0 ) ; + if ( res.constant == 1 ) res.value = atoi( string_get( res.value ) ); + } + else if ( typedef_base( res.type ) == TYPE_CHAR ) + { + res.type = typedef_new( t ); + } + else + compile_error( MSG_INTEGER_REQUIRED ) ; + break ; + + case TYPE_FLOAT: + if ( typedef_is_string( res.type ) ) + { + codeblock_add( code, MN_STR2FLOAT, 0 ) ; + if ( res.constant == 1 ) res.fvalue = ( float )atof( string_get( res.value ) ); + } + else + compile_error( MSG_NUMBER_REQUIRED ) ; + break ; + + case TYPE_STRING: + if ( typedef_is_array( res.type ) && res.lvalue && + res.type.chunk[1].type == TYPE_CHAR ) + { + codeblock_add( code, MN_A2STR, 0 ) ; + res.lvalue = 0 ; + } + else if ( typedef_is_integer( res.type ) ) + { + codeblock_add( code, MN_INT2STR | mntype( res.type, 0 ), 0 ) ; + if ( res.constant ) + { + char buffer[32] ; + sprintf( buffer, "%d", res.value ) ; + res.value = string_new( buffer ) ; + } + } + else if ( typedef_is_float( res.type ) ) + { + codeblock_add( code, MN_FLOAT2STR, 0 ) ; + if ( res.constant ) + { + char buffer[32] ; + sprintf( buffer, "%g", res.fvalue ) ; + res.value = string_new( buffer ) ; + } + } + else + compile_error( MSG_STRING_EXP ) ; + break ; + + default: + compile_error( MSG_INCOMP_TYPE ) ; + } + res.type = typedef_new( t ) ; + } + + return res ; +} + +int compile_sentence_end() +{ + token_next() ; + + if ( token.type == NOTOKEN ) return 1; + + if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) return 0 ; /* ";" */ + + /* + if (token.type == IDENTIFIER && token.code == identifier_end) + { + token_back() ; + return 1 ; + } + */ + + compile_error( MSG_EXPECTED, ";" ) ; + return 0; +} + +extern int dcb_options ; + +void basetype_describe( char * buffer, BASETYPE t ) +{ + switch ( t ) + { + case TYPE_INT: + sprintf( buffer, "INT" ) ; + return ; + + case TYPE_DWORD: + sprintf( buffer, "DWORD" ) ; + return ; + + case TYPE_SHORT: + sprintf( buffer, "SHORT" ) ; + return ; + + case TYPE_WORD: + sprintf( buffer, "WORD" ) ; + return ; + + case TYPE_BYTE: + sprintf( buffer, "BYTE" ) ; + return ; + + case TYPE_CHAR: + sprintf( buffer, "CHAR" ) ; + return ; + + case TYPE_SBYTE: + sprintf( buffer, "SIGNED BYTE" ) ; + return ; + + case TYPE_STRING: + sprintf( buffer, "STRING" ) ; + return ; + + case TYPE_FLOAT: + sprintf( buffer, "FLOAT" ) ; + return ; + + case TYPE_STRUCT: + sprintf( buffer, "STRUCT" ) ; + + case TYPE_ARRAY: + sprintf( buffer, "ARRAY" ) ; + return ; + + case TYPE_POINTER: + sprintf( buffer, "POINTER" ) ; + return ; + + case TYPE_UNDEFINED: + default: + sprintf( buffer, "<UNDEFINED>" ) ; + return ; + } +} + +void compile_block( PROCDEF * p ) +{ + int loop, last_loop, et1, et2 ; + expresion_result res, from, to ; + int codelabel; + + proc = p ; + code = &p->code ; + + for ( ;; ) + { + token_next() ; + if ( token.type == NOTOKEN ) break ; + + if ( token.type == IDENTIFIER ) + { + if ( token.code == identifier_end || /* "END" */ + token.code == identifier_until || /* "UNTIL" */ + token.code == identifier_else || /* "ELSE" */ + token.code == identifier_elseif ) /* "ELSEIF" */ + break ; + + if ( token.code == identifier_semicolon ) /* ";" */ + continue ; + + if ( token.code == identifier_colon ) /* ":" */ + continue ; + + if ( token.code == identifier_continue ) /* "CONTINUE" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + if ( !code->loop_active ) compile_error( MSG_NO_LOOP ) ; + + codeblock_add( code, MN_REPEAT, code->loop_active ) ; + compile_sentence_end() ; + continue ; + } + + if ( token.code == identifier_break ) /* "BREAK" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + if ( !code->loop_active ) compile_error( MSG_NO_LOOP ) ; + + codeblock_add( code, MN_BREAK, code->loop_active ) ; + compile_sentence_end() ; + continue ; + } + + if ( token.code == identifier_frame || token.code == identifier_yield ) /* "FRAME or YIELD " */ + { + if ( proc->type != TYPE_INT && proc->type != TYPE_DWORD ) + if ( !( proc->flags & PROC_FUNCTION ) ) compile_error( MSG_FRAME_REQUIRES_INT ); + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) /* ";" */ + { + token_back() ; + compile_expresion( 0, 0, 0, TYPE_DWORD ) ; + codeblock_add( code, MN_FRAME, 0 ) ; + compile_sentence_end() ; + } + else + { + codeblock_add( code, MN_PUSH, 100 ) ; + codeblock_add( code, MN_FRAME, 0 ) ; + } + proc->flags |= PROC_USES_FRAME; + continue ; + } + + if ( token.code == identifier_debug ) /* "DEBUG" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + codeblock_add( code, MN_DEBUG, 0 ) ; + compile_sentence_end() ; + continue ; + } + + if ( token.code == identifier_return ) /* "RETURN" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) /* ";" */ + { + token_back() ; + compile_expresion( 0, 0, 0, p->type ) ; + codeblock_add( code, MN_RETURN, 0 ) ; + compile_sentence_end() ; + } + else + { + codeblock_add( code, MN_END, 0 ) ; + } + continue ; + } + + if ( token.code == identifier_clone ) /* "CLONE" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + et1 = codeblock_label_add( code, -1 ) ; + codeblock_add( code, MN_CLONE, et1 ) ; + compile_block( p ) ; + codeblock_label_set( code, et1, code->current ) ; + proc->flags |= PROC_USES_FRAME; + continue ; + } + + if ( token.code == identifier_if ) /* "IF" */ + { + /* Label at the end of a IF/ELSEIF/ELSEIF/ELSE chain */ + int end_of_chain = -1; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + for ( ;; ) + { + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_leftp ) /* "(" */ + { + token_back() ; + compile_expresion( 0, 0, 0, TYPE_DWORD ); + token_next() ; + if ( token.type != IDENTIFIER || ( token.code != identifier_semicolon && token.code != identifier_colon ) ) /* ";" or ":" */ + compile_error( MSG_EXPECTED, ";" MSG_OR ":" ) ; + } + else + { + compile_expresion( 0, 0, 0, TYPE_DWORD ); + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) /* ")" */ + compile_error( MSG_EXPECTED, ")" ) ; + } + + et1 = codeblock_label_add( code, -1 ) ; + codeblock_add( code, MN_JFALSE, et1 ) ; + compile_block( p ) ; + if ( token.type == IDENTIFIER && token.code == identifier_else ) /* "ELSE" */ + { + et2 = codeblock_label_add( code, -1 ) ; + codeblock_add( code, MN_JUMP, et2 ) ; + codeblock_label_set( code, et1, code->current ) ; + compile_block( p ) ; + codeblock_label_set( code, et2, code->current ) ; + break; + } + else if ( token.type == IDENTIFIER && token.code == identifier_elseif ) /* "ELSEIF" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + if ( end_of_chain == -1 ) end_of_chain = codeblock_label_add( code, -1 ) ; + codeblock_add( code, MN_JUMP, end_of_chain ); + codeblock_label_set( code, et1, code->current ) ; + continue; + } + else + { + codeblock_label_set( code, et1, code->current ) ; + break; + } + } + if ( end_of_chain != -1 ) codeblock_label_set( code, end_of_chain, code->current ) ; + continue ; + } + + if ( token.code == identifier_for ) /* "FOR" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + loop = codeblock_loop_add( code ) ; + et1 = codeblock_label_add( code, -1 ) ; + et2 = codeblock_label_add( code, -1 ) ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_leftp ) /* "(" */ + compile_error( MSG_EXPECTED, "(" ) ; + + /* Inicializadores */ + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) /* ";" */ + { + token_back() ; + do + { + compile_expresion( 0, 0, 0, TYPE_DWORD ) ; + codeblock_add( code, MN_POP, 0 ) ; + token_next() ; + } + while ( token.type == IDENTIFIER && token.code == identifier_comma ) ; /* "," */ + } + + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) /* ";" */ + compile_error( MSG_EXPECTED, ";" ) ; + + codeblock_label_set( code, et1, code->current ) ; + + /* Condiciones */ + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) /* ";" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + token_back() ; + do + { + compile_expresion( 0, 0, 0, TYPE_DWORD ) ; + codeblock_add( code, MN_BRFALSE, loop ) ; + token_next() ; + } + while ( token.type == IDENTIFIER && token.code == identifier_comma ) ; /* "," */ + } + + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) /* ";" */ + compile_error( MSG_EXPECTED, ";" ) ; + + codeblock_add( code, MN_JUMP, et2 ) ; + + /* Incrementos */ + codeblock_loop_start( code, loop, code->current ) ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) /* ")" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + token_back() ; + do + { + compile_expresion( 0, 0, 0, TYPE_DWORD ) ; + codeblock_add( code, MN_POP, 0 ) ; + token_next() ; + } + while ( token.type == IDENTIFIER && token.code == identifier_comma ) ; /* "," */ + } + + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) /* ")" */ + compile_error( MSG_EXPECTED, ")" ) ; + + codeblock_add( code, MN_JUMP, et1 ) ; + + /* Bloque */ + codeblock_label_set( code, et2, code->current ) ; + + last_loop = code->loop_active ; + code->loop_active = loop ; + compile_block( p ) ; + code->loop_active = last_loop ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + codeblock_add( code, MN_REPEAT, loop ) ; + codeblock_loop_end( code, loop, code->current ) ; + continue ; + } + + if ( token.code == identifier_switch ) /* "SWITCH" */ + { + BASETYPE switch_type = TYPE_UNDEFINED; + expresion_result switch_exp ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_leftp ) /* "(" */ + compile_error( MSG_EXPECTED, "(" ) ; + + switch_exp = compile_expresion( 0, 0, 0, TYPE_UNDEFINED ) ; + switch_type = typedef_base( switch_exp.type ); + + if ( switch_type == TYPE_ARRAY && switch_exp.type.chunk[0].type == TYPE_CHAR ) + { + codeblock_add( code, MN_A2STR, 0 ) ; + switch_type = TYPE_STRING; + } + else if ( typedef_is_integer( switch_exp.type ) ) + { + switch_exp = convert_result_type( switch_exp, TYPE_INT ); + switch_type = TYPE_INT; + } + token_next() ; + + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) /* ")" */ + compile_error( MSG_EXPECTED, ")" ); + + token_next() ; + if ( token.type != IDENTIFIER || ( token.code != identifier_semicolon && token.code != identifier_colon ) ) /* ";" or ":" */ + token_back() ; + + if ( switch_type == TYPE_STRING ) + codeblock_add( code, MN_SWITCH | MN_STRING, 0 ) ; + else + codeblock_add( code, MN_SWITCH, 0 ) ; + + et1 = codeblock_label_add( code, -1 ) ; + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_case ) /* "CASE" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + for ( ;; ) + { + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_colon ) /* ":" */ + break ; + if ( token.type == IDENTIFIER && token.code == identifier_comma ) /* "," */ + continue ; + token_back() ; + + compile_expresion( 0, 0, 0, switch_type ) ; + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_twopoints ) /* ".." */ + { + compile_expresion( 0, 0, 0, switch_type ) ; + if ( switch_type == TYPE_STRING ) + { + codeblock_add( code, MN_CASE_R | MN_STRING, 0 ) ; + } + else + { + codeblock_add( code, MN_CASE_R, 0 ) ; + } + token_next() ; + } + else + { + if ( switch_type == TYPE_STRING ) + { + codeblock_add( code, MN_CASE | MN_STRING, 0 ) ; + } + else + { + codeblock_add( code, MN_CASE, 0 ) ; + } + } + + if ( token.type == IDENTIFIER && token.code == identifier_colon ) /* ":" */ + break ; + + if ( token.type != IDENTIFIER || token.code != identifier_comma ) /* "," */ + compile_error( MSG_EXPECTED, "," ) ; + } + et2 = codeblock_label_add( code, -1 ) ; + codeblock_add( code, MN_JNOCASE, et2 ) ; + compile_block( p ) ; + codeblock_add( code, MN_JUMP, et1 ) ; + codeblock_label_set( code, et2, code->current ) ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_default ) /* "DEFAULT" */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + token_next() ; + + if ( token.type != IDENTIFIER || token.code != identifier_colon ) /* ":" */ + compile_error( MSG_EXPECTED, ":" ) ; + + compile_block( p ) ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) /* ";" */ + continue ; + else if ( token.type == IDENTIFIER && token.code == identifier_end ) /* "END" */ + break ; + else + compile_error( MSG_EXPECTED, "CASE" ); + } + codeblock_label_set( code, et1, code->current ) ; + continue ; + } + + if ( token.code == identifier_loop ) /* "LOOP" */ + { + loop = codeblock_loop_add( code ) ; + codeblock_loop_start( code, loop, code->current ) ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + last_loop = code->loop_active ; + code->loop_active = loop ; + compile_block( p ) ; + code->loop_active = last_loop ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + codeblock_add( code, MN_REPEAT, loop ) ; + codeblock_loop_end( code, loop, code->current ) ; + continue ; + } + + /* FROM ... TO */ + + if ( token.code == identifier_from ) /* "FROM" */ + { + int inc = 1 ; + CODEBLOCK_POS var_pos; + CODEBLOCK_POS var_end; + int is_unsigned = 0; + int is_float = 0; + BASETYPE res_type = TYPE_UNDEFINED; + + et1 = codeblock_label_add( code, -1 ) ; + + /* Compile the variable access */ + + loop = codeblock_loop_add( code ) ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + var_pos = codeblock_pos( code ); + + res = compile_value() ; + res_type = typedef_base( res.type ); + + if ( typedef_is_unsigned( res.type ) ) is_unsigned = MN_UNSIGNED; + if ( typedef_is_float( res.type ) ) is_float = MN_FLOAT; + + var_end = codeblock_pos( code ); + if ( !res.lvalue ) compile_error( MSG_VARIABLE_REQUIRED ) ; + if ( !typedef_is_numeric( res.type ) ) compile_error( MSG_NUMBER_REQUIRED ); + + /* Compile the assignation of first value */ + + token_next() ; + + if ( token.type != IDENTIFIER || token.code != identifier_equal ) /* "=" */ + compile_error( MSG_EXPECTED, "=" ) ; + + from = compile_expresion( 0, 0, 0, res_type ); + codeblock_add( code, MN_LETNP | mntype( res.type, 0 ), 0 ); + + /* Compile the loop termination check */ + + codeblock_label_set( code, et1, code->current ) ; + + codeblock_add_block( code, var_pos, var_end ); + codeblock_add( code, MN_PTR | mntype( res.type, 0 ), 0 ); + token_next() ; + + if ( token.type != IDENTIFIER || token.code != identifier_to ) /* "TO" */ + compile_error( MSG_EXPECTED, "TO" ) ; + + to = compile_expresion( 0, 0, 0, res_type ) ; + + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_step ) /* "STEP" */ + { + CODEBLOCK_POS p = codeblock_pos( code ); + expresion_result r = compile_expresion( 1, 0, 0, res_type ) ; + if ( !r.constant ) compile_error( MSG_CONSTANT_EXP ); + if ( !typedef_is_numeric( r.type ) ) compile_error( MSG_NUMBER_REQUIRED ); + + if ( res_type == TYPE_FLOAT ) + { + if ( r.fvalue == 0.0 ) compile_error( MSG_INVALID_STEP ) ; + inc = *( int * ) & r.fvalue; + } + else + { + if ( r.value == 0 ) compile_error( MSG_INVALID_STEP ) ; + inc = r.value; + } + + codeblock_setpos( code, p ); + if (( res_type == TYPE_FLOAT && r.fvalue > 0 ) || ( res_type != TYPE_FLOAT && r.value > 0 ) ) + codeblock_add( code, MN_LTE | is_float | is_unsigned, 0 ) ; + else + codeblock_add( code, MN_GTE | is_float | is_unsigned, 0 ) ; + } + else + { + if ( from.constant && to.constant ) + { + int dec = 0; + if ( res_type == TYPE_FLOAT && from.fvalue > to.fvalue ) + { + float v = -1; + inc = *(( int * ) & v ); + dec = 1; + } + else if ( from.value > to.value ) + { + inc = -1; + dec = 1; + } + codeblock_add( code, ( dec ? MN_GTE : MN_LTE ) | is_float | is_unsigned, 0 ) ; + } + else + codeblock_add( code, MN_LTE | is_float | is_unsigned, 0 ) ; + token_back() ; + } + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) /* ";" */ + compile_error( MSG_EXPECTED, ";" ) ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + codeblock_add( code, MN_BRFALSE, loop ) ; + + /* Compile the loop block contents */ + + last_loop = code->loop_active ; + code->loop_active = loop ; + compile_block( p ) ; + code->loop_active = last_loop ; + + /* Compile the increment and looping code */ + + codeblock_loop_start( code, loop, code->current ) ; + + codeblock_add_block( code, var_pos, var_end ); + if ( inc == 1 ) + codeblock_add( code, MN_INC | mntype( res.type, 0 ), 1 ) ; + else if ( inc == -1 ) + codeblock_add( code, MN_DEC | mntype( res.type, 0 ), 1 ) ; + else + { + codeblock_add( code, MN_PUSH, inc ) ; + codeblock_add( code, MN_VARADD | mntype( res.type, 0 ), 0 ) ; + } + codeblock_add( code, MN_POP, 0 ) ; + codeblock_add( code, MN_JUMP, et1 ) ; + + codeblock_loop_end( code, loop, code->current ) ; + continue ; + } + + /* REPEAT ... UNTIL */ + + if ( token.code == identifier_repeat ) /* "REPEAT" */ + { + et1 = codeblock_label_add( code, -1 ) ; + et2 = codeblock_label_add( code, -1 ) ; + + loop = codeblock_loop_add( code ) ; + + codeblock_add( code, MN_JUMP, et1 ) ; + + codeblock_loop_start( code, loop, code->current ) ; + + codeblock_add( code, MN_JUMP, et2 ) ; + codeblock_label_set( code, et1, code->current ) ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + last_loop = code->loop_active ; + code->loop_active = loop ; + compile_block( p ) ; + code->loop_active = last_loop ; + + codeblock_label_set( code, et2, code->current ) ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + if ( token.type != IDENTIFIER || token.code != identifier_until ) /* "UNTIL" */ + compile_error( MSG_EXPECTED, "UNTIL" ) ; + + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_leftp ) /* "(" */ + { + compile_expresion( 0, 0, 0, TYPE_DWORD ) ; + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) /* ")" */ + compile_error( MSG_EXPECTED, ")" ) ; + } + else + { + token_back() ; + compile_expresion( 0, 0, 0, TYPE_DWORD ) ; + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) /* ";" */ + compile_error( MSG_EXPECTED, ";" ) ; + } + codeblock_add( code, MN_JFALSE, et1 ) ; + codeblock_loop_end( code, loop, code->current ) ; + continue ; + } + + /* WHILE ... END */ + + if ( token.code == identifier_while ) /* "WHILE" */ + { + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_leftp ) /* "(" */ + { + token_back() ; + loop = codeblock_loop_add( code ) ; + codeblock_loop_start( code, loop, code->current ) ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + compile_expresion( 0, 0, 0, TYPE_DWORD ) ; + token_next() ; + if ( token.type != IDENTIFIER || ( token.code != identifier_semicolon && token.code != identifier_colon ) ) /* ";" or ":" */ + compile_error( MSG_EXPECTED, ";" MSG_OR ":" ) ; + } + else + { + loop = codeblock_loop_add( code ) ; + codeblock_loop_start( code, loop, code->current ) ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + compile_expresion( 0, 0, 0, TYPE_DWORD ) ; + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) /* ")" */ + compile_error( MSG_EXPECTED, ")" ) ; + } + + codeblock_add( code, MN_BRFALSE, loop ) ; + + last_loop = code->loop_active ; + code->loop_active = loop ; + compile_block( p ) ; + code->loop_active = last_loop ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + codeblock_add( code, MN_REPEAT, loop ) ; + codeblock_loop_end( code, loop, code->current ) ; + continue ; + } + + if ( token.code == identifier_jmp ) /* JMP */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + token_next(); + + if ( token.type != IDENTIFIER ) compile_error( MSG_INVALID_PARAM ); + + if (( codelabel = codeblock_label_get_id_by_name( code, token.code ) ) == -1 ) + codelabel = codeblock_label_add( code, token.code ); + + codeblock_add( code, MN_JUMP, codelabel ); + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) compile_error( MSG_EXPECTED, ";" ) ; + continue; + } + + if ( token.code == identifier_call ) /* CALL */ + { + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + token_next(); + + if ( token.type != IDENTIFIER ) compile_error( MSG_INVALID_PARAM ); + + if (( codelabel = codeblock_label_get_id_by_name( code, token.code ) ) == -1 ) + codelabel = codeblock_label_add( code, token.code ); + + codeblock_add( code, MN_NCALL, codelabel ); + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) compile_error( MSG_EXPECTED, ";" ) ; + continue; + } + + if ( token.code == identifier_on ) /* ON EXIT/ON ERROR */ + { + int on_req = 0; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + token_next(); + + if ( token.type != IDENTIFIER || ( token.code != identifier_exit && token.code != identifier_error ) ) compile_error( MSG_ON_PARAM_ERR ); + + on_req = token.code; + + token_next(); + if ( token.type != IDENTIFIER || token.code != identifier_jmp ) compile_error( MSG_GOTO_EXP ); + + token_next(); + if ( token.type == NUMBER && token.code == 0 ) + codelabel = -1; + else if (( codelabel = codeblock_label_get_id_by_name( code, token.code ) ) == -1 ) + codelabel = codeblock_label_add( code, token.code ); + + codeblock_add( code, on_req == identifier_exit ? MN_EXITHNDLR : MN_ERRHNDLR, codelabel ); + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) compile_error( MSG_EXPECTED, ";" ) ; + continue; + } + } + + if ( token.type == LABEL || /* Label */ + ( token.type == IDENTIFIER && ( token.code == identifier_onexit || token.code == identifier_onerror ) ) /* ONEXIT or ONERROR */ + ) + { + if ( token.code == identifier_onexit ) /* "ONEXIT" */ + { + /* Finalizo el bloque actual y todo el codigo a continuacion es onexit */ + codeblock_add( code, MN_END, 0 ) ; + p->exitcode = code->current; + } + + if ( token.code == identifier_onerror ) /* "ONERROR" */ + { + /* Finalizo el bloque actual y todo el codigo a continuacion es onerror */ + codeblock_add( code, MN_END, 0 ) ; + p->errorcode = code->current; + } + + if (( codelabel = codeblock_label_get_id_by_name( code, token.code ) ) != -1 ) + { + if ( codeblock_label_get( code, codelabel ) != -1 ) + compile_error( "Label already defined" ); + } + else + { + codelabel = codeblock_label_add( code, token.code ); + } + + codeblock_label_set( code, codelabel, code->current ) ; + continue; + } + + if ( token.type != IDENTIFIER ) /* || token.code < reserved_words) */ compile_error( MSG_INVALID_SENTENCE ) ; + + if ( dcb_options & DCB_DEBUG ) codeblock_add( code, MN_SENTENCE, line_count + ( current_file << 20 ) ) ; + + token_back() ; + + /* Asignation */ + + res = compile_subexpresion() ; + if ( !res.asignation && !res.call ) + compile_error( MSG_INVALID_SENTENCE ) ; + if ( typedef_is_string( res.type ) && !res.lvalue ) + codeblock_add( code, MN_POP | MN_STRING, 0 ) ; + else + codeblock_add( code, MN_POP, 0 ) ; + + if ( compile_sentence_end() ) break ; + } +} + diff --git a/core/bgdc/src/c_data.c b/core/bgdc/src/c_data.c new file mode 100644 index 0000000..83ef97d --- /dev/null +++ b/core/bgdc/src/c_data.c @@ -0,0 +1,960 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#ifdef TARGET_BEOS +#include <posix/assert.h> +#else +#include <assert.h> +#endif +#include <string.h> +#include <stdlib.h> + +#include "bgdc.h" +#include "xctype.h" + +/* ---------------------------------------------------------------------- */ +/* Este módulo contiene las funciones que compilan definiciones de datos: */ +/* declaraciones de variables e inicialización de las mismas */ +/* ---------------------------------------------------------------------- */ + +int compile_array_data( VARSPACE * n, segment * data, int size, int subsize, BASETYPE *t ) +{ + int block, count = 0, base, remaining = size ; + int base_offset, total_length ; + + expresion_result res ; + + for ( ;; ) + { + if ( !remaining && size ) + { + token_back(); + break; +// compile_error( MSG_TOO_MANY_INIT ) ; + } + + token_next() ; + /* + if (*t == TYPE_UNDEFINED && token.type == STRING) + { + *t = typedef_base(typedef_new(TYPE_STRING)) ; + } + */ + if ( token.type == STRING && *t == TYPE_CHAR ) + { + const char * str = string_get( token.code ) ; + int subcount = 0 ; + + if ( subsize == 0 ) subsize = strlen( str ) + 1; + + if (( int )strlen( str ) > subsize ) compile_error( MSG_TOO_MANY_INIT ) ; + while ( *str ) + { + segment_add_as( data, *str++, *t ) ; + subcount++ ; + } + while ( subcount++ < subsize ) segment_add_as( data, 0, *t ) ; + count += subsize ; + remaining -= subsize ; + } + else if ( token.type == IDENTIFIER && ( token.code == identifier_rightp || token.code == identifier_semicolon ) ) + { + token_back() ; + break ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_leftp ) + { + block = compile_array_data( n, data, remaining, remaining, t ) ; + remaining -= block ; + count += block ; + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) + compile_error( MSG_EXPECTED, ")" ) ; + } + else + { + token_back() ; + res = compile_expresion( 1, 0, 0, *t ) ; + if ( *t == TYPE_UNDEFINED ) + { + *t = typedef_base( res.type ) ; + if ( *t == TYPE_UNDEFINED ) + { + compile_error( MSG_INCOMP_TYPE ) ; + } + } + base = res.value ; + if ( *t == TYPE_FLOAT ) base = *( int * ) & res.fvalue ; + + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_dup ) + { + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_leftp ) compile_error( MSG_EXPECTED, "(" ) ; + base_offset = data->current ; + block = compile_array_data( n, data, remaining, remaining, t ) ; + total_length = data->current - base_offset ; + if ( size && block * base > remaining ) + { + break; /* MSG_TOO_MANY_INIT */ + } + count += block * base ; + if ( size ) remaining -= block * base ; + while ( base-- > 1 ) + { + segment_copy( data, base_offset, total_length ) ; + base_offset += total_length ; + } + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) + compile_error( MSG_EXPECTED, ")" ) ; + } + else + { + token_back() ; + if ( *t == TYPE_STRING ) varspace_varstring( n, data->current ) ; + segment_add_as( data, base, *t ) ; + count ++ ; + if ( size ) remaining -- ; + } + } + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_comma ) + { + if ( !size && *t == TYPE_CHAR ) compile_error( MSG_TOO_MANY_INIT ); + continue ; + } + token_back() ; + break ; + } + + return count ; +} + +static BASETYPE get_basetype( VARSPACE * v ) +{ + TYPEDEF t ; + BASETYPE type = TYPE_UNDEFINED, newtype ; + int n ; + + for ( n = 0 ; n < v->count ; n++ ) + { + t = v->vars[n].type ; + while ( typedef_is_array( t ) ) + { + t = typedef_reduce( t ) ; + } + + if ( typedef_is_struct( t ) ) + { + newtype = get_basetype( typedef_members( t ) ) ; + } + else + { + newtype = typedef_base( t ) ; + } + + if ( type != TYPE_UNDEFINED && type != newtype ) + { + return TYPE_UNDEFINED ; + } + + type = newtype ; + } + return type ; +} + +/* + * FUNCTION : compile_struct_data + * + * Compile the values of an struct initialization + * Does not suppor parenthized sections or the DUP operator + * + * PARAMS: + * n Current variable space + * data Current data segment + * size Size (total number of variables) of the array + * including all dimensions (1 for single struct) + * sub 1 if the struct we'are initializing is part of + * another one + * (the function will then ignore a trailing comma) + * + * RETURN VALUE: + * Number of structs initialized + */ + +int compile_struct_data( VARSPACE * n, segment * data, int size, int sub ) +{ + int elements = 0 ; + int position = 0 ; + expresion_result res ; + + for ( ;; ) + { + token_next() ; + + /* Allow parenthized struct initialization */ + if ( token.type == IDENTIFIER && token.code == identifier_leftp ) + { + if (( elements % n->count ) != 0 ) compile_error( MSG_NOT_ENOUGH_INIT ); + + /* Note - don't ignore a trailing comma! */ + elements = compile_struct_data( n, data, size, 0 ) ; + + if ( elements >= n->count ) size -= ( elements / n->count ); + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ) ; + + token_next() ; + if (( elements % n->count ) == 0 && size > 0 && token.type == IDENTIFIER && token.code == identifier_comma ) + continue; + + token_back() ; + return elements ; + } + + /* Allow empty initialization */ + if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) return 0 ; + + token_back() ; + + for ( ;; ) + { + TYPEDEF next_type = n->vars[position].type ; + + /* Next variable is a pointer */ + + if ( typedef_is_pointer( next_type ) ) + { + res = compile_expresion( 1, 0, 0, TYPE_DWORD ) ; + if ( !res.constant ) compile_error( MSG_INCORRECT_PTR_INIT ); + segment_add_as( data, 0, TYPE_POINTER ) ; + } + else if ( typedef_is_array( next_type ) ) /* Next variable is an array */ + { + int elements = typedef_tcount( next_type ) ; + BASETYPE base; + + /* Get the array base type */ + + while ( typedef_is_array( next_type ) ) next_type = typedef_reduce( next_type ); + + base = typedef_base( next_type ); + + /* Special case: array of structs */ + + if ( base == TYPE_STRUCT ) + { + compile_struct_data( next_type.varspace, data, elements, 1 ); + + } + else + { + token_next(); + + /* Special case: intializing char[] strings */ + + if ( token.type == STRING && next_type.chunk[1].type == TYPE_CHAR ) + { + const char * str = string_get( token.code ) ; + int subcount = 0 ; + + if (( int )strlen( str ) > typedef_count( next_type ) - 1 ) compile_error( MSG_TOO_MANY_INIT ) ; + + while ( *str ) + { + segment_add_as( data, *str++, TYPE_CHAR ) ; + subcount++ ; + } + + while ( subcount++ < typedef_count( next_type ) ) segment_add_as( data, 0, TYPE_CHAR ) ; + + } + else /* Initializing normal arrays */ + { + int has_parents = 1; + + if ( token.type != IDENTIFIER || token.code != identifier_leftp ) + { + has_parents = 0; + token_back(); + } + + compile_array_data( n, data, elements, elements, &base ) ; + + if ( has_parents ) + { + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ) ; + } + } + } + } + else if ( typedef_is_struct( next_type ) ) /* Next variable is another struct */ + { + compile_struct_data( next_type.varspace, data, 1, 1 ) ; + } + else /* Next variable is a single type */ + { + res = compile_expresion( 1, 0, 0, typedef_base( next_type ) ) ; + if ( !res.constant ) compile_error( MSG_CONSTANT_EXP ); + segment_add_as( data, typedef_base( next_type ) == TYPE_FLOAT ? *( int* )&res.fvalue : res.value, typedef_base( next_type ) ) ; + } + + position++ ; + elements++ ; + + if ( position == n->count && size < 2 && sub ) break ; + + /* A comma should be here */ + + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) + { + token_back(); + break ; + } + + if ( token.type == IDENTIFIER && token.code == identifier_rightp ) + { + token_back() ; + break ; + } + + if ( token.type != IDENTIFIER || token.code != identifier_comma ) compile_error( MSG_EXPECTED, "," ) ; + + /* Wrap around for the next struct */ + + if ( position == n->count ) + { + if ( size == 1 && !sub ) compile_error( MSG_TOO_MANY_INIT ) ; + size--; + position = 0; + } + } + break; + } + + return elements ; +} + +static void set_type( TYPEDEF * t, BASETYPE type ) +{ +/* + int n ; + + for ( n = 0 ; n < t->depth ; n++ ) + if ( t->chunk[n].type == TYPE_UNDEFINED ) + { + t->chunk[n].type = type ; + break ; + } + return ; +*/ + t->chunk[t->depth-1].type = type ; +} + +/* + * FUNCTION : compile_varspace + * + * Compile a variable space (a LOCAL, PRIVATE or GLOBAL section, or part of a STRUCT data) + * + * PARAMS : + * n Pointer to the VARSPACE object (already initialized) + * data Pointer to the data segment. All variables are added at end. + * additive 1 if the compiling is additive (the struct members have non-local offset; GLOBAL case) + * or not (STRUCT case) + * copies Number of data copies (if the STRUCT is part of an array) + * collision Check this varspace array for name collisions (NULL = end of array), + * if nonzero (2006/11/19 19:34 GMT-03:00, Splinter - jj_arg@yahoo.com) + * alignment Byte size for member alignment. Empty data will be added + * to the varspace if its size is not multiple of this value. + * + * In any case, nested varspaces (structs) will have an alignment of 0. + * + * RETURN VALUE : + * None + * + */ + +int compile_varspace( VARSPACE * n, segment * data, int additive, int copies, int padding, VARSPACE ** collision, int alignment, int duplicateignore ) +{ + int i, j, total_count, last_count = 0 ; + int base_offset = data->current ; + int total_length ; + int size, count ; + int code ; + expresion_result res ; + VARIABLE * var ; + int unsigned_prefix = 0; + int signed_prefix = 0; + + BASETYPE basetype = TYPE_UNDEFINED ; + TYPEDEF type, typeaux; + segment * segm = NULL ; + PROCDEF * proc = NULL; + + /* Backup vars */ + BASETYPE basetypeb = TYPE_UNDEFINED ; + TYPEDEF typeb; + segment * segmb = NULL ; + + /* Initialize some stuffs */ + + type = typedef_new( TYPE_UNDEFINED ) ; + typeb = typedef_new( TYPE_UNDEFINED ) ; + + for ( ;; ) + { + if ( n->reserved == n->count ) varspace_alloc( n, 16 ) ; + + if ( alignment && ( n->size % alignment ) > 0 ) + { + int extra = alignment - ( n->size % alignment ); + if ( n->reserved <= n->count + extra ) + { + varspace_alloc( n, extra + 16 ); + } + if ( data->reserved <= data->current + extra ) + { + segment_alloc( data, extra + 16 ); + } + n->size += extra; + data->current += extra; + } + + token_next() ; + + /* Se salta comas y puntos y coma */ + + if ( token.type == NOTOKEN ) break ; + + if ( token.type != IDENTIFIER ) compile_error( MSG_INCOMP_TYPE ) ; + + if ( token.code == identifier_comma ) + { + basetype = basetypeb ; + type = typeb ; + + segm = segmb ; + + continue ; + } + else if ( token.code == identifier_semicolon ) + { + basetype = TYPE_UNDEFINED ; + set_type( &type, TYPE_UNDEFINED ) ; + + basetypeb = basetype ; + typeb = type ; + + segm = NULL ; + proc = NULL ; + + continue ; + } + else if ( token.code == identifier_end ) + { + break ; + } + + /* "Unsigned" */ + + if ( token.code == identifier_unsigned ) + { + unsigned_prefix = 1; + token_next(); + } + else if ( token.code == identifier_signed ) + { + signed_prefix = 1; + token_next(); + } + + /* Tipos de datos básicos */ + + if ( token.code == identifier_dword ) + { + basetype = signed_prefix ? TYPE_INT : TYPE_DWORD ; + signed_prefix = unsigned_prefix = 0; + token_next() ; + } + else if ( token.code == identifier_word ) + { + basetype = signed_prefix ? TYPE_SHORT : TYPE_WORD ; + signed_prefix = unsigned_prefix = 0; + token_next() ; + } + else if ( token.code == identifier_byte ) + { + basetype = signed_prefix ? TYPE_SBYTE : TYPE_BYTE ; + signed_prefix = unsigned_prefix = 0; + token_next() ; + } + else if ( token.code == identifier_int ) + { + basetype = unsigned_prefix ? TYPE_DWORD : TYPE_INT; + signed_prefix = unsigned_prefix = 0; + token_next() ; + } + else if ( token.code == identifier_short ) + { + basetype = unsigned_prefix ? TYPE_WORD : TYPE_SHORT; + signed_prefix = unsigned_prefix = 0; + token_next() ; + } + else if ( token.code == identifier_char ) + { + basetype = TYPE_CHAR ; + token_next() ; + } + else if ( token.code == identifier_float ) + { + basetype = TYPE_FLOAT ; + token_next() ; + } + else if ( token.code == identifier_string ) + { + basetype = TYPE_STRING ; + token_next() ; + } + else + { + if ( !proc && ( proc = procdef_search( token.code ) ) ) /* Variables tipo proceso, Splinter */ + { + basetype = TYPE_INT ; + token_next(); + } + else + { + if ( + token.type == IDENTIFIER && + token.code >= reserved_words && + !segment_by_name( token.code ) ) + { + int code = token.code; + token_next(); + if ( token.type == IDENTIFIER && token.code >= reserved_words ) + { + proc = procdef_new( procdef_getid(), code ); + basetype = TYPE_INT ; + } + else + { + token_back(); + } + } + } + } + + if ( signed_prefix || unsigned_prefix ) compile_error( MSG_INVALID_TYPE ); + if ( basetype != TYPE_STRUCT ) type = typedef_new( basetype ) ; + if ( basetype == TYPE_UNDEFINED ) type = typedef_new( TYPE_INT ) ; + + /* Tipos de datos definidos por el usuario */ + if ( basetype != TYPE_STRUCT && ( segm = segment_by_name( token.code ) ) ) + { + basetype = TYPE_STRUCT ; + type = * typedef_by_name( token.code ) ; + token_next() ; + } + + if ( token.type == IDENTIFIER && token.code == identifier_struct ) + { + type.chunk[0].type = TYPE_STRUCT ; + type.chunk[0].count = 1 ; + type.depth = 1 ; + token_next() ; + segm = 0 ; + } + + basetypeb = basetype ; + typeb = type ; + segmb = segm ; + + /* Tipos de datos derivados */ + while ( token.type == IDENTIFIER && ( token.code == identifier_pointer || token.code == identifier_multiply ) ) + { + type = typedef_enlarge( type ) ; + type.chunk[0].type = TYPE_POINTER ; + basetype = TYPE_POINTER ; + segm = NULL ; + token_next() ; + } + + /* Nombre del dato */ + + if ( token.type != IDENTIFIER ) compile_error( MSG_IDENTIFIER_EXP ) ; + + if ( token.code < reserved_words ) + { + if ( proc ) compile_error( MSG_VARIABLE_ERROR ); + token_back() ; + break ; + } + + if (( var = varspace_search( n, token.code ) ) ) + { + if ( duplicateignore ) + { + int skip_all_until_semicolon = 0; + int skip_equal = 0; + + if ( debug ) compile_warning( 0, MSG_VARIABLE_REDECLARE ) ; + + for ( ;; ) + { + token_next() ; + + /* Se salta todo hasta el puntos y coma o en el end o la coma si no hay asignacion */ + + if ( token.type == NOTOKEN ) break ; + + if ( token.type == IDENTIFIER ) + { + if ( !skip_equal && token.code == identifier_equal ) + { + skip_all_until_semicolon = 1; + continue; + } + + if ( !skip_all_until_semicolon && token.code == identifier_comma ) break; + if ( token.code == identifier_semicolon ) break ; + if ( token.code == identifier_end ) break ; + } + } + token_back(); + continue; + } + else + compile_error( MSG_VARIABLE_REDECLARE ) ; + } + + /* (2006/11/19 19:34 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + if ( collision ) + for ( i = 0; collision[i];i++ ) + if ( varspace_search( collision[i], token.code ) ) compile_error( MSG_VARIABLE_REDECLARE ) ; + /* (2006/11/19 19:34 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + + if ( constants_search( token.code ) ) compile_error( MSG_CONSTANT_REDECLARED_AS_VARIABLE ) ; + + code = token.code ; + n->vars[n->count].code = token.code ; + n->vars[n->count].offset = data->current; + + /* Non-additive STRUCT; use zero-based member offsets */ + + if ( !additive ) n->vars[n->count].offset -= base_offset; + + token_next() ; + + /* Compila una estructura no predefinida */ + + if ( !segm && typedef_is_struct( type ) ) + { + VARSPACE * members ; + + type.chunk[0].count = 1 ; + count = 1 ; + while ( token.type == IDENTIFIER && token.code == identifier_leftb ) + { + res = compile_expresion( 1, 0, 0, TYPE_INT ) ; + if ( !typedef_is_integer( res.type ) ) compile_error( MSG_INTEGER_REQUIRED ) ; + count *= res.value + 1 ; + type = typedef_enlarge( type ) ; + type.chunk[0].type = TYPE_ARRAY ; + type.chunk[0].count = res.value + 1 ; + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ; + token_next() ; + } + token_back() ; + + /* Da la vuelta a los índices [10][5] -> [5][10] */ + + for ( i = 0 ; i < type.depth ; i++ ) if ( type.chunk[i].type != TYPE_ARRAY ) break ; + i--; + for ( j = 0 ; j <= i ; j++ ) typeaux.chunk[ j ] = type.chunk[ i - j ]; + for ( j = 0 ; j <= i ; j++ ) type.chunk[ j ] = typeaux.chunk[ j ]; + + members = ( VARSPACE * )calloc( 1, sizeof( VARSPACE ) ) ; + if ( !members ) + { + fprintf( stdout, "compile_varspace: out of memory\n" ) ; + exit( 1 ) ; + } + varspace_init( members ) ; + + size = compile_varspace( members, data, 0, count, 0, NULL, 0, duplicateignore ) ; + + type.varspace = members ; + + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_equal ) + { + i = data->current ; + data->current = n->vars[n->count].offset ; + compile_struct_data( members, data, count, 0 ); + data->current = i ; + } + else + { + token_back() ; + } + + for ( i = 0 ; i < members->stringvar_count ; i++ ) + varspace_varstring( n, members->stringvars[i] ) ; + + n->size += typedef_size( type ) ; + n->vars[n->count].type = type ; + n->count++ ; + + continue ; /* No ; */ + + } + else if ( token.type == IDENTIFIER && token.code == identifier_leftb ) /* Compila un array */ + { + total_count = 1 ; + + while ( token.type == IDENTIFIER && token.code == identifier_leftb ) + { + if ( type.depth == MAX_TYPECHUNKS ) compile_error( MSG_TOO_MANY_AL ) ; + + type = typedef_enlarge( type ) ; + type.chunk[0].type = TYPE_ARRAY ; + + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_rightb ) + { + type.chunk[0].count = 0 ; + if ( total_count != 1 ) compile_error( MSG_VTA ) ; + total_count = 0 ; + last_count = 0 ; + } + else + { + token_back() ; + res = compile_expresion( 1, 0, 0, TYPE_DWORD ) ; + if ( !total_count ) compile_error( MSG_VTA ) ; + total_count *= res.value + 1 ; + last_count = res.value + 1 ; + type.chunk[0].count = res.value + 1 ; + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ; + } + + token_next() ; + } + + /* Da la vuelta a los índices [10][5] -> [5][10] */ + + for ( i = 0 ; i < type.depth ; i++ ) if ( type.chunk[i].type != TYPE_ARRAY ) break ; + i--; + for ( j = 0 ; j <= i ; j++ ) typeaux.chunk[ j ] = type.chunk[ i - j ]; + for ( j = 0 ; j <= i ; j++ ) type.chunk[ j ] = typeaux.chunk[ j ]; + + if ( segm && token.type == IDENTIFIER && token.code == identifier_equal ) + { + for ( i = 0 ; i < total_count ; i++ ) segment_add_from( data, segm ) ; + i = data->current ; + data->current = n->vars[n->count].offset ; + compile_struct_data( type.varspace, data, typedef_count( type ), 0 ); + + if ( !type.chunk[0].count ) + type.chunk[0].count = ( data->current - i ) / typedef_size( typeb ); + else + data->current = i; /* Solo si ya habia sido alocada */ + + } + else if ( token.type == IDENTIFIER && token.code == identifier_equal ) + { + /* if (basetype == TYPE_UNDEFINED) basetype = TYPE_INT; */ + i = compile_array_data( n, data, total_count, last_count, &basetype ) ; + assert( basetype != TYPE_UNDEFINED ) ; + set_type( &type, basetype ) ; + if ( total_count == 0 ) + { + type.chunk[0].count = i; + } + else if ( i < total_count ) + { + for ( ; i < total_count; i++ ) + { + if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ; + segment_add_as( data, 0, basetype ) ; + } + } + } + else if ( segm ) + { + int string_offset = 0, j; + + if ( total_count == 0 ) compile_error( MSG_EXPECTED, "=" ) ; + + for ( i = 0; i < total_count; i++ ) + { + segment_add_from( data, segm ) ; + for ( j = 0; j < type.varspace->stringvar_count; j++ ) + varspace_varstring( n, type.varspace->stringvars[j] + string_offset ); + string_offset += type.varspace->size; + } + token_back() ; + } + else + { + if ( basetype == TYPE_UNDEFINED ) + { + basetype = TYPE_INT; + set_type( &type, basetype ) ; + } + + if ( type.chunk[0].count == 0 ) compile_error( MSG_EXPECTED, "=" ) ; + + for ( i = 0; i < total_count; i++ ) + { + if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ; + segment_add_as( data, 0, basetype ) ; + } + token_back() ; + } + } + else if ( segm && token.type == IDENTIFIER && token.code == identifier_equal ) /* Compila una asignación de valores por defecto */ + { + segment_add_from( data, segm ) ; + i = data->current ; + data->current = n->vars[n->count].offset ; + if ( !additive ) data->current += base_offset; + compile_struct_data( type.varspace, data, 1, 0 ); + data->current = i ; + + } + else if ( token.type == IDENTIFIER && token.code == identifier_equal ) + { + res = compile_expresion( 1, 0, 0, basetype ) ; + + if ( basetype == TYPE_UNDEFINED ) + { + basetype = typedef_base( res.type ) ; + if ( basetype == TYPE_UNDEFINED ) compile_error( MSG_INCOMP_TYPE ) ; + set_type( &type, basetype ) ; + } + + if ( basetype == TYPE_FLOAT ) + { + segment_add_as( data, *( int * )&res.fvalue, basetype ) ; + } + else + { + if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ; + segment_add_as( data, res.value, basetype ) ; + } + + } + else if ( !segm ) /* Asigna valores por defecto (0) */ + { + if ( basetype == TYPE_UNDEFINED ) + { + basetype = TYPE_INT; + set_type( &type, basetype ) ; + } + + if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ; + segment_add_as( data, 0, basetype ) ; + token_back() ; + + } + else + { + if ( typedef_is_struct( type ) ) + for ( i = 0 ; i < type.varspace->stringvar_count ; i++ ) + varspace_varstring( n, type.varspace->stringvars[i] + n->size ); + segment_add_from( data, segm ) ; + token_back() ; + } + + n->size += typedef_size( type ) ; + n->vars[n->count].type = type ; + + /* Variables tipo proceso, asigno varspace al tipo. Splinter */ + if ( proc ) n->vars[n->count].type.varspace = proc->pubvars; + + n->count++ ; + + token_next() ; + + if ( token.type == IDENTIFIER && token.code == identifier_comma ) + { + token_back() ; + continue ; + } + + if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) + { + token_back() ; + continue ; + } + + compile_error( MSG_EXPECTED, ";" ) ; + token_back() ; + break ; + } + + if ( padding && ( data->current % padding ) > 0 ) + { + padding -= data->current % padding; + data->current += padding; + n->size += padding; + + if ( data->reserved <= data->current ) + segment_alloc( data, data->reserved - data->current + 32 ); + } + + n->last_offset = data->current ; + total_length = data->current - base_offset ; + + /* n->size *= copies ; */ + while ( copies-- > 1 ) + { + int i ; + + for ( i = 0 ; i < n->stringvar_count ; i++ ) + { + if ( n->stringvars[i] >= base_offset && n->stringvars[i] < base_offset + total_length ) + { + varspace_varstring( n, n->stringvars[i] - base_offset + data->current ) ; + } + } + + segment_copy( data, base_offset, total_length ) ; + base_offset += total_length ; + } + + return total_length ; +} diff --git a/core/bgdc/src/c_debug.c b/core/bgdc/src/c_debug.c new file mode 100644 index 0000000..75e3c32 --- /dev/null +++ b/core/bgdc/src/c_debug.c @@ -0,0 +1,84 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#ifdef TARGET_BEOS +#include <posix/assert.h> +#else +#include <assert.h> +#endif + +#include "bgdc.h" + +/* ---------------------------------------------------------------------- */ +/* Este módulo contiene funciones que muestran el equivalente en texto de */ +/* una instrucción o mnemónico, o de un bloque de código completo */ +/* ---------------------------------------------------------------------- */ + +void codeblock_dump (CODEBLOCK * c) +{ + int i, n, showdir ; + for (i = 0 ; i < c->current ; i += MN_PARAMS(c->data[i])+1) + { + showdir = 0 ; + for (n = 0 ; n < c->label_count ; n++) + { + if (c->labels[n] == i) + { + if (!showdir) printf ("\n") ; + printf ("Label %d:\n", n) ; + showdir = 1 ; + } + } + for (n = 1 ; n < c->loop_count ; n++) + { + if (c->loops[n*2] == i) + { + if (!showdir) printf ("\n") ; + printf("Start %d:\n", n) ; + showdir = 1 ; + } + if (c->loops[n*2+1] == i) + { + if (!showdir) printf ("\n") ; + printf("End %d:\n", n) ; + showdir = 1 ; + } + } + if (showdir) printf ("\n%d:\n", i) ; + + printf ("\t") ; + + mnemonic_dump (c->data[i], c->data[i+1] ); + + } + printf ("%d:\n", i) ; +} + +/* ---------------------------------------------------------------------- */ diff --git a/core/bgdc/src/c_main.c b/core/bgdc/src/c_main.c new file mode 100644 index 0000000..24e7c16 --- /dev/null +++ b/core/bgdc/src/c_main.c @@ -0,0 +1,1285 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <loadlib.h> /* Must be first include */ + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <stdlib.h> +#include <limits.h> + +#include "bgdc.h" + +#include <bgddl.h> + +/* ---------------------------------------------------------------------- */ + +extern void token_dump() ; + +static char * import_filename = NULL; +static int import_line = 0; + +int imports_aux[512] ; /* Modules */ +int nimports_aux = 0 ; +int imports[512] ; /* Modules */ +int nimports = 0 ; + +/* ---------------------------------------------------------------------- */ +/* Módulo principal del compilador. Contiene código que inicializa los */ +/* identificadores conocidos, así como las funciones de compilado de */ +/* nivel más alto */ +/* ---------------------------------------------------------------------- */ + +/* Tipos */ +int identifier_dword ; +int identifier_word ; +int identifier_byte ; +int identifier_int ; +int identifier_short ; +int identifier_char ; +int identifier_unsigned ; +int identifier_signed ; +int identifier_string ; +int identifier_float ; +int identifier_struct ; +int identifier_type ; + +int identifier_declare ; + +int identifier_program ; +int identifier_debug ; +int identifier_begin ; +int identifier_end ; +int identifier_global ; +int identifier_local ; +int identifier_public ; +int identifier_private ; +int identifier_const ; +int identifier_dup ; +int identifier_from ; +int identifier_step ; +int identifier_to ; +int identifier_if ; +int identifier_else ; +int identifier_elseif ; +int identifier_for ; +int identifier_while ; +int identifier_frame ; +int identifier_clone ; + +int identifier_yield ; + +int identifier_onexit ; +int identifier_onerror ; + +int identifier_on ; +int identifier_exit ; +int identifier_error ; +int identifier_resume ; +int identifier_stm_next ; + +int identifier_jmp ; +int identifier_call ; + +int identifier_switch ; +int identifier_case ; +int identifier_default ; +int identifier_repeat ; +int identifier_until ; +int identifier_loop ; +int identifier_break ; +int identifier_continue ; +int identifier_return ; +int identifier_process ; +int identifier_function ; +int identifier_bandoffset ; +int identifier_offset ; +int identifier_sizeof ; +int identifier_pointer ; + +int identifier_and ; +int identifier_or ; +int identifier_xor ; +int identifier_not ; + +int identifier_band ; +int identifier_bor ; +int identifier_bxor ; +int identifier_bnot ; + +int identifier_plus ; +int identifier_minus ; +int identifier_plusplus ; +int identifier_minusminus ; +int identifier_equal ; +int identifier_multiply ; +int identifier_mod ; +int identifier_divide ; +int identifier_semicolon ; +int identifier_colon ; +int identifier_comma ; +int identifier_ror ; +int identifier_rol ; +int identifier_rightp ; +int identifier_leftp ; +int identifier_rightb ; +int identifier_leftb ; +int identifier_point ; +int identifier_twopoints ; + +int identifier_eq ; +int identifier_ne ; +int identifier_gte ; +int identifier_lte ; +int identifier_lt ; +int identifier_gt ; +int identifier_question ; + +int identifier_plusequal ; +int identifier_minusequal ; +int identifier_multequal ; +int identifier_divequal ; +int identifier_modequal ; +int identifier_orequal ; +int identifier_xorequal ; +int identifier_andequal ; +int identifier_rorequal ; +int identifier_rolequal ; +int identifier_mouse ; +int identifier_include ; + +int identifier_import ; +int reserved_words ; +int debug = 0 ; + +/* ---------------------------------------------------------------------- */ + +void compile_init() +{ + /* Initialize reserved words */ + + identifier_dword = identifier_add( "DWORD" ) ; + identifier_word = identifier_add( "WORD" ) ; + identifier_byte = identifier_add( "BYTE" ) ; + identifier_int = identifier_add( "INT" ) ; + identifier_short = identifier_add( "SHORT" ) ; + identifier_char = identifier_add( "CHAR" ) ; + identifier_unsigned = identifier_add( "UNSIGNED" ) ; + identifier_signed = identifier_add( "SIGNED" ) ; + identifier_float = identifier_add( "FLOAT" ) ; + identifier_string = identifier_add( "STRING" ) ; + identifier_struct = identifier_add( "STRUCT" ) ; + + identifier_declare = identifier_add( "DECLARE" ) ; + + identifier_include = identifier_add( "INCLUDE" ) ; + + identifier_program = identifier_add( "PROGRAM" ) ; + identifier_debug = identifier_add( "DEBUG" ) ; + identifier_const = identifier_add( "CONST" ) ; + identifier_begin = identifier_add( "BEGIN" ) ; + identifier_end = identifier_add( "END" ) ; + identifier_process = identifier_add( "PROCESS" ) ; + identifier_function = identifier_add( "FUNCTION" ) ; + identifier_global = identifier_add( "GLOBAL" ) ; + identifier_local = identifier_add( "LOCAL" ) ; + identifier_public = identifier_add( "PUBLIC" ) ; + identifier_private = identifier_add( "PRIVATE" ) ; + identifier_dup = identifier_add( "DUP" ) ; + identifier_from = identifier_add( "FROM" ) ; + identifier_to = identifier_add( "TO" ) ; + identifier_step = identifier_add( "STEP" ) ; + identifier_for = identifier_add( "FOR" ) ; + identifier_while = identifier_add( "WHILE" ) ; + identifier_repeat = identifier_add( "REPEAT" ) ; + identifier_until = identifier_add( "UNTIL" ) ; + identifier_switch = identifier_add( "SWITCH" ) ; + identifier_case = identifier_add( "CASE" ) ; + identifier_default = identifier_add( "DEFAULT" ) ; + identifier_loop = identifier_add( "LOOP" ) ; + identifier_break = identifier_add( "BREAK" ) ; + identifier_continue = identifier_add( "CONTINUE" ) ; + identifier_return = identifier_add( "RETURN" ) ; + identifier_if = identifier_add( "IF" ) ; + identifier_else = identifier_add( "ELSE" ) ; + identifier_elseif = identifier_add( "ELSEIF" ) ; + identifier_frame = identifier_add( "FRAME" ) ; + identifier_clone = identifier_add( "CLONE" ) ; + + identifier_yield = identifier_add( "YIELD" ) ; + + identifier_onexit = identifier_add( "ONEXIT" ) ; + identifier_onerror = identifier_add( "ONERROR" ) ; + + identifier_on = identifier_add( "ON" ) ; + identifier_exit = identifier_add( "EXIT" ) ; + identifier_error = identifier_add( "ERROR" ) ; + identifier_resume = identifier_add( "RESUME" ) ; + identifier_stm_next = identifier_add( "NEXT" ) ; + + identifier_jmp = identifier_add( "JMP" ) ; + identifier_add_as( "GOTO", identifier_jmp ) ; + + identifier_call = identifier_add( "CALL" ) ; + + identifier_and = identifier_add( "AND" ); + identifier_or = identifier_add( "OR" ); + identifier_xor = identifier_add( "XOR" ); + identifier_not = identifier_add( "NOT" ); + + identifier_band = identifier_add( "BAND" ); + identifier_bor = identifier_add( "BOR" ); + identifier_bxor = identifier_add( "BXOR" ); + identifier_bnot = identifier_add( "BNOT" ); + + identifier_sizeof = identifier_add( "SIZEOF" ); + identifier_offset = identifier_add( "OFFSET" ); + identifier_pointer = identifier_add( "POINTER" ); + identifier_type = identifier_add( "TYPE" ); + + identifier_bandoffset = identifier_add( "&" ); + + identifier_add_as( "!", identifier_not ) ; + identifier_add_as( "&&", identifier_and ) ; + identifier_add_as( "||", identifier_or ) ; + identifier_add_as( "^^", identifier_xor ) ; + + identifier_add_as( "~", identifier_bnot ) ; + identifier_add_as( "|", identifier_bor ) ; + identifier_add_as( "^", identifier_bxor ) ; + + identifier_plus = identifier_add( "+" ) ; + identifier_minus = identifier_add( "-" ) ; + identifier_plusplus = identifier_add( "++" ) ; + identifier_minusminus = identifier_add( "--" ) ; + identifier_multiply = identifier_add( "*" ) ; + identifier_mod = identifier_add( "%" ) ; + identifier_divide = identifier_add( "/" ) ; + identifier_equal = identifier_add( "=" ) ; + identifier_semicolon = identifier_add( ";" ) ; + identifier_comma = identifier_add( "," ) ; + identifier_ror = identifier_add( ">>" ) ; + identifier_rol = identifier_add( "<<" ) ; + identifier_rightp = identifier_add( ")" ) ; + identifier_leftp = identifier_add( "(" ) ; + identifier_rightb = identifier_add( "]" ) ; + identifier_leftb = identifier_add( "[" ) ; + identifier_point = identifier_add( "." ) ; + identifier_twopoints = identifier_add( ".." ) ; + identifier_question = identifier_add( "?" ) ; + + identifier_add_as( "MOD", identifier_mod ) ; + identifier_add_as( "ELIF", identifier_elseif ); + identifier_add_as( "ELSIF", identifier_elseif ); + + + identifier_colon = identifier_add( ":" ) ; + + identifier_eq = identifier_add( "==" ) ; + identifier_ne = identifier_add( "!=" ) ; + identifier_gt = identifier_add( ">" ) ; + identifier_lt = identifier_add( "<" ) ; + identifier_gte = identifier_add( ">=" ) ; + identifier_lte = identifier_add( "<=" ) ; + + identifier_add_as( "<>", identifier_ne ) ; + identifier_add_as( "=>", identifier_gte ) ; + identifier_add_as( "=<", identifier_lte ) ; + + identifier_plusequal = identifier_add( "+=" ) ; + identifier_andequal = identifier_add( "&=" ) ; + identifier_xorequal = identifier_add( "^=" ) ; + identifier_orequal = identifier_add( "|=" ) ; + identifier_divequal = identifier_add( "/=" ) ; + identifier_modequal = identifier_add( "%=" ) ; + identifier_multequal = identifier_add( "*=" ) ; + identifier_minusequal = identifier_add( "-=" ) ; + identifier_rorequal = identifier_add( ">>=" ) ; + identifier_rolequal = identifier_add( "<<=" ) ; + + identifier_import = identifier_add( "IMPORT" ) ; + + reserved_words = identifier_next_code() ; + + identifier_mouse = identifier_add( "MOUSE" ) ; /* Hack */ + + varspace_init( &global ) ; + varspace_init( &local ) ; + globaldata = segment_new() ; + localdata = segment_new() ; + +} + +/* ---------------------------------------------------------------------- */ + +void compile_error( const char *fmt, ... ) +{ + char text[4000] ; + char * fname = ( import_filename ) ? import_filename : (( current_file != -1 && files[current_file] && *files[current_file] ) ? files[current_file] : NULL ); + + va_list ap; + va_start( ap, fmt ); + vsprintf( text, fmt, ap ); + va_end( ap ); + + fprintf( stdout, MSG_COMPILE_ERROR, + ( fname && ( fname[0] != '/' && fname[0] != '\\' && fname[1] != ':' ) ) ? main_path : "", + fname ? fname : "N/A", + ( import_filename ) ? import_line : line_count, + text ) ; + fprintf( stdout, " ( token error: " ); + token_dump() ; + fprintf( stdout, " ).\n" ); + exit( 2 ) ; +} + +/* ---------------------------------------------------------------------- */ + +void compile_warning( int notoken, const char *fmt, ... ) +{ + char text[4000] ; + char * fname = ( import_filename ) ? import_filename : (( current_file != -1 && files[current_file] && *files[current_file] ) ? files[current_file] : NULL ); + + va_list ap; + va_start( ap, fmt ); + vsprintf( text, fmt, ap ); + va_end( ap ); + + fprintf( stdout, MSG_COMPILE_WARNING, + ( fname && ( fname[0] != '/' && fname[0] != '\\' && fname[1] != ':' ) ) ? main_path : "", + fname ? fname : "N/A", + ( import_filename ) ? import_line : line_count, + text ) ; + if ( !notoken ) + { + fprintf( stdout, " ( token warning: " ); + token_dump() ; + fprintf( stdout, " ).\n" ); + } else { + fprintf( stdout, ".\n" ); + } + +} + +/* ---------------------------------------------------------------------- */ + +static char * trim( char * ptr ) +{ + char * ostr = ptr; + char * bptr = ptr; + + while ( *ptr == ' ' || *ptr == '\n' || *ptr == '\r' || *ptr == '\t' ) ptr++; + + while ( *ptr ) *bptr++ = *ptr++; + + while ( bptr > ostr && ( bptr[-1] == ' ' || bptr[-1] == '\n' || bptr[-1] == '\r' || bptr[-1] == '\t' ) ) bptr--; + + *bptr = 0; + + return ( ostr ); +} + +/* ---------------------------------------------------------------------- */ + +static int import_exists( char * libname ) +{ + int n; + for ( n = 0; n < nimports_aux; n++ ) if ( !strcmp( libname, string_get( imports_aux[n] ) ) ) return n; + return -1; +} + +/* ---------------------------------------------------------------------- */ + +void compile_type() +{ + int code; + segment * s = segment_new() ; + VARSPACE * v = varspace_new() ; + TYPEDEF t = typedef_new( TYPE_STRUCT ); + + t.chunk[0].count = 1 ; + + token_next() ; + if (( code = token.code ) < reserved_words || token.type != IDENTIFIER ) compile_error( MSG_INVALID_TYPE ) ; + + t.varspace = v ; + typedef_name( t, code ) ; + segment_name( s, code ) ; + + /* (2006/11/19 19:34 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + compile_varspace( v, s, 0, 1, 0, NULL, 0, 0 ) ; + if ( token.code != identifier_end ) compile_error( MSG_NO_END ) ; +} + +/* ---------------------------------------------------------------------- */ + +static char * modules_exts[] = +{ + ".dll", + ".dylib", + ".so", + NULL +} ; + +static char * dlsearchpath[] = +{ + "modules", + "mod", + "mods", + "extensions", + "plugins", + "data", + NULL +}; + +static void import_module( const char * filename ) +{ + int libid ; + void * library = NULL; + + char ** globals_def = NULL; + char ** locals_def = NULL; + DLCONSTANT * constants_def = NULL; + DLSYSFUNCS * functions_exports = NULL; + char ** modules_dependency = NULL; + char ** types_def = NULL; + + char soname[ __MAX_PATH ], fullsoname[ __MAX_PATH ], **spath ; + char * ptr; + char ** pex; + +#if defined( WIN32 ) +#define DLLEXT ".dll" +#elif defined(TARGET_MAC) +#define DLLEXT ".dylib" +#else +#define DLLEXT ".so" +#endif + + strncpy( soname, filename, sizeof( soname ) ); + + for ( ptr = soname; *ptr; ptr++ ) + { + if ( *ptr == PATH_CHAR_SEP ) *ptr = PATH_CHAR_ISEP ; + else *ptr = TOLOWER( *ptr ); + } + + pex = modules_exts; + while ( pex && * pex ) + { + int nlen = strlen( soname ); + int elen = strlen( *pex ); + if ( nlen > elen && strcmp( &soname[nlen - elen], *pex ) == 0 ) + { + soname[nlen - elen] = '\0' ; + pex = modules_exts; + } + else + { + pex++; + } + } + + if ( import_exists(( char * )soname ) != -1 ) return; + + filename = soname; + libid = string_new( soname ); + + imports_aux[nimports_aux++] = libid; + + strcat( soname, DLLEXT ); + + fullsoname[0] = '\0'; + + spath = dlsearchpath; + while( !library && spath && *spath ) + { + sprintf( fullsoname, "%s%s/%s", appexepath, *spath, filename ); + library = dlibopen( fullsoname ) ; + spath++; + } + + if ( !library ) library = dlibopen( filename ) ; + + if ( !library ) compile_error( MSG_LIBRARY_NOT_FOUND, filename ) ; + + modules_dependency = ( char ** ) _dlibaddr( library, "modules_dependency" ) ; + + if ( modules_dependency ) + { + char * old_import_filename = import_filename; + while ( *modules_dependency ) + { + if ( import_exists( *modules_dependency ) == -1 ) + { + import_filename = *modules_dependency ; + import_module( *modules_dependency ); + import_filename = NULL ; + } + modules_dependency++; + } + import_filename = old_import_filename; + } + + imports[nimports++] = libid; + + constants_def = ( DLCONSTANT * ) _dlibaddr( library, "constants_def" ) ; + if ( constants_def ) + { + while ( constants_def->name ) + { + int code = identifier_search_or_add( constants_def->name ) ; + constants_add( code, typedef_new( constants_def->type ), constants_def->code ) ; + constants_def++ ; + } + } + + types_def = ( char ** ) _dlibaddr( library, "types_def" ) ; + if ( types_def && *types_def ) + { + token_init( *types_def, -1 ) ; + token_next(); + while ( token.type == IDENTIFIER && token.code == identifier_type ) + { + compile_type() ; + token_next(); + } + } + + globals_def = ( char ** ) _dlibaddr( library, "globals_def" ) ; + if ( globals_def && *globals_def ) + { + VARSPACE * v[] = {&local, NULL}; + token_init( *globals_def, -1 ) ; + compile_varspace( &global, globaldata, 1, 1, 0, v, DEFAULT_ALIGNMENT, 1 ) ; + } + + locals_def = ( char ** ) _dlibaddr( library, "locals_def" ) ; + if ( locals_def && *locals_def ) + { + VARSPACE * v[] = {&global, NULL}; + + token_init( *locals_def, -1 ) ; + compile_varspace( &local, localdata, 1, 1, 0, v, DEFAULT_ALIGNMENT, 1 ) ; + } + + functions_exports = ( DLSYSFUNCS * ) _dlibaddr( library, "functions_exports" ) ; + if ( functions_exports ) + { + while ( functions_exports->name ) + { + sysproc_add( functions_exports->name, functions_exports->paramtypes, functions_exports->type, functions_exports->func ); + functions_exports++; + } + } +} + +/* ---------------------------------------------------------------------- */ + +void import_files( char * filename ) +{ + file * fp = file_open( filename, "rb0" ); + char libname[__MAX_PATH]; + + if ( !fp ) return; + + import_line = 0; + + while ( !file_eof( fp ) ) + { + import_line++; + if ( !file_gets( fp, libname, sizeof( libname ) ) ) break; + trim( libname ); + if ( *libname == '\0' ) continue; + if ( import_exists( libname ) != -1 ) continue; + import_filename = filename ; + import_module( libname ); + import_filename = NULL ; + } + + file_close( fp ); +} + +/* ---------------------------------------------------------------------- */ + +void import_mod( char * libname ) +{ + import_line = 0; + if ( import_exists( libname ) != -1 ) return; + import_filename = libname ; + import_module( libname ); + import_filename = NULL ; +} + +/* ---------------------------------------------------------------------- */ + +void compile_import( void ) +{ + no_include_this_file = 1; + + token_next() ; + if ( token.type != STRING ) compile_error( MSG_STRING_EXP ) ; + + import_module( string_get( token.code ) ); +} + +/* ---------------------------------------------------------------------- */ + +void compile_constants() +{ + int code; + expresion_result res; + + for ( ;; ) + { + token_next() ; + if ( token.type == NOTOKEN ) break ; + + if ( token.type != IDENTIFIER ) compile_error( MSG_CONSTANT_NAME_EXP ) ; + + if ( token.code == identifier_semicolon ) continue ; + + if ( token.code == identifier_begin || + token.code == identifier_local || + token.code == identifier_public || + token.code == identifier_private || + token.code == identifier_global ) + { + token_back() ; + return ; + } + + if ( token.code == identifier_end ) return ; + + if ( token.code < reserved_words ) compile_error( MSG_INVALID_IDENTIFIER ); + + code = token.code ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_equal ) compile_error( MSG_EXPECTED, "=" ) ; + + res = compile_expresion( 1, 0, 0, 0 ) ; + if ( !typedef_is_float( res.type ) && !typedef_is_string( res.type ) && !typedef_is_integer( res.type ) ) compile_error( MSG_INVALID_TYPE ); + + constants_add( code, res.type, typedef_base( res.type ) == TYPE_FLOAT ? *( int * )&res.fvalue : res.value ) ; + + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) continue ; + + compile_error( MSG_EXPECTED, ";" ) ; + } +} + +/* ---------------------------------------------------------------------- */ + +void compile_process() +{ + PROCDEF * proc, * external_proc ; + VARIABLE * var ; + int is_declare = 0 ; + int is_function = 0 ; + int type_implicit = 1; + int code, tcode, params ; + BASETYPE type, typeb ; + TYPEDEF ctype, ctypeb ; + + int signed_prefix = 0; + int unsigned_prefix = 0; + + tcode = token.code ; + + if ( tcode == identifier_declare ) /* Es una declaracion? */ + { + is_declare = 1; + token_next() ; + tcode = token.code; + } + + /* Es funcion? */ + if ( tcode == identifier_function ) is_function = 1; + + if (( tcode == identifier_process || tcode == identifier_function ) ) /* Si proceso o funcion, obtengo el signo */ + { + token_next() ; + tcode = token.code; + } + + if ( token.code == identifier_signed ) /* signed */ + { + signed_prefix = 1; + token_next(); + tcode = token.code; + } + else if ( token.code == identifier_unsigned ) /* unsigned */ + { + unsigned_prefix = 1; + token_next(); + tcode = token.code; + } + + if ( segment_by_name( token.code ) ) /* Nombre del Segmento al que pertenece */ + { + tcode = identifier_pointer ; + token_next() ; + } + + if ( identifier_is_basic_type( token.code ) ) /* Salto identificador de tipo basico */ + { + tcode = token.code ; + token_next(); + } + + while ( token.code == identifier_pointer || token.code == identifier_multiply ) /* Salto el indentificador POINTER */ + { + tcode = token.code ; + token_next() ; + } + + /* Check if the process name is valid */ + + if ( token.type != IDENTIFIER || token.code < reserved_words ) compile_error( MSG_PROCNAME_EXP ) ; + + code = token.code ; + + /* Create the process if it is not defined already */ + proc = procdef_search( code ) ; + if ( !proc ) proc = procdef_new( procdef_getid(), code ) ; + else if ( proc->defined ) compile_error( MSG_PROC_ALREADY_DEFINED ); + else if ( is_declare && proc->declared ) compile_error( MSG_PROC_ALREADY_DECLARED ); + + /* is declaration? */ + if ( !is_declare ) proc->defined = 1 ; + + /* is a function? */ + if ( is_function ) + { + if ( is_declare && proc->declared && !( proc->flags & PROC_FUNCTION ) ) compile_error( MSG_PROTO_ERROR ) ; + proc->flags |= PROC_FUNCTION; + } + + /* Get function/process return type */ + + if ( tcode == identifier_float ) + { + if ( is_declare && proc->declared && proc->type != TYPE_FLOAT ) compile_error( MSG_PROTO_ERROR ) ; + proc->type = TYPE_FLOAT ; + } + + if ( tcode == identifier_string ) + { + if ( is_declare && proc->declared && proc->type != TYPE_STRING ) compile_error( MSG_PROTO_ERROR ) ; + proc->type = TYPE_STRING ; + } + + if ( tcode == identifier_word ) + { + if ( is_declare && proc->declared && proc->type != ( signed_prefix ? TYPE_SHORT : TYPE_WORD ) ) compile_error( MSG_PROTO_ERROR ) ; + proc->type = signed_prefix ? TYPE_SHORT : TYPE_WORD; + signed_prefix = unsigned_prefix = 0; + } + + if ( tcode == identifier_dword ) + { + if ( is_declare && proc->declared && proc->type != ( signed_prefix ? TYPE_INT : TYPE_DWORD ) ) compile_error( MSG_PROTO_ERROR ) ; + proc->type = signed_prefix ? TYPE_INT : TYPE_DWORD; + signed_prefix = unsigned_prefix = 0; + } + + if ( tcode == identifier_byte ) + { + if ( is_declare && proc->declared && proc->type != ( signed_prefix ? TYPE_SBYTE : TYPE_BYTE ) ) compile_error( MSG_PROTO_ERROR ) ; + proc->type = signed_prefix ? TYPE_SBYTE : TYPE_BYTE; + signed_prefix = unsigned_prefix = 0; + } + + if ( tcode == identifier_int ) + { + if ( is_declare && proc->declared && proc->type != ( unsigned_prefix ? TYPE_DWORD : TYPE_INT ) ) compile_error( MSG_PROTO_ERROR ) ; + proc->type = unsigned_prefix ? TYPE_DWORD : TYPE_INT; + signed_prefix = unsigned_prefix = 0; + } + + if ( tcode == identifier_short ) + { + if ( is_declare && proc->declared && proc->type != ( unsigned_prefix ? TYPE_WORD : TYPE_SHORT ) ) compile_error( MSG_PROTO_ERROR ) ; + proc->type = unsigned_prefix ? TYPE_WORD : TYPE_SHORT; + signed_prefix = unsigned_prefix = 0; + } + + if ( tcode == identifier_char ) + { + if ( is_declare && proc->declared && proc->type != TYPE_CHAR ) compile_error( MSG_PROTO_ERROR ) ; + proc->type = TYPE_CHAR; + } + + if ( tcode == identifier_pointer || tcode == identifier_multiply ) + { + if ( is_declare && proc->declared && proc->type != TYPE_POINTER ) compile_error( MSG_PROTO_ERROR ) ; + proc->type = TYPE_POINTER ; + } + + if ( signed_prefix || unsigned_prefix ) compile_error( MSG_INVALID_TYPE ); + + /* Parse the process parameters */ + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_leftp ) compile_error( MSG_EXPECTED, "(" ) ; + + token_next() ; + + params = 0 ; + type = TYPE_INT; + typeb = TYPE_INT; + type_implicit = 1; + ctype = typedef_new( type ) ; + ctypeb = ctype ; + signed_prefix = unsigned_prefix = 0; + external_proc = NULL; + + while ( token.type != IDENTIFIER || token.code != identifier_rightp ) + { + type = typeb; + ctype = ctypeb; + + /* Recogo signo del parametro */ + if ( token.type == IDENTIFIER && token.code == identifier_unsigned ) + { + unsigned_prefix = 1; + token_next(); + } + else if ( token.type == IDENTIFIER && token.code == identifier_signed ) + { + signed_prefix = 1; + token_next(); + } + + /* Recogo tipo del parametro */ + if ( token.type == IDENTIFIER && token.code == identifier_dword ) + { + type_implicit = 0; + type = signed_prefix ? TYPE_INT : TYPE_DWORD; + unsigned_prefix = signed_prefix = 0; + ctype = typedef_new( type ) ; + external_proc = NULL; + token_next() ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_int ) + { + type_implicit = 0; + type = unsigned_prefix ? TYPE_DWORD : TYPE_INT; + unsigned_prefix = signed_prefix = 0; + ctype = typedef_new( type ) ; + external_proc = NULL; + token_next() ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_word ) + { + type_implicit = 0; + type = signed_prefix ? TYPE_SHORT : TYPE_WORD ; + unsigned_prefix = signed_prefix = 0; + ctype = typedef_new( type ) ; + external_proc = NULL; + token_next() ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_short ) + { + type_implicit = 0; + type = unsigned_prefix ? TYPE_WORD : TYPE_SHORT; + unsigned_prefix = signed_prefix = 0; + ctype = typedef_new( type ) ; + external_proc = NULL; + token_next() ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_byte ) + { + type_implicit = 0; + type = signed_prefix ? TYPE_SBYTE : TYPE_BYTE ; + unsigned_prefix = signed_prefix = 0; + ctype = typedef_new( type ) ; + external_proc = NULL; + token_next() ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_char ) + { + type_implicit = 0; + type = TYPE_CHAR ; + ctype = typedef_new( type ) ; + external_proc = NULL; + token_next() ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_string ) + { + type_implicit = 0; + type = TYPE_STRING ; + ctype = typedef_new( type ) ; + external_proc = NULL; + token_next() ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_float ) + { + type_implicit = 0; + type = TYPE_FLOAT ; + ctype = typedef_new( type ) ; + external_proc = NULL; + token_next() ; + } + else if ( token.type == IDENTIFIER && segment_by_name( token.code ) ) + { + type_implicit = 0; + type = TYPE_STRUCT ; + ctype = *typedef_by_name( token.code ) ; + external_proc = NULL; + token_next() ; + } + else if ( !external_proc && ( external_proc = procdef_search( token.code ) ) ) /* Variables tipo proceso, Splinter */ + { + type_implicit = 0; + type = TYPE_INT ; + ctype = typedef_new( type ) ; + token_next(); + } + + if ( signed_prefix || unsigned_prefix ) + { + compile_error( MSG_INVALID_TYPE ); + signed_prefix = unsigned_prefix = 0; + } + + typeb = type; + ctypeb = ctype; + + while ( token.type == IDENTIFIER && ( token.code == identifier_pointer || token.code == identifier_multiply ) ) + { + type_implicit = 0; + type = TYPE_POINTER ; + ctype = typedef_pointer( ctype ) ; + token_next() ; + } + + if ( type == TYPE_STRUCT ) + { + type_implicit = 0; + type = TYPE_POINTER ; + ctype = typedef_pointer( ctype ) ; + } + + if ( token.type != IDENTIFIER || token.code < reserved_words ) compile_error( MSG_INVALID_PARAM ) ; + + if ( constants_search( token.code ) ) compile_error( MSG_CONSTANT_REDECLARED_AS_VARIABLE ) ; + + /* Check if the process was used before declared */ + if ( !proc->declared ) + { + var = varspace_search( &local, token.code ) ; + if ( var ) + { + /* El parámetro es en realidad un local */ + if ( type_implicit ) + { + type = typedef_base( var->type ); + ctype = var->type; + } + if ( typedef_base( var->type ) != type ) + { + if ( typedef_is_integer( var->type ) && typedef_is_integer( typedef_new( type ) ) ) + { + /* + A parameter was used before the process is declared. The + data type declared is different from the data type used, + but both are integers. The error is ignored, but no + conversion is done. This can lead to type conversion issues. + */ + } + else + compile_error( MSG_INVALID_PARAMT ) ; + } + codeblock_add( &proc->code, MN_LOCAL, var->offset ) ; + codeblock_add( &proc->code, MN_PRIVATE, proc->pridata->current ) ; + codeblock_add( &proc->code, MN_PTR, 0 ) ; + + if ( typedef_base( var->type ) == TYPE_STRING ) codeblock_add( &proc->code, MN_LET | MN_STRING, 0 ) ; + else codeblock_add( &proc->code, MN_LET, 0 ) ; + + codeblock_add( &proc->code, MN_POP, 0 ) ; + + if ( proc->privars->reserved == proc->privars->count ) varspace_alloc( proc->privars, 16 ) ; + + proc->privars->vars[proc->privars->count].type = typedef_new( TYPE_DWORD ); + proc->privars->vars[proc->privars->count].offset = proc->pridata->current ; + proc->privars->vars[proc->privars->count].code = -1 ; + + proc->privars->count++ ; + + segment_add_dword( proc->pridata, 0 ) ; + } + else + { + var = varspace_search( &global, token.code ); + if ( var ) + { + /* El parámetro es en realidad un global */ + if ( type_implicit ) + { + type = typedef_base( var->type ); + ctype = var->type; + } + + if ( typedef_base( var->type ) != type ) compile_error( MSG_INVALID_PARAMT ) ; + + codeblock_add( &proc->code, MN_GLOBAL, var->offset ) ; + codeblock_add( &proc->code, MN_PRIVATE, proc->pridata->current ) ; + codeblock_add( &proc->code, MN_PTR, 0 ) ; + + if ( typedef_base( var->type ) == TYPE_STRING ) codeblock_add( &proc->code, MN_LET | MN_STRING, 0 ) ; + else codeblock_add( &proc->code, MN_LET, 0 ) ; + + codeblock_add( &proc->code, MN_POP, 0 ) ; + + if ( proc->privars->reserved == proc->privars->count ) varspace_alloc( proc->privars, 16 ) ; + + proc->privars->vars[proc->privars->count].type = typedef_new( TYPE_DWORD ); + proc->privars->vars[proc->privars->count].offset = proc->pridata->current ; + proc->privars->vars[proc->privars->count].code = -1 ; + + proc->privars->count++ ; + + segment_add_dword( proc->pridata, 0 ) ; + } + else + { + /* Crear la variable privada */ + if ( proc->privars->reserved == proc->privars->count ) varspace_alloc( proc->privars, 16 ) ; + + if ( type == TYPE_STRING ) varspace_varstring( proc->privars, proc->pridata->current ) ; + + proc->privars->vars[proc->privars->count].type = ctype; + proc->privars->vars[proc->privars->count].offset = proc->pridata->current ; + proc->privars->vars[proc->privars->count].code = token.code ; + if ( external_proc ) proc->privars->vars[proc->privars->count].type.varspace = external_proc->pubvars; + + proc->privars->count++ ; + + segment_add_dword( proc->pridata, 0 ) ; + } + } + } + else + { + if ( proc->paramtype[params] != type || proc->paramname[params] != token.code ) compile_error( MSG_PROTO_ERROR ); + } + + if ( proc->params != -1 ) + { + /* El proceso fue usado previamente */ + + if ( proc->paramtype[params] == TYPE_UNDEFINED ) proc->paramtype[params] = type ; + else if (( proc->paramtype[params] == TYPE_DWORD || proc->paramtype[params] == TYPE_INT ) && + ( type == TYPE_DWORD || + type == TYPE_INT || + type == TYPE_BYTE || + type == TYPE_WORD || + type == TYPE_SHORT || + type == TYPE_SBYTE + ) ) proc->paramtype[params] = type ; + else if ( type == TYPE_DWORD && ( proc->paramtype[params] == TYPE_BYTE || proc->paramtype[params] == TYPE_WORD ) ) proc->paramtype[params] = type ; + else if ( proc->paramtype[params] != type ) compile_error( MSG_INVALID_PARAMT ) ; + } + else proc->paramtype[params] = type; + + proc->paramname[params] = token.code; + + params++ ; + + if ( params == MAX_PARAMS ) compile_error( MSG_TOO_MANY_PARAMS ) ; + + token_next() ; +// if ( token.type == IDENTIFIER && token.code == identifier_comma ) token_next() ; + if ( token.type == IDENTIFIER ) + { + if ( token.code != identifier_rightp && token.code != identifier_comma ) compile_error( MSG_EXPECTED, "," ); + if ( token.code == identifier_comma ) token_next() ; + } + + } /* END while (token.type != IDENTIFIER || token.code != identifier_rightp) */ + + if ( proc->params == -1 ) proc->params = params ; + else if ( proc->params != params ) compile_error( MSG_INCORRECT_PARAMC, identifier_name( code ), proc->params ) ; + + token_next() ; + + if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) token_next() ; + + /* Compile LOCAL/PRIVATE/PUBLIC sections on process/function. + NOTE: LOCAL section here considere as PUBLIC section */ + + while ( token.type == IDENTIFIER && ( + token.code == identifier_local || + token.code == identifier_public || + token.code == identifier_private ) ) + { + if (( !proc->declared ) && ( token.code == identifier_local || token.code == identifier_public ) ) + { + /* (2006/11/19 19:34 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + /* Ahora las declaraciones locales, son solo locales al proceso, pero visibles desde todo proceso */ + /* Se permite declarar local/publica una variable que haya sido declarada global, es una variable propia, no es la global */ + VARSPACE * v[] = {&local, proc->privars, NULL}; + compile_varspace( proc->pubvars, proc->pubdata, 1, 1, 0, v, DEFAULT_ALIGNMENT, 0 ) ; + } + else if ( token.code == identifier_private ) + { + /* (2006/11/19 19:34 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + /* Se permite declarar privada una variable que haya sido declarada global, es una variable propia, no es la global */ + VARSPACE * v[] = {&local, proc->pubvars, NULL}; + compile_varspace( proc->privars, proc->pridata, 1, 1, 0, v, DEFAULT_ALIGNMENT, 0 ) ; + } + + token_next() ; + } + + /* Gestiona procesos cuyos parámetros son variables locales */ + + if ( !is_declare ) + { + if ( token.type != IDENTIFIER || token.code != identifier_begin ) compile_error( MSG_NO_BEGIN ) ; + + compile_block( proc ) ; + + if ( token.type == IDENTIFIER && token.code == identifier_else ) compile_error( MSG_ELSE_WOUT_IF ) ; + } + + if ( token.type != IDENTIFIER || token.code != identifier_end ) compile_error( MSG_NO_END ) ; + + if ( !is_declare ) codeblock_add( &proc->code, MN_END, 0 ) ; + + proc->declared = 1 ; + +} + +/* ---------------------------------------------------------------------- */ + +void compile_program() +{ + /* Ahora lo del program es opcional :-P */ + + token_next() ; + if ( token.type == IDENTIFIER && token.code == identifier_program ) + { + token_next() ; + if ( token.type != IDENTIFIER || token.code < reserved_words ) compile_error( MSG_PROGRAM_NAME_EXP ) ; + + token_next() ; + if ( token.type != IDENTIFIER || token.code != identifier_semicolon ) compile_error( MSG_EXPECTED, ";" ) ; + } + else token_back() ; + + for ( ;; ) + { + token_next() ; + + while ( token.type == IDENTIFIER && token.code == identifier_semicolon ) token_next() ; + + if ( token.type == IDENTIFIER && token.code == identifier_import ) compile_import() ; + else if ( token.type == IDENTIFIER && token.code == identifier_const ) compile_constants() ; + else if ( token.type == IDENTIFIER && token.code == identifier_local ) + { + /* (2006/11/19 19:34 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + VARSPACE * v[] = { &global, NULL }; + compile_varspace( &local, localdata, 1, 1, 0, v, DEFAULT_ALIGNMENT, 0 ) ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_global ) + { + /* (2006/11/19 19:34 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + VARSPACE * v[] = { &local, NULL }; + compile_varspace( &global, globaldata, 1, 1, 0, v, DEFAULT_ALIGNMENT, 0 ) ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_private ) + { + /* (2006/11/19 19:34 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + VARSPACE * v[] = { &local, &global, NULL }; + compile_varspace( mainproc->privars, mainproc->pridata, 1, 1, 0, v, DEFAULT_ALIGNMENT, 0 ) ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_begin ) + { + if ( mainproc->defined ) + { + /* Hack para poder redefinir el proceso principal */ + mainproc->code.current -= 1 ; + } + + mainproc->defined = 1 ; + + compile_block( mainproc ) ; + + if ( token.type == IDENTIFIER && token.code == identifier_else ) compile_error( MSG_ELSE_WOUT_IF ) ; + + if ( token.type != IDENTIFIER || token.code != identifier_end ) compile_error( MSG_NO_END ) ; + + codeblock_add( &mainproc->code, MN_END, 0 ) ; + } + else if ( token.type == IDENTIFIER && token.code == identifier_type ) compile_type(); /* Tipo de dato definido por el usuario */ + else if ( token.type == IDENTIFIER && + ( + token.code == identifier_process || + token.code == identifier_function || + token.code == identifier_declare || + identifier_is_basic_type( token.type ) + ) ) compile_process() ; /* Definición de proceso */ + else if ( segment_by_name( token.code ) ) compile_process() ; + else break ; + } + + if ( global.count && debug ) + { + printf( "\n---- Global variables\n\n" ) ; + varspace_dump( &global, 0 ) ; + } + + if ( local.count && debug ) + { + printf( "\n---- Local variables\n\n" ) ; + varspace_dump( &local, 0 ) ; + /* segment_dump (localdata) ; */ + } + + if ( token.type != NOTOKEN ) compile_error( MSG_UNEXPECTED_TOKEN ) ; + + program_postprocess() ; + + if ( debug ) program_dumpprocesses() ; + + if ( !libmode && !mainproc->defined ) compile_error( MSG_NO_MAIN ) ; + + if ( debug ) + { + identifier_dump() ; + string_dump( NULL ) ; + } +} + +/* ---------------------------------------------------------------------- */ diff --git a/core/bgdc/src/codeblock.c b/core/bgdc/src/codeblock.c new file mode 100644 index 0000000..d99808f --- /dev/null +++ b/core/bgdc/src/codeblock.c @@ -0,0 +1,426 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "bgdc.h" + +/* + * FUNCTION : codeblock_postprocess + * + * After every codeblock has been completed (all the source code is + * compiled), update a codeblock with all things that couldn't be + * done before. This function does the following: + * + * - Updates all user procedure/function calls with the process + * number instead of its identifier id. Emits a compiler error + * if a process what user but never defined. + * + * - Updates all jumps so that they go to absolute opcode offsets + * inside the procedure, instead of refering to the label table + * + * This function will be called once for each existing code block. + * + * PARAMS : + * code Pointer to the codeblock to modify + * + * RETURN VALUE : + * None + */ + +void codeblock_postprocess (CODEBLOCK * code) +{ + int * ptr = code->data ; + PROCDEF * proc, * my = procdef_search_by_codeblock( code ) ; + + while (ptr < code->data + code->current) + { + if ( !libmode && ( *ptr == MN_CALL || *ptr == MN_PROC || *ptr == MN_TYPE )) + { + proc = procdef_search(ptr[1]) ; + if (!proc || !proc->defined) + { + token.type = IDENTIFIER ; + token.code = ptr[1] ; + /* Patch so linecount gets right */ + line_count = identifier_line(token.code) ; + current_file = identifier_file(token.code) ; + compile_error (MSG_UNDEFINED_PROC) ; + } + ptr[1] = proc->typeid ; + } + if ( !my->imported ) + { + if (*ptr == MN_JUMP || *ptr == MN_NCALL || + *ptr == MN_JFALSE || *ptr == MN_JTFALSE || + *ptr == MN_JTRUE || *ptr == MN_JTTRUE || + *ptr == MN_JNOCASE || *ptr == MN_CLONE || + *ptr == MN_EXITHNDLR || *ptr == MN_ERRHNDLR + ) + { + ptr++ ; + if (*ptr == -1) + { +// *ptr = 0; + ptr++; + continue; + } + if (code->labels[*ptr] == -1) + { + token.type = LABEL ; + token.code = code->labelsextra[*ptr].name ; + /* Patch so linecount gets right */ + line_count = code->labelsextra[*ptr].line ; + current_file = code->labelsextra[*ptr].file ; + compile_error ("Undefined label") ; + } + *ptr = code->labels[*ptr] ; + ptr++ ; + continue ; + } + if (*ptr == MN_REFALSE) + { + *ptr++ = MN_JFALSE ; + *ptr = code->loops[*ptr*2] ; + ptr++ ; + continue ; + } + if (*ptr == MN_REPEAT || *ptr == MN_RETRUE) + { + *ptr = (*ptr == MN_REPEAT ? MN_JUMP : MN_JTRUE) ; + ptr++ ; + *ptr = code->loops[*ptr*2] ; + ptr++ ; + continue ; + } + if (*ptr == MN_BREAK || *ptr == MN_BRFALSE) + { + *ptr = (*ptr == MN_BREAK ? MN_JUMP : MN_JFALSE) ; + ptr++ ; + *ptr = code->loops[*ptr*2 + 1] ; + ptr++ ; + continue ; + } + } + ptr+=MN_PARAMS(*ptr)+1 ; + } +} + +/* + * FUNCTION : codeblock_init + * + * Initializes a new code block and allocates initial data + * for all its internal structs. + * + * PARAMS : + * c Pointer to the codeblock to initialize + * + * RETURN VALUE : + * None + */ + +void codeblock_init(CODEBLOCK * c) +{ + c->data = (int *) calloc (64, sizeof(int)) ; + c->reserved = 64 ; + + c->loops = (int *) calloc (16, sizeof(int)) ; + c->loop_reserved = 8 ; + c->loop_count = 1 ; + c->loop_active = 0 ; + + c->labels = (int *) calloc (16, sizeof(int)) ; + c->labelsextra = (struct _labelsextra *) calloc (16, sizeof(struct _labelsextra)) ; + c->label_count = 0 ; + c->label_reserved = 16 ; + + c->current = 0 ; + c->previous = 0 ; + c->previous2 = 0 ; + + if (!c->data || !c->loops || !c->labels || !c->labelsextra) + { + fprintf (stdout, "CODEBLOCK: out of memory\n") ; + exit (1) ; + } +} + +/* + * FUNCTION : codeblock_alloc + * codeblock_loop_alloc + * codeblock_label_alloc + * + * Internal functions that alloc more memory for an + * internal data of the code block. Shouldn't be used + * outside this module. + * + * PARAMS : + * c Pointer to the codeblock + * count Additional size in number of members + * + * RETURN VALUE : + * None + */ + +void codeblock_alloc (CODEBLOCK * c, int count) +{ + c->reserved += count ; + c->data = (int *) realloc (c->data, c->reserved * sizeof(int)) ; + if (!c->data) + { + fprintf (stdout, "CODEBLOCK: out of memory\n") ; + exit (1) ; + } +} + +static void codeblock_loop_alloc (CODEBLOCK * c, int count) +{ + c->loop_reserved += count ; + c->loops = (int *) realloc (c->loops, c->loop_reserved * sizeof(int) * 2) ; + if (!c->loops) + { + fprintf (stdout, "CODEBLOCK: out of memory\n") ; + exit (1) ; + } +} + +static void codeblock_label_alloc (CODEBLOCK * c, int count) +{ + c->label_reserved += count ; + c->labels = (int *) realloc (c->labels, c->label_reserved * sizeof(int)) ; + c->labelsextra = (struct _labelsextra *) realloc (c->labelsextra, c->label_reserved * sizeof(struct _labelsextra)) ; + if (!c->labels) + { + fprintf (stdout, "CODEBLOCK: out of memory\n") ; + exit (1) ; + } +} + +int codeblock_loop_add (CODEBLOCK * c) +{ + return c->loop_count++ ; +} + +void codeblock_loop_start (CODEBLOCK * c, int loop, int begin) +{ + if (c->loop_reserved <= loop) + codeblock_loop_alloc (c, loop + 8 - c->loop_reserved) ; + if (c->loop_count <= loop) + c->loop_count = loop+1 ; + c->loops[loop*2] = begin ; +} + +void codeblock_loop_end (CODEBLOCK * c, int loop, int end) +{ + if (c->loop_reserved <= loop) + codeblock_loop_alloc (c, loop + 8 - c->loop_reserved) ; + if (c->loop_count <= loop) + c->loop_count = loop+1 ; + c->loops[loop*2+1] = end ; +} + +int codeblock_label_add (CODEBLOCK * c, int identifier) +{ + if (c->label_count == c->label_reserved) codeblock_label_alloc (c, c->label_count + 16) ; + c->labels[c->label_count] = -1; + c->labelsextra[c->label_count].name = identifier; + c->labelsextra[c->label_count].file = current_file; + c->labelsextra[c->label_count].line = line_count; + c->label_count++ ; + return c->label_count - 1 ; +} + +void codeblock_label_set (CODEBLOCK * c, int label, int offset) +{ + c->labels[label] = offset ; +} + +int codeblock_label_get (CODEBLOCK * c, int label) +{ + return c->labels[label] ; +} + +int codeblock_label_get_id_by_name (CODEBLOCK * c, int identifier) +{ + int i; + for (i = 0; i < c->label_count; i++) if (c->labelsextra[i].name != -1 && c->labelsextra[i].name == identifier) return i; + return -1; +} + +void codeblock_stepback (CODEBLOCK * c) +{ + int code = c->data[c->previous]; + int param = 0; + + if (MN_PARAMS(code) > 0) + param = c->data[c->previous+1]; + + if (c->previous != c->previous2) + { + c->current = c->previous; + c->previous = c->previous2; + codeblock_add (c, code, param); + } +} + +CODEBLOCK_POS codeblock_pos(CODEBLOCK * c) +{ + CODEBLOCK_POS p; + + p.current = c->current; + p.previous = c->previous; + p.previous2 = c->previous2; + return p; +} + +void codeblock_setpos(CODEBLOCK * c, CODEBLOCK_POS p) +{ + c->current = p.current; + c->previous = p.previous; + c->previous2 = p.previous2; +} + +void codeblock_add_block (CODEBLOCK * c, CODEBLOCK_POS from, CODEBLOCK_POS to) +{ + if (c->current+(to.current - from.current)+2 >= c->reserved) + codeblock_alloc (c, (to.current - from.current + 34) & 0x1F) ; + + memcpy (c->data + c->current, c->data + from.current, 4*(to.current - from.current)); + c->current += to.current - from.current; + c->previous = c->current - (to.current - to.previous); + if (to.current - from.current > 2) + c->previous2 = c->current - (to.current - to.previous2); + else + c->previous2 = c->previous; +} + +void codeblock_add (CODEBLOCK * c, int code, int param) +{ + if (!c) return ; + + if (MN_PARAMS(code) == 0 && param) + fprintf (stdout, "WARNING: mnemonic 0x%02X don't get params\n", code) ; + + if (c->current > 0) + { + if (code == MN_ARRAY && c->data[c->previous] == MN_PUSH) + { + c->data[c->previous] = MN_INDEX ; + c->data[c->previous+1] *= param ; + codeblock_stepback(c); + return ; + } + else if (code == MN_ADD && c->data[c->previous] == MN_PUSH) + { + c->data[c->previous] = MN_INDEX ; + codeblock_stepback(c); + return ; + } + else if (code == MN_SUB && c->data[c->previous] == MN_PUSH) + { + c->data[c->previous] = MN_INDEX ; + c->data[c->previous+1] = -c->data[c->previous+1] ; + codeblock_stepback(c); + return ; + } + else if ((code & MN_MASK) == MN_INDEX) + { + if (c->data[c->previous] == MN_INDEX) + { + c->data[c->previous+1] += param ; + return ; + } + if ((c->data[c->previous] & MN_MASK) == MN_GLOBAL + || (c->data[c->previous] & MN_MASK) == MN_LOCAL + || (c->data[c->previous] & MN_MASK) == MN_PUBLIC + || (c->data[c->previous] & MN_MASK) == MN_REMOTE_PUBLIC + || (c->data[c->previous] & MN_MASK) == MN_PRIVATE + || (c->data[c->previous] & MN_MASK) == MN_REMOTE) + { + c->data[c->previous+1] += param ; + return ; + } + } + else if (code == MN_POP) + { + switch (c->data[c->previous] & MN_MASK) + { + case MN_LET: + c->data[c->previous] = MN_LETNP | (c->data[c->previous] & ~MN_MASK); + return ; + case MN_CALL: + c->data[c->previous] = MN_PROC ; + return ; + case MN_SYSCALL: + c->data[c->previous] = MN_SYSPROC ; + return ; + } + } + else if ((code & MN_MASK) == MN_PTR) + { + /* Mismo caso */ + + switch (c->data[c->previous] & MN_MASK) + { + case MN_PRIVATE: + c->data[c->previous] = MN_GET_PRIV | (code & ~MN_MASK) ; + return ; + case MN_LOCAL: + c->data[c->previous] = MN_GET_LOCAL | (code & ~MN_MASK) ; + return ; + case MN_PUBLIC: + c->data[c->previous] = MN_GET_PUBLIC | (code & ~MN_MASK) ; + return ; + case MN_REMOTE_PUBLIC: + c->data[c->previous] = MN_GET_REMOTE_PUBLIC | (code & ~MN_MASK) ; + return ; + case MN_GLOBAL: + c->data[c->previous] = MN_GET_GLOBAL | (code & ~MN_MASK) ; + return ; + case MN_REMOTE: + c->data[c->previous] = MN_GET_REMOTE | (code & ~MN_MASK) ; + return ; + case MN_PUSH: + return ; + } + } + } + + c->previous2 = c->previous; + c->previous = c->current ; + c->data[c->current++] = code ; + + if (MN_PARAMS(code) > 0) { + c->data[c->current++] = param ; + } + + if (c->current+2 >= c->reserved) codeblock_alloc (c, 32) ; +} + diff --git a/core/bgdc/src/constants.c b/core/bgdc/src/constants.c new file mode 100644 index 0000000..d9b63a4 --- /dev/null +++ b/core/bgdc/src/constants.c @@ -0,0 +1,110 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "bgdc.h" + +#include "varspace.h" + +/* ---------------------------------------------------------------------- */ +/* Gestor de constantes */ +/* ---------------------------------------------------------------------- */ + +static CONSTANT * constants ; +static int constants_used ; +static int constants_reserved ; + +void constants_init() +{ + constants = ( CONSTANT * ) calloc( 16, sizeof( CONSTANT ) ); + constants_reserved = 16 ; + constants_used = 0 ; +} + +void constants_alloc( int count ) +{ + constants = ( CONSTANT * ) realloc( constants, ( constants_reserved += count ) * sizeof( CONSTANT ) ) ; + if ( !constants ) + { + fprintf( stdout, "constants_alloc: out of memory\n" ) ; + exit( 1 ) ; + } +} + +CONSTANT * constants_search( int code ) +{ + int i ; + + for ( i = 0 ; i < constants_used ; i++ ) if ( constants[i].code == code ) return &constants[i] ; + return 0 ; +} + +void constants_add( int code, TYPEDEF type, int value ) +{ + CONSTANT * c; + + if ( constants_used == constants_reserved ) constants_alloc( 16 ) ; + + if ( varspace_search( &global, code ) ) + { + token.code = code; + token.type = IDENTIFIER; + compile_error( MSG_VARIABLE_REDECLARED_AS_CONSTANT ) ; + } + + if ( varspace_search( &local, code ) ) + { + token.code = code; + token.type = IDENTIFIER; + compile_error( MSG_VARIABLE_REDECLARED_AS_CONSTANT ) ; + } + + if (( c = constants_search( code ) ) && ( !typedef_is_equal( c->type, type ) || c->value != value ) ) + { + token.code = string_new( identifier_name( code ) ); + token.type = STRING; + compile_error( "Constant redefined" ); + } + + constants[constants_used].code = code ; + constants[constants_used].type = type ; + constants[constants_used].value = value ; + constants_used++ ; +} + +void constants_dump() +{ + int i ; + + printf( "---- %d constants of %d ----\n", constants_used, constants_reserved ) ; + for ( i = 0 ; i < constants_used ; i++ ) + printf( "%4d: %-16s= %d\n", i, + identifier_name( constants[i].code ), constants[i].value ) ; +} diff --git a/core/bgdc/src/dcbw.c b/core/bgdc/src/dcbw.c new file mode 100644 index 0000000..987a947 --- /dev/null +++ b/core/bgdc/src/dcbw.c @@ -0,0 +1,1258 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdlib.h> + +#ifdef TARGET_BEOS +#include <posix/assert.h> +#else +#include <assert.h> +#endif + +#include <stdio.h> +#include <string.h> + +#include "bgdc.h" +#include "dcb.h" + +#define SYSPROCS_ONLY_DECLARE +#include "sysprocs.h" + +#define FREEM(m) if(m) { free(m); m = NULL; } + +/* dirty declare external vars */ + +extern char * string_mem; +extern int * string_offset; +extern int string_count, string_used; +extern int procdef_count; +extern int identifier_count; +extern PROCDEF ** procs; + +extern int debug; + +/* List of files to include in DCB file managment */ + +DCB_FILE * dcb_files = 0; +int dcb_ef_alloc = 0; +int dcb_filecount = 0; +char ** dcb_fullname = 0; +int dcb_options = 0; + +void dcb_add_file( const char * filename ) +{ + file * fp; + long size; + int i; + char buffer[1024]; + + if ( filename[0] == '@' ) + { + fp = file_open( filename + 1, "rb" ); + if ( !fp ) return; + while ( !file_eof( fp ) ) + { + char *p; + file_qgets( fp, buffer, sizeof( buffer ) ); + if ( ( p = strchr( buffer, '\n' ) ) ) *p = '\0'; + if ( ( p = strchr( buffer, '\r' ) ) ) *p = '\0'; + if ( buffer[0] == '#' || !buffer[0] ) continue; + dcb_add_file( buffer ); + } + file_close( fp ); + return; + } + + /* Dinamyc libraries aren't included in the stub */ +/* + if ( strlen( filename ) > 4 && !strncmp( filename + strlen( filename ) - 4, ".dll", 4 ) ) return; + if ( strlen( filename ) > 3 && !strncmp( filename + strlen( filename ) - 3, ".so", 3 ) ) return; + if ( strlen( filename ) > 6 && !strncmp( filename + strlen( filename ) - 6, ".dylib", 6 ) ) return; +*/ + for ( i = 0; filename[i]; i++ ) if ( filename[i] == '\\' ) buffer[i] = '/'; else buffer[i] = filename[i]; + buffer[i] = '\0'; + + filename = ( const char * ) buffer; + + fp = file_open( filename, "rb" ); + if ( !fp ) return; + size = file_size( fp ); + file_close( fp ); + + if ( dcb_ef_alloc == dcb_filecount ) + { + dcb_files = ( DCB_FILE * )realloc( dcb_files, sizeof( DCB_FILE ) * ( dcb_ef_alloc += 16 ) ); + if ( !dcb_files ) compile_error( "dcb_add_file: out of memory" ); + } + + /* file is already included ? */ + + for ( i = 0; i < dcb_filecount; i++ ) + if ( strcmp( filename, (const char *)dcb_files[i].Name ) == 0 ) return; + + dcb_files[dcb_filecount].Name = (uint8_t *) strdup( filename ); + dcb_files[dcb_filecount].SFile = size; + + dcb_filecount++; +} + +/* Hack for set ID's to varspaces */ + +VARSPACE ** dcb_orig_varspace = 0; +int dcb_varspaces = 0; + +static int dcb_varspace( VARSPACE * v ) +{ + int n, result; + + for ( n = 0; n < dcb_varspaces; n++ ) + if ( dcb_orig_varspace[n] == v ) return n; + + dcb.varspace = ( DCB_VARSPACE * ) realloc( dcb.varspace, sizeof( DCB_VARSPACE ) * ( dcb_varspaces + 1 ) ); + dcb_orig_varspace = ( VARSPACE ** ) realloc( dcb_orig_varspace, sizeof( VARSPACE * ) * ( dcb_varspaces + 1 ) ); + + dcb_orig_varspace[dcb_varspaces] = v; + + dcb.varspace[dcb_varspaces].NVars = v->count; ARRANGE_DWORD( &dcb.varspace[dcb_varspaces].NVars ); /* Used Only for dcb */ + result = dcb_varspaces++; + + for ( n = 0; n < v->count; n++ ) + if ( v->vars[n].type.varspace ) dcb_varspace( v->vars[n].type.varspace ); + + return result; +} + +/* TYPEDEF converts (used in compile time) */ + +void dcb_settype( DCB_TYPEDEF * d, TYPEDEF * t ) +{ + int n; + + for ( n = 0; n < MAX_TYPECHUNKS; n++ ) + { + d->BaseType[n] = t->chunk[n].type; /* 8 bits */ + d->Count [n] = t->chunk[n].count; + } + + if ( t->varspace ) + d->Members = dcb_varspace( t->varspace ); + else + d->Members = NO_MEMBERS; +} + + +/* TYPEDEF converts (used in save time) */ + +void dcb_prepare_type( DCB_TYPEDEF * d, TYPEDEF * t ) +{ + int n; + + for ( n = 0; n < MAX_TYPECHUNKS; n++ ) + { + d->BaseType[n] = t->chunk[n].type; /* 8 bits */ + d->Count [n] = t->chunk[n].count; ARRANGE_DWORD( &d->Count[n] ); + } + + if ( t->varspace ) + d->Members = dcb_varspace( t->varspace ); + else + d->Members = NO_MEMBERS; + + ARRANGE_DWORD( &d->Members ); +} + +/* Make DCB file (see dcb.h) */ + +DCB_HEADER dcb; + +int dcb_save( const char * filename, int options, const char * stubname ) +{ + file * fp; + uint32_t n, i, size; + long offset; + identifier * id; + long stubsize = 0; + void * stubdata; + + int NPriVars = 0; + int NPubVars = 0; + + int SCode = 0; + int SPrivate = 0; + int SPublic = 0; + int OFilesTab = 0; + + DCB_SYSPROC_CODE sdcb; + SYSPROC * s; + int NSysProcs = 0; + + fp = file_open( filename, "wb0" ); + if ( !fp ) + { + fprintf( stdout, "ERROR: can't open %s\n", filename ); + return 0; + } + + /* Write the stub file */ + if ( stubname ) + { + file * stub = file_open( stubname, "rb0" ); + + if ( !stub ) + { + fprintf( stdout, "ERROR: can't open %s\n", stubname ); + return 0; + } + + stubsize = file_size( stub ); + stubdata = calloc( stubsize, sizeof( char ) ); + if ( !stubdata ) + { + fprintf( stdout, "ERROR: Stub %s too big\n", stubname ); + return 0; + } + if ( file_read( stub, stubdata, stubsize ) != stubsize ) + { + fprintf( stdout, "ERROR: error reading stub %s\n", stubname ); + return 0; + } + file_write( fp, stubdata, stubsize ); + if ( stubsize & 15 ) + { + file_write( fp, stubdata, 16 - ( stubsize & 15 ) ); + stubsize += 16 - ( stubsize & 15 ); + } + free( stubdata ); + file_close( stub ); + } + + /* Refresh sysprocs list */ + + for ( s = sysprocs; s->name; s++ ) + { + if ( s->id == 0 ) s->id = identifier_search_or_add( s->name ); + NSysProcs++; + } + + /* We can asume that dcb.varspace is already filled */ + + /* Splinter, fix to save neccessary info only */ + if ( !( options & DCB_DEBUG ) ) n_files = 0; + + /* 1. Fill header */ + + if ( libmode ) + memcpy( dcb.data.Header, DCL_MAGIC, sizeof( DCL_MAGIC ) - 1 ); + else + memcpy( dcb.data.Header, DCB_MAGIC, sizeof( DCB_MAGIC ) - 1 ); + + dcb.data.Version = DCB_VERSION; ARRANGE_DWORD( &dcb.data.Version ); + + dcb.data.NProcs = procdef_count; ARRANGE_DWORD( &dcb.data.NProcs ); + dcb.data.NFiles = dcb_filecount; ARRANGE_DWORD( &dcb.data.NFiles ); + dcb.data.NID = identifier_count; ARRANGE_DWORD( &dcb.data.NID ); + dcb.data.NStrings = string_count; ARRANGE_DWORD( &dcb.data.NStrings ); + dcb.data.NLocVars = local.count; ARRANGE_DWORD( &dcb.data.NLocVars ); + dcb.data.NLocStrings = local.stringvar_count; ARRANGE_DWORD( &dcb.data.NLocStrings ); + dcb.data.NGloVars = global.count; ARRANGE_DWORD( &dcb.data.NGloVars ); + + dcb.data.SGlobal = globaldata->current; ARRANGE_DWORD( &dcb.data.SGlobal ); + dcb.data.SLocal = localdata->current; ARRANGE_DWORD( &dcb.data.SLocal ); + dcb.data.SText = string_used; ARRANGE_DWORD( &dcb.data.SText ); + + dcb.data.NImports = nimports; ARRANGE_DWORD( &dcb.data.NImports ); + + dcb.data.NSourceFiles = n_files; ARRANGE_DWORD( &dcb.data.NSourceFiles ); + + dcb.data.NSysProcsCodes = NSysProcs; ARRANGE_DWORD( &dcb.data.NSysProcsCodes ); + + /* 2. Build process table */ + + dcb.proc = ( DCB_PROC * ) calloc( procdef_count, sizeof( DCB_PROC ) ); + + for ( n = 0; n < procdef_count; n++ ) + { + dcb.proc[n].data.ID = procs[n]->identifier; ARRANGE_DWORD( &dcb.proc[n].data.ID ); + dcb.proc[n].data.Flags = procs[n]->flags; ARRANGE_DWORD( &dcb.proc[n].data.Flags ); + dcb.proc[n].data.NParams = procs[n]->params; ARRANGE_DWORD( &dcb.proc[n].data.NParams ); + + dcb.proc[n].data.NPriVars = procs[n]->privars->count; ARRANGE_DWORD( &dcb.proc[n].data.NPriVars ); + dcb.proc[n].data.NPriStrings = procs[n]->privars->stringvar_count; ARRANGE_DWORD( &dcb.proc[n].data.NPriStrings ); + + dcb.proc[n].data.NPubVars = procs[n]->pubvars->count; ARRANGE_DWORD( &dcb.proc[n].data.NPubVars ); + dcb.proc[n].data.NPubStrings = procs[n]->pubvars->stringvar_count; ARRANGE_DWORD( &dcb.proc[n].data.NPubStrings ); + + dcb.proc[n].data.NSentences = procs[n]->sentence_count; ARRANGE_DWORD( &dcb.proc[n].data.NSentences ); + + dcb.proc[n].data.SPrivate = procs[n]->pridata->current; ARRANGE_DWORD( &dcb.proc[n].data.SPrivate ); + dcb.proc[n].data.SPublic = procs[n]->pubdata->current; ARRANGE_DWORD( &dcb.proc[n].data.SPublic ); + + dcb.proc[n].data.SCode = procs[n]->code.current * 4; ARRANGE_DWORD( &dcb.proc[n].data.SCode ); + + dcb.proc[n].data.OExitCode = procs[n]->exitcode ; ARRANGE_DWORD( &dcb.proc[n].data.OExitCode ); + dcb.proc[n].data.OErrorCode = procs[n]->errorcode ; ARRANGE_DWORD( &dcb.proc[n].data.OErrorCode ); + + SCode += procs[n]->code.current * 4; + + NPriVars += procs[n]->privars->count; + NPubVars += procs[n]->pubvars->count; + + SPrivate += procs[n]->pridata->current; + SPublic += procs[n]->pubdata->current; + + dcb.proc[n].sentence = ( DCB_SENTENCE * ) calloc( procs[n]->sentence_count, sizeof( DCB_SENTENCE ) ); + + for ( i = 0; i < procs[n]->sentence_count; i++ ) + { + dcb.proc[n].sentence[i].NFile = 0; ARRANGE_DWORD( &dcb.proc[n].sentence[i].NFile ); + dcb.proc[n].sentence[i].NLine = procs[n]->sentences[i].line; ARRANGE_DWORD( &dcb.proc[n].sentence[i].NLine ); + dcb.proc[n].sentence[i].NCol = procs[n]->sentences[i].col; ARRANGE_DWORD( &dcb.proc[n].sentence[i].NCol ); + dcb.proc[n].sentence[i].OCode = procs[n]->sentences[i].offset; ARRANGE_DWORD( &dcb.proc[n].sentence[i].OCode ); + } + + /* Splinter, tipos de parametros */ + + dcb.proc[n].privar = ( DCB_VAR * ) calloc( procs[n]->privars->count, sizeof( DCB_VAR ) ); + for ( i = 0; i < procs[n]->privars->count; i++ ) + { + dcb_prepare_type( &dcb.proc[n].privar[i].Type, &procs[n]->privars->vars[i].type ); + + dcb.proc[n].privar[i].ID = procs[n]->privars->vars[i].code; ARRANGE_DWORD( &dcb.proc[n].privar[i].ID ); + dcb.proc[n].privar[i].Offset = procs[n]->privars->vars[i].offset; ARRANGE_DWORD( &dcb.proc[n].privar[i].Offset ); + } + + dcb.proc[n].pubvar = ( DCB_VAR * ) calloc( procs[n]->pubvars->count, sizeof( DCB_VAR ) ); + for ( i = 0; i < procs[n]->pubvars->count; i++ ) + { + dcb_prepare_type( &dcb.proc[n].pubvar[i].Type, &procs[n]->pubvars->vars[i].type ); + + dcb.proc[n].pubvar[i].ID = procs[n]->pubvars->vars[i].code; ARRANGE_DWORD( &dcb.proc[n].pubvar[i].ID ); + dcb.proc[n].pubvar[i].Offset = procs[n]->pubvars->vars[i].offset; ARRANGE_DWORD( &dcb.proc[n].pubvar[i].Offset ); + } + } + + /* 3. Build global tables */ + + dcb.id = ( DCB_ID * ) calloc( identifier_count, sizeof( DCB_ID ) ); + + id = identifier_first(); + + for ( n = 0; n < identifier_count; n++ ) + { + assert( id != 0 ); + strncpy( (char *)dcb.id[n].Name, id->name, sizeof( dcb.id[n].Name ) ); + dcb.id[n].Code = id->code; ARRANGE_DWORD( &dcb.id[n].Code ); + + id = identifier_next( id ); + } + + dcb.glovar = ( DCB_VAR * ) calloc( global.count, sizeof( DCB_VAR ) ); + dcb.locvar = ( DCB_VAR * ) calloc( local.count, sizeof( DCB_VAR ) ); + + for ( n = 0; n < global.count; n++ ) + { + dcb_prepare_type( &dcb.glovar[n].Type, &global.vars[n].type ); + + dcb.glovar[n].ID = global.vars[n].code; ARRANGE_DWORD( &dcb.glovar[n].ID ); + dcb.glovar[n].Offset = global.vars[n].offset; ARRANGE_DWORD( &dcb.glovar[n].Offset ); + } + + for ( n = 0; n < local.count; n++ ) + { + dcb_prepare_type( &dcb.locvar[n].Type, &local.vars[n].type ); + + dcb.locvar[n].ID = local.vars[n].code; ARRANGE_DWORD( &dcb.locvar[n].ID ); + dcb.locvar[n].Offset = local.vars[n].offset; ARRANGE_DWORD( &dcb.locvar[n].Offset ); + } + + dcb.data.NVarSpaces = dcb_varspaces; + + dcb.file = dcb_files; + + /* 4. Calculate offsets */ + + offset = sizeof( DCB_HEADER_DATA ); + + dcb.data.OProcsTab = offset; offset += sizeof( DCB_PROC_DATA ) * procdef_count; ARRANGE_DWORD( &dcb.data.OProcsTab ); + dcb.data.OStrings = offset; offset += 4 * string_count; ARRANGE_DWORD( &dcb.data.OStrings ); + dcb.data.OGloVars = offset; offset += sizeof( DCB_VAR ) * global.count; ARRANGE_DWORD( &dcb.data.OGloVars ); + dcb.data.OLocVars = offset; offset += sizeof( DCB_VAR ) * local.count; ARRANGE_DWORD( &dcb.data.OLocVars ); + dcb.data.OLocStrings = offset; offset += 4 * local.stringvar_count; ARRANGE_DWORD( &dcb.data.OLocStrings ); + dcb.data.OID = offset; offset += sizeof( DCB_ID ) * identifier_count; ARRANGE_DWORD( &dcb.data.OID ); + dcb.data.OVarSpaces = offset; offset += sizeof( DCB_VARSPACE ) * dcb_varspaces; ARRANGE_DWORD( &dcb.data.OVarSpaces ); + dcb.data.OText = offset; offset += string_used; ARRANGE_DWORD( &dcb.data.OText ); + dcb.data.OImports = offset; offset += 4 * nimports; ARRANGE_DWORD( &dcb.data.OImports ); + dcb.data.OGlobal = offset; offset += globaldata->current; ARRANGE_DWORD( &dcb.data.OGlobal ); + dcb.data.OLocal = offset; offset += localdata->current; ARRANGE_DWORD( &dcb.data.OLocal ); + + dcb.data.OSourceFiles = offset; ARRANGE_DWORD( &dcb.data.OSourceFiles ); + + /* sources */ + for ( n = 0; n < n_files; n++ ) + offset += sizeof( uint32_t ) + strlen( files[n] ) + 1; + + dcb.data.OSysProcsCodes = offset; ARRANGE_DWORD( &dcb.data.OSysProcsCodes ); + for ( s = sysprocs; s->name; s++ ) + { + offset += sizeof( DCB_SYSPROC_CODE ); + offset += s->params; + } + + for ( n = 0; n < dcb_varspaces; n++ ) + { + dcb.varspace[n].OVars = offset; ARRANGE_DWORD( &dcb.varspace[n].OVars ); + offset += sizeof( DCB_VAR ) * dcb_orig_varspace[n]->count; + } + + for ( n = 0; n < procdef_count; n++ ) + { + dcb.proc[n].data.OSentences = offset; offset += sizeof( DCB_SENTENCE ) * procs[n]->sentence_count; ARRANGE_DWORD( &dcb.proc[n].data.OSentences ); + + /* Private */ + dcb.proc[n].data.OPriVars = offset; offset += sizeof( DCB_VAR ) * procs[n]->privars->count; ARRANGE_DWORD( &dcb.proc[n].data.OPriVars ); + dcb.proc[n].data.OPriStrings = offset; offset += 4 * procs[n]->privars->stringvar_count; ARRANGE_DWORD( &dcb.proc[n].data.OPriStrings ); + dcb.proc[n].data.OPrivate = offset; offset += procs[n]->pridata->current; ARRANGE_DWORD( &dcb.proc[n].data.OPrivate ); + + /* Publics */ + dcb.proc[n].data.OPubVars = offset; offset += sizeof( DCB_VAR ) * procs[n]->pubvars->count; ARRANGE_DWORD( &dcb.proc[n].data.OPubVars ); + dcb.proc[n].data.OPubStrings = offset; offset += 4 * procs[n]->pubvars->stringvar_count; ARRANGE_DWORD( &dcb.proc[n].data.OPubStrings ); + dcb.proc[n].data.OPublic = offset; offset += procs[n]->pubdata->current; ARRANGE_DWORD( &dcb.proc[n].data.OPublic ); + + /* Code */ + dcb.proc[n].data.OCode = offset; offset += procs[n]->code.current * 4; ARRANGE_DWORD( &dcb.proc[n].data.OCode ); + } + + /* Archivos incluidos */ + OFilesTab = offset; + dcb.data.OFilesTab = OFilesTab; ARRANGE_DWORD( &dcb.data.OFilesTab ); + + /* FullPathName */ + dcb_fullname = calloc( dcb_filecount, sizeof( char * ) ); + + /* Cada uno de los archivos incluidos */ + for ( n = 0; n < dcb_filecount; n++ ) + { + dcb_fullname[n] = (char *)dcb.file[n].Name; /* Guardo el Name, porque lo destruyo en SName (es un union) */ + dcb.file[n].SName = strlen( (const char *)dcb.file[n].Name ) + 1; /* Todavia no hago el ARRANGE de este dato, lo hago luego cuando lo voy a grabar */ + offset += sizeof( DCB_FILE ) + dcb.file[n].SName; + } + + /* Data de los archivos incluidos */ + for ( n = 0; n < dcb_filecount; n++ ) + { + dcb.file[n].OFile = offset; ARRANGE_DWORD( &dcb.file[n].OFile ); + offset += dcb.file[n].SFile; ARRANGE_DWORD( &dcb.file[n].SFile ); + } + + /* ************************************** */ + /* ************************************** */ + /* 5. Guardar todo en disco ordenadamente */ + /* ************************************** */ + /* ************************************** */ + + file_write( fp, &dcb, sizeof( DCB_HEADER_DATA ) ); + + for ( n = 0; n < procdef_count; n++ ) + file_write( fp, &dcb.proc[n], sizeof( DCB_PROC_DATA ) ); + + file_writeUint32A( fp, (uint32_t *)string_offset, string_count ); + file_write( fp, dcb.glovar, sizeof( DCB_VAR ) * global.count ); /* Ya procesado el byteorder */ + file_write( fp, dcb.locvar, sizeof( DCB_VAR ) * local.count ); /* Ya procesado el byteorder */ + file_writeUint32A( fp, (uint32_t *)local.stringvars, local.stringvar_count ); + file_write( fp, dcb.id, sizeof( DCB_ID ) * identifier_count ); /* Ya procesado el byteorder */ + file_write( fp, dcb.varspace, sizeof( DCB_VARSPACE ) * dcb_varspaces ); /* Ya procesado el byteorder */ + file_write( fp, string_mem, string_used ); /* No necesita byteorder */ + file_writeUint32A( fp, (uint32_t *)imports, nimports ); + file_write( fp, globaldata->bytes, globaldata->current ); /* ****** */ + file_write( fp, localdata->bytes, localdata->current ); /* ****** */ + + if ( dcb_options & DCB_DEBUG ) + { + for ( n = 0; n < n_files; n++ ) + { + size = strlen( files[n] ) + 1; + file_writeUint32( fp, &size ); + file_write( fp, files[n], size ); + } + } + + for ( s = sysprocs; s->name; s++ ) + { + int l = s->params; + sdcb.Id = s->id; ARRANGE_DWORD( &sdcb.Id ); + sdcb.Type = s->type; ARRANGE_DWORD( &sdcb.Type ); + sdcb.Params = l; ARRANGE_DWORD( &sdcb.Params ); + sdcb.Code = s->code; ARRANGE_DWORD( &sdcb.Code ); + file_write( fp, &sdcb, sizeof( DCB_SYSPROC_CODE ) ); + file_write( fp, s->paramtypes, l ); + } + + for ( n = 0; n < dcb_varspaces; n++ ) + { + VARIABLE * var; + DCB_VAR v; + + memset (&v, '\0', sizeof(v)); + + var = &dcb_orig_varspace[n]->vars[0]; + + for ( i = 0; i < dcb_orig_varspace[n]->count; i++, var++ ) + { + dcb_prepare_type( &v.Type, &var->type ); + v.ID = var->code; ARRANGE_DWORD( &v.ID ); + v.Offset = var->offset; ARRANGE_DWORD( &v.Offset ); + + file_write( fp, &v, sizeof( DCB_VAR ) ); + } + } + + for ( n = 0; n < procdef_count; n++ ) + { + file_write( fp, dcb.proc[n].sentence, sizeof( DCB_SENTENCE ) * procs[n]->sentence_count ); /* Ya procesado el byteorder */ + + /* Privadas */ + file_write( fp, dcb.proc[n].privar, sizeof( DCB_VAR ) * procs[n]->privars->count ); /* Ya procesado el byteorder */ + file_writeUint32A( fp, (uint32_t *)procs[n]->privars->stringvars, procs[n]->privars->stringvar_count ); + file_write( fp, procs[n]->pridata->bytes, procs[n]->pridata->current ); /* ****** */ + + /* Publicas */ + file_write( fp, dcb.proc[n].pubvar, sizeof( DCB_VAR ) * procs[n]->pubvars->count ); /* Ya procesado el byteorder */ + file_writeUint32A( fp, (uint32_t *)procs[n]->pubvars->stringvars, procs[n]->pubvars->stringvar_count ); + file_write( fp, procs[n]->pubdata->bytes, procs[n]->pubdata->current ); /* ****** */ + + /* Code */ + file_writeUint32A( fp, (uint32_t *)procs[n]->code.data, procs[n]->code.current ); + } + + /* Cada uno de los archivos incluidos */ + for ( n = 0; n < dcb_filecount; n++ ) + { + int siz = dcb.file[n].SName; + ARRANGE_DWORD( &dcb.file[n].SName ); + ARRANGE_DWORD( &dcb.file[n].SFile ); + ARRANGE_DWORD( &dcb.file[n].OFile ); + file_write( fp, &dcb.file[n], sizeof( DCB_FILE ) ); + file_write( fp, dcb_fullname[n], siz ); + } + + for ( n = 0; n < dcb_filecount; n++ ) + { + char buffer[8192]; + file * fp_r = file_open ( dcb_fullname[n], "rb" ); + int chunk_size, siz = 0; + + assert( fp_r ); + while ( !file_eof( fp_r ) ) + { + siz += chunk_size = file_read( fp_r, buffer, 8192 ); + file_write( fp, buffer, chunk_size ); + if ( chunk_size < 8192 ) break; + } + file_close( fp_r ); + } + + /* Write the stub signature */ + + if ( stubname != NULL ) + { + dcb_signature dcb_signature; + + /* Voy al final del archivo */ + + strcpy( dcb_signature.magic, DCB_STUB_MAGIC ); + dcb_signature.dcb_offset = ( int )stubsize; + + ARRANGE_DWORD( &dcb_signature.dcb_offset ); + + file_write( fp, &dcb_signature, sizeof( dcb_signature ) ); + } + + file_close( fp ); + + /* 6. Mostrar estad�sticas */ + + printf( "\nFile %s compiled (%ld bytes):\n\n", filename, offset ); + printf( " Processes %8d\n", procdef_count ); + printf( " Global data %8d bytes\n", globaldata->current ); + printf( " Local data %8d bytes\n", localdata->current ); + printf( " Private data %8d bytes\n", SPrivate ); + printf( " Public data %8d bytes\n", SPublic ); + printf( " Code %8d bytes\n", SCode ); + printf( " System processes %8d\n", NSysProcs ); + + printf( " Globals vars %8d\n", global.count ); + printf( " Locals vars %8d\n", local.count ); + printf( " Private vars %8d\n", NPriVars ); + printf( " Publics vars %8d\n", NPubVars ); + printf( " Identifiers %8d\n", identifier_count ); + printf( " Structs %8d\n", dcb_varspaces ); + printf( " Strings %8d (%d bytes)\n", string_count, string_used ); + + if ( dcb_filecount ) + printf( " Files added %8d (%ld bytes)\n", dcb_filecount, offset - OFilesTab ); + + printf( "\n" ); + + return 1; +} + +/* --------------------------------------------------------------------------- + * load_dcb as library + * --------------------------------------------------------------------------- */ + +int * newid = NULL; +int * stringid = NULL; +int * fileid = NULL; + +/* --------------------------------------------------------------------------- */ + +void * glodata = NULL ; +void * locdata = NULL ; + +DCB_SYSPROC_CODE2 * sysproc_code_ref = NULL ; + +/* ---------------------------------------------------------------------- */ + +typedef struct +{ + int offstart; + int offend; + int offnew; +} range; + +range * glovaroffs = NULL; +range * locvaroffs = NULL; + +VARSPACE * varspaces = NULL; + +/* ---------------------------------------------------------------------- */ + +void dcb_varspaces_load( file * fp, VARSPACE * vs, VARSPACE * vs_array, int count ) +{ + int n, m; + DCB_VAR vars; + VARIABLE var; + TYPEDEF type; + + for ( n = 0; n < count; n++ ) + { + file_read( fp, &vars, sizeof( DCB_VAR ) ) ; + ARRANGE_DWORD( &vars.ID ); + ARRANGE_DWORD( &vars.Offset ); + for ( m = 0; m < MAX_TYPECHUNKS; m++ ) ARRANGE_DWORD( &vars.Type.Count[m] ); + ARRANGE_DWORD( &vars.Type.Members ); + + type.depth = 0; + for ( m = 0; m < MAX_TYPECHUNKS; m++ ) + { + type.chunk[m].type = vars.Type.BaseType[m]; + type.chunk[m].count = vars.Type.Count[m]; + if ( type.chunk[m].type != TYPE_UNDEFINED ) type.depth++; + } + + if ( vars.Type.Members != NO_MEMBERS ) + type.varspace = &vs_array[vars.Type.Members]; + else + type.varspace = NULL; + + var.code = newid[vars.ID]; + var.type = type; + var.offset = vars.Offset; + varspace_add( vs, var ); + } +} + +/* ---------------------------------------------------------------------- */ + +void dcb_vars_load( file * fp, VARSPACE * vs, segment * data, char * data_source, int count, range ** offs, int totalsize ) +{ + int n, m; + DCB_VAR * vars = calloc( count, sizeof( DCB_VAR ) ); + VARIABLE var, * v; + TYPEDEF type; + + if ( offs ) *offs = calloc( count, sizeof( range ) ); + + for ( n = 0; n < count; n++ ) + { + file_read( fp, &vars[n], sizeof( DCB_VAR ) ) ; + ARRANGE_DWORD( &vars[n].ID ); + ARRANGE_DWORD( &vars[n].Offset ); + for ( m = 0; m < MAX_TYPECHUNKS; m++ ) ARRANGE_DWORD( &vars[n].Type.Count[m] ); + ARRANGE_DWORD( &vars[n].Type.Members ); + } + + for ( n = 0; n < count; n++ ) + { + type.depth = 0; + + for ( m = 0; m < MAX_TYPECHUNKS; m++ ) + { + type.chunk[m].type = vars[n].Type.BaseType[m]; + type.chunk[m].count = vars[n].Type.Count[m]; + if ( type.chunk[m].type != TYPE_UNDEFINED ) type.depth++; + } + + if ( vars[n].Type.Members != NO_MEMBERS ) + type.varspace = &varspaces[vars[n].Type.Members]; + else + type.varspace = NULL; + + var.code = newid[vars[n].ID]; + var.type = type; + var.offset = data->current; + + if ( ( v = varspace_search( vs, newid[vars[n].ID] ) ) ) + { + int sz; + + if ( !typedef_is_equal( v->type, type ) ) + { + printf( "ERROR: var %s already exits in varspace but is different\n", identifier_name( newid[vars[n].ID] ) ); + exit ( -1 ); + } + + sz = typedef_size( v->type ); + if ( sz & 0x0003 ) sz = ( sz & ~0x0003 ) + 4; + + if ( offs ) + { + (*offs)[n].offstart = vars[n].Offset; + (*offs)[n].offend = vars[n].Offset + sz - 1; + (*offs)[n].offnew = v->offset; + } + } + else + { + int sz; + if ( n < count - 1 ) + sz = vars[n+1].Offset - vars[n].Offset; + else + sz = totalsize - vars[n].Offset; + + segment_alloc(data, sz); + var.offset = data->current; + varspace_add( vs, var ); + + if ( offs ) + { + (*offs)[n].offstart = vars[n].Offset; + (*offs)[n].offend = vars[n].Offset + sz - 1; + (*offs)[n].offnew = var.offset; + } + + memmove( &((char *)data->bytes)[var.offset], &data_source[vars[n].Offset], sz ); + + data->current += sz; + } + } + + free( vars ); +} + +/* ---------------------------------------------------------------------- */ + +int get_new_off( int off, range * offs, int noffs ) +{ + int n; + + for ( n = 0; n < noffs; n++ ) + if ( off >= offs[n].offstart && off <= offs[n].offend ) + return off - offs[n].offstart + offs[n].offnew; + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +void codeblock_adjust(CODEBLOCK * code) +{ + int * ptr = code->data ; + int n; + + while (ptr < code->data + code->current) + { + if (*ptr == MN_CALL || *ptr == MN_PROC || *ptr == MN_TYPE) + { + ptr[1] = newid[ptr[1]]; + } + + if (MN_TYPEOF(*ptr) == MN_STRING && (*ptr & MN_MASK) == MN_PUSH) + { + ptr[1] = stringid[ptr[1]]; + } + + if ( (*ptr & MN_MASK) == MN_GLOBAL) + { + ptr[1] = get_new_off( ptr[1], glovaroffs, dcb.data.NGloVars ); + } + + if ( (*ptr & MN_MASK) == MN_LOCAL) + { + ptr[1] = get_new_off( ptr[1], locvaroffs, dcb.data.NLocVars ); + } + + if ( (*ptr & MN_MASK) == MN_SENTENCE ) + { + if ( dcb.data.Version == 0x0700 ) + ptr[1] = (ptr[1] & 0xfffff) | ( fileid[ptr[1]>>24] << 20 ); + else + ptr[1] = (ptr[1] & 0xfffff) | ( fileid[ptr[1]>>20] << 20 ); + } + + if ( (*ptr & MN_MASK) == MN_SYSCALL || (*ptr & MN_MASK) == MN_SYSPROC ) + { + DCB_SYSPROC_CODE2 * s = sysproc_code_ref ; + int found = 0; + for ( n = 0; n < dcb.data.NSysProcsCodes && !found; n++, s++ ) + { + if ( s->Code == ptr[1] ) + { + SYSPROC * p = sysproc_get( newid[ s->Id ] ); + for ( ; p && !found; p = p->next ) + { + if ( p->type == s->Type && p->params == s->Params && + !strcmp( (const char *)s->ParamTypes, p->paramtypes ) ) + { + ptr[1] = p->code; + found = 1; + } + } + } + } + } + ptr += MN_PARAMS(*ptr)+1 ; + } +} + +/* ---------------------------------------------------------------------- */ + +int dcb_load_lib( const char * filename ) +{ + unsigned int n ; + file * fp ; + PROCDEF * proc; + + /* check for existence of the DCB FILE */ + if ( !file_exists( filename ) ) return 0 ; + + fp = file_open( filename, "rb0" ) ; + if ( !fp ) + { + fprintf( stderr, "ERROR: Runtime error - Could not open file (%s)\n", filename ) ; + exit( 1 ); + } + + /* Read Header */ + + file_seek( fp, 0, SEEK_SET ); + file_read( fp, &dcb, sizeof( DCB_HEADER_DATA ) ) ; + + ARRANGE_DWORD( &dcb.data.Version ); + ARRANGE_DWORD( &dcb.data.NProcs ); + ARRANGE_DWORD( &dcb.data.NFiles ); + ARRANGE_DWORD( &dcb.data.NID ); + ARRANGE_DWORD( &dcb.data.NStrings ); + ARRANGE_DWORD( &dcb.data.NLocVars ); + ARRANGE_DWORD( &dcb.data.NLocStrings ); + ARRANGE_DWORD( &dcb.data.NGloVars ); + + ARRANGE_DWORD( &dcb.data.SGlobal ); + ARRANGE_DWORD( &dcb.data.SLocal ); + ARRANGE_DWORD( &dcb.data.SText ); + + ARRANGE_DWORD( &dcb.data.NImports ); + + ARRANGE_DWORD( &dcb.data.NSourceFiles ); + + ARRANGE_DWORD( &dcb.data.NSysProcsCodes ); + + ARRANGE_DWORD( &dcb.data.OProcsTab ); + ARRANGE_DWORD( &dcb.data.OID ); + ARRANGE_DWORD( &dcb.data.OStrings ); + ARRANGE_DWORD( &dcb.data.OText ); + ARRANGE_DWORD( &dcb.data.OGlobal ); + ARRANGE_DWORD( &dcb.data.OGloVars ); + ARRANGE_DWORD( &dcb.data.OLocal ); + ARRANGE_DWORD( &dcb.data.OLocVars ); + ARRANGE_DWORD( &dcb.data.OLocStrings ); + ARRANGE_DWORD( &dcb.data.OVarSpaces ); + ARRANGE_DWORD( &dcb.data.OFilesTab ); + ARRANGE_DWORD( &dcb.data.OImports ); + + ARRANGE_DWORD( &dcb.data.OSourceFiles ); + ARRANGE_DWORD( &dcb.data.OSysProcsCodes ); + + if ( memcmp( dcb.data.Header, DCL_MAGIC, sizeof( DCL_MAGIC ) - 1 ) != 0 ) return 0 ; + if ( dcb.data.Version < 0x0710 ) return -1 ; + + /* Load identifiers */ + + if ( dcb.data.NID ) + { + dcb.id = ( DCB_ID * ) calloc( dcb.data.NID, sizeof( DCB_ID ) ) ; + + FREEM( newid ); + newid = calloc( dcb.data.NID, sizeof( int ) ); + + file_seek( fp, dcb.data.OID, SEEK_SET ) ; + for ( n = 0; n < dcb.data.NID; n++ ) + { + file_read( fp, &dcb.id[n], sizeof( DCB_ID ) ) ; + ARRANGE_DWORD( &dcb.id[n].Code ); + newid[dcb.id[n].Code] = identifier_search_or_add( ( const char * ) dcb.id[n].Name ); + } + free( dcb.id ); + } + + /* Load strings */ + + if ( dcb.data.NStrings ) + { + char * strdata = calloc( 1, dcb.data.SText ); + uint32_t * stroffs = calloc( dcb.data.NStrings, sizeof( uint32_t ) ); + + FREEM( stringid ); + stringid = calloc( dcb.data.NStrings, sizeof( int ) ); + + file_seek(( file * )fp, dcb.data.OStrings, SEEK_SET ) ; + file_readUint32A(( file * )fp, stroffs, dcb.data.NStrings ) ; + + file_seek(( file * )fp, dcb.data.OText, SEEK_SET ) ; + file_read(( file * )fp, strdata, dcb.data.SText ) ; + + for ( n = 0; n < dcb.data.NStrings; n++ ) stringid[n] = string_new( &strdata[stroffs[n]] ); + + free( strdata ); + free( stroffs ); + } + + /* Load imports */ + + if ( dcb.data.NImports ) + { + dcb.imports = ( uint32_t * )calloc( dcb.data.NImports, sizeof( uint32_t ) ) ; + file_seek( fp, dcb.data.OImports, SEEK_SET ) ; + file_readUint32A( fp, dcb.imports, dcb.data.NImports ) ; + for ( n = 0; n < dcb.data.NImports; n++ ) import_mod( ( char * ) string_get( stringid[dcb.imports[n]] ) ); + FREEM( dcb.imports ); + } + + /* Recupero tabla de fixup de sysprocs */ + + sysproc_code_ref = calloc( dcb.data.NSysProcsCodes, sizeof( DCB_SYSPROC_CODE2 ) ) ; + file_seek( fp, dcb.data.OSysProcsCodes, SEEK_SET ) ; + for ( n = 0; n < dcb.data.NSysProcsCodes; n++ ) + { + DCB_SYSPROC_CODE sdcb; + file_read( fp, &sdcb, sizeof( DCB_SYSPROC_CODE ) ) ; + + ARRANGE_DWORD( &sdcb.Id ); + ARRANGE_DWORD( &sdcb.Type ); + ARRANGE_DWORD( &sdcb.Params ); + ARRANGE_DWORD( &sdcb.Code ); + + sysproc_code_ref[n].Id = sdcb.Id ; + sysproc_code_ref[n].Type = sdcb.Type ; + sysproc_code_ref[n].Params = sdcb.Params ; + sysproc_code_ref[n].Code = sdcb.Code ; + sysproc_code_ref[n].ParamTypes = ( uint8_t * ) calloc( sdcb.Params + 1, sizeof( char ) ); + if ( sdcb.Params ) file_read( fp, sysproc_code_ref[n].ParamTypes, sdcb.Params ) ; + } + + /* Load sources */ + + if ( dcb.data.NSourceFiles ) + { + char filename[__MAX_PATH] ; + + fileid = calloc( dcb.data.NSourceFiles, sizeof( int ) ); + + dcb.sourcecount = ( uint32_t * ) calloc( dcb.data.NSourceFiles, sizeof( uint32_t ) ) ; + dcb.sourcelines = ( uint8_t *** ) calloc( dcb.data.NSourceFiles, sizeof( char ** ) ) ; + dcb.sourcefiles = ( uint8_t ** ) calloc( dcb.data.NSourceFiles, sizeof( char * ) ) ; + file_seek( fp, dcb.data.OSourceFiles, SEEK_SET ) ; + for ( n = 0; n < dcb.data.NSourceFiles; n++ ) + { + int m; + uint32_t size; + file_readUint32( fp, &size ) ; + file_read( fp, filename, size ) ; + fileid[n] = -1; + for( m = 0; m < n_files; m++ ) if ( !strcmp( filename, files[m] ) ) fileid[n] = m; + if ( fileid[n] == -1 ) + { + strcpy( files[n_files], filename ); + fileid[n] = n_files++; + } + } + } + + /* Load datas */ + + glodata = ( void * ) calloc( dcb.data.SGlobal, 1 ) ; + locdata = ( void * ) calloc( dcb.data.SLocal, 1 ) ; + + /* Recupera las zonas de datos globales */ + + file_seek( fp, dcb.data.OGlobal, SEEK_SET ) ; + file_read( fp, glodata, dcb.data.SGlobal ) ; /* **** */ + + file_seek( fp, dcb.data.OLocal, SEEK_SET ) ; + file_read( fp, locdata, dcb.data.SLocal ) ; /* **** */ + + /* Varspaces Load */ + + if ( dcb.data.NVarSpaces ) + { + varspaces = ( VARSPACE * ) calloc( dcb.data.NVarSpaces, sizeof( VARSPACE ) ) ; + dcb.varspace = ( DCB_VARSPACE * ) calloc( dcb.data.NVarSpaces, sizeof( DCB_VARSPACE ) ) ; + + file_seek( fp, dcb.data.OVarSpaces, SEEK_SET ) ; + for ( n = 0; n < dcb.data.NVarSpaces; n++ ) + { + file_read( fp, &dcb.varspace[n], sizeof( DCB_VARSPACE ) ) ; + ARRANGE_DWORD( &dcb.varspace[n].NVars ); + ARRANGE_DWORD( &dcb.varspace[n].OVars ); + } + + for ( n = 0; n < dcb.data.NVarSpaces; n++ ) + { + if ( !dcb.varspace[n].NVars ) continue ; + file_seek( fp, dcb.varspace[n].OVars, SEEK_SET ) ; + dcb_varspaces_load( fp, &varspaces[n], varspaces, dcb.varspace[n].NVars ); + } + } + + if ( dcb.data.NGloVars ) + { + file_seek( fp, dcb.data.OGloVars, SEEK_SET ) ; + dcb_vars_load( fp, &global, globaldata, glodata, dcb.data.NGloVars, &glovaroffs, dcb.data.SGlobal ); + } + + if ( dcb.data.NLocVars ) + { + file_seek( fp, dcb.data.OLocVars, SEEK_SET ) ; + dcb_vars_load( fp, &local, localdata, locdata, dcb.data.NLocVars, &locvaroffs, dcb.data.SLocal ); + } + + if ( dcb.data.NLocStrings ) + { + int o, newoff, found, m; + int * locstr = ( int * ) calloc( dcb.data.NLocStrings + 4, sizeof( int ) ) ; + + file_seek( fp, dcb.data.OLocStrings, SEEK_SET ) ; + file_readUint32A( fp, (uint32_t *)locstr, dcb.data.NLocStrings ) ; + for ( m = 0; m < dcb.data.NLocStrings; m++ ) + { + newoff = get_new_off( locstr[m], locvaroffs, dcb.data.NLocStrings ); + for ( found = 0, o = 0; o < local.stringvar_count; o++ ) if ( newoff == local.stringvars[o] ) { found = 1; break; } + if ( !found ) varspace_varstring( &local, newoff ); + } + FREEM( locstr ); + } + + /* Load process */ + + dcb.proc = ( DCB_PROC * ) calloc(( 1 + dcb.data.NProcs ), sizeof( DCB_PROC ) ) ; + + file_seek( fp, dcb.data.OProcsTab, SEEK_SET ) ; + for ( n = 0; n < dcb.data.NProcs; n++ ) + { + file_read( fp, &dcb.proc[n], sizeof( DCB_PROC_DATA ) ) ; + + ARRANGE_DWORD( &dcb.proc[n].data.ID ); + + ARRANGE_DWORD( &dcb.proc[n].data.Flags ); + ARRANGE_DWORD( &dcb.proc[n].data.NParams ); + + ARRANGE_DWORD( &dcb.proc[n].data.NPriVars ); + ARRANGE_DWORD( &dcb.proc[n].data.NPriStrings ); + + ARRANGE_DWORD( &dcb.proc[n].data.NPubVars ); + ARRANGE_DWORD( &dcb.proc[n].data.NPubStrings ); + + ARRANGE_DWORD( &dcb.proc[n].data.NSentences ); + + ARRANGE_DWORD( &dcb.proc[n].data.SPrivate ); + ARRANGE_DWORD( &dcb.proc[n].data.SPublic ); + + ARRANGE_DWORD( &dcb.proc[n].data.SCode ); + + ARRANGE_DWORD( &dcb.proc[n].data.OExitCode ); + ARRANGE_DWORD( &dcb.proc[n].data.OErrorCode ); + + ARRANGE_DWORD( &dcb.proc[n].data.OSentences ); + + ARRANGE_DWORD( &dcb.proc[n].data.OPriVars ); + ARRANGE_DWORD( &dcb.proc[n].data.OPriStrings ); + ARRANGE_DWORD( &dcb.proc[n].data.OPrivate ); + + ARRANGE_DWORD( &dcb.proc[n].data.OPubVars ); + ARRANGE_DWORD( &dcb.proc[n].data.OPubStrings ); + ARRANGE_DWORD( &dcb.proc[n].data.OPublic ); + + ARRANGE_DWORD( &dcb.proc[n].data.OCode ); + } + + for ( n = 0; n < dcb.data.NProcs; n++ ) + { + char * pridata = NULL, *pubdata = NULL; + range * prioffs = NULL, * puboffs = NULL; + + if ( !dcb.proc[n].data.SCode ) + { + continue; + } + else if ( procdef_search( newid[dcb.proc[n].data.ID] ) ) + { + if ( debug ) + { + token.type = IDENTIFIER; + token.code = newid[dcb.proc[n].data.ID]; + compile_warning(0, MSG_PROC_ALREADY_DEFINED); + } + continue; + } + + proc = procdef_new(procdef_getid(), newid[dcb.proc[n].data.ID]); + + codeblock_alloc(&proc->code, dcb.proc[n].data.SCode); + + file_seek( fp, dcb.proc[n].data.OCode, SEEK_SET ) ; + file_readUint32A( fp, (uint32_t *)proc->code.data, dcb.proc[n].data.SCode / sizeof(uint32_t) ) ; + proc->code.current = dcb.proc[n].data.SCode / sizeof(uint32_t); + + if ( dcb.proc[n].data.OExitCode ) + proc->exitcode = dcb.proc[n].data.OExitCode ; + else + proc->exitcode = 0 ; + + if ( dcb.proc[n].data.OErrorCode ) + proc->errorcode = dcb.proc[n].data.OErrorCode ; + else + proc->errorcode = 0 ; + + proc->defined = 1; + proc->declared = 1; + proc->imported = 1; + proc->flags = dcb.proc[n].data.Flags ; + + proc->params = dcb.proc[n].data.NParams ; + + if ( dcb.proc[n].data.SPrivate ) + { + pridata = calloc(dcb.proc[n].data.SPrivate, 1); + file_seek( fp, dcb.proc[n].data.OPrivate, SEEK_SET ) ; + file_read( fp, pridata, dcb.proc[n].data.SPrivate ) ; /* *** */ + } + + if ( dcb.proc[n].data.SPublic ) + { + pubdata = calloc(dcb.proc[n].data.SPublic, 1); + file_seek( fp, dcb.proc[n].data.OPublic, SEEK_SET ) ; + file_read( fp, pubdata, dcb.proc[n].data.SPublic ) ; /* *** */ + } + + if ( dcb.proc[n].data.NPriVars ) + { + prioffs = calloc( dcb.proc[n].data.NPriVars, sizeof( range ) ); + file_seek( fp, dcb.proc[n].data.OPriVars, SEEK_SET ) ; + dcb_vars_load( fp, proc->privars, proc->pridata, pridata, dcb.proc[n].data.NPriVars, &prioffs, dcb.proc[n].data.SPrivate ); + } + + if ( dcb.proc[n].data.NPubVars ) + { + puboffs = calloc( dcb.proc[n].data.NPubVars, sizeof( range ) ); + file_seek( fp, dcb.proc[n].data.OPubVars, SEEK_SET ) ; + dcb_vars_load( fp, proc->pubvars, proc->pubdata, pubdata, dcb.proc[n].data.NPubVars, &puboffs, dcb.proc[n].data.SPublic ); + } + + if ( dcb.proc[n].data.NPriStrings ) + { + int m, * sv = ( int * )calloc( dcb.proc[n].data.NPriStrings, sizeof( int ) ) ; + file_seek( fp, dcb.proc[n].data.OPriStrings, SEEK_SET ) ; + file_readUint32A( fp, (uint32_t *)sv, dcb.proc[n].data.NPriStrings ) ; + for ( m = 0; m < dcb.proc[n].data.NPriStrings; m++ ) varspace_varstring( proc->privars, get_new_off( sv[m], prioffs, dcb.proc[n].data.NPriVars )); + FREEM( sv ); + } + + if ( dcb.proc[n].data.NPubStrings ) + { + int m, * sv = ( int * )calloc( dcb.proc[n].data.NPubStrings, sizeof( int ) ) ; + file_seek( fp, dcb.proc[n].data.OPubStrings, SEEK_SET ) ; + file_readUint32A( fp, (uint32_t *)sv, dcb.proc[n].data.NPubStrings ) ; + for ( m = 0; m < dcb.proc[n].data.NPubStrings; m++ ) varspace_varstring( proc->pubvars, get_new_off( sv[m], puboffs, dcb.proc[n].data.NPubVars )); + FREEM( sv ); + } + + codeblock_adjust( &proc->code ); + + FREEM( pridata ) + FREEM( pubdata ) + FREEM( prioffs ) + FREEM( puboffs ) + } + + FREEM( sysproc_code_ref ); + FREEM( fileid ); + FREEM( newid ); + FREEM( stringid ); + FREEM( glodata ); + FREEM( locdata ); + FREEM( glovaroffs ); + FREEM( locvaroffs ); + + /* Recupera los ficheros incluídos */ +/* N/A + if ( dcb.data.NFiles ) + { + DCB_FILE dcbfile; + char fname[__MAX_PATH]; + + xfile_init( dcb.data.NFiles ); + file_seek( fp, dcb.data.OFilesTab, SEEK_SET ) ; + for ( n = 0 ; n < dcb.data.NFiles; n++ ) + { + file_read( fp, &dcbfile, sizeof( DCB_FILE ) ) ; + + ARRANGE_DWORD( &dcbfile.SName ); + ARRANGE_DWORD( &dcbfile.SFile ); + ARRANGE_DWORD( &dcbfile.OFile ); + + file_read( fp, &fname, dcbfile.SName ) ; + file_add_xfile( fp, NULL, dcbfile.OFile, fname, dcbfile.SFile ) ; + } + } +*/ + file_close( fp ); + + return 1 ; +} + +/* ---------------------------------------------------------------------- */ diff --git a/core/bgdc/src/error.c b/core/bgdc/src/error.c new file mode 100644 index 0000000..f18551e --- /dev/null +++ b/core/bgdc/src/error.c @@ -0,0 +1,204 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "bgdc.h" +#include "errors.h" +#include "files.h" + +/* Errors indexed table */ +struct _errindex errtable[10] ; + +/* + * Generate & populate the error table + */ + +void err_buildErrorTable() +{ + + file * fp ; + char fname[64] ; + char line[1024] ; + char * token ; + int code ; + int size ; + char * msg = NULL ; + struct _errmsg * err = NULL ; + int len; + + /* open the desired localized error file, check for existence if not open EN default */ + strcpy( fname, "msg/" ) ; + strcat( fname, langinfo ) ; + strcat( fname, ".msg" ) ; + + if ( !file_exists( fname ) ) strcpy( fname, "msg/en.msg" ) ; + + fp = file_open( fname, "r" ) ; + + if ( fp ) + { + while ( !file_eof( fp ) ) + { + len = file_qgets( fp, line, 1024 ); + if ( file_eof( fp ) ) break; + if ( !len ) continue; + /* Check for multiline... */ + if ( line[0] == '_' ) + { + /* must resize the string and concatenate */ + if ( err ) + { + size = strlen( err->msg ) + strlen( line ) ; + msg = ( char * )calloc( size, sizeof( char ) ) ; + strcpy( msg, err->msg ) ; + line[0] = '\n' ; + strcat( msg, line ) ; + free( err->msg ) ; + err->msg = strdup( msg ) ; + } + } + else + { + /* Check for comment */ + token = strtok( line, "#" ) ; + code = 0 ; + while ( token != NULL ) + { + /* don't process comments */ + if ( strlen( token ) == 0 ) break ; + if ( !code ) code = atoi( token ) ; + else msg = token ; + token = strtok( NULL, "#" ) ; + } + if ( code ) err = err_addError( code, msg ) ; + } + } + file_close( fp ) ; + } +} + +struct _errmsg * err_addError( int code, const char * msg ) +{ + + int idx ; + struct _errmsg * err ; + struct _errmsg * cerr ; + + /* build error object */ + + err = calloc( 1, sizeof( struct _errmsg ) ) ; + if ( err ) + { + err->code = code ; + err->msg = strdup( msg ) ; + err->prev = NULL ; + err->next = NULL ; + + /* determine index to use... */ + idx = code / 100 ; + + /* find insertion point */ + + cerr = errtable[idx].errlist ; + + if ( cerr ) + { + while ( cerr->next ) cerr = cerr->next ; + cerr->next = err ; + err->prev = cerr ; + } + else + { + errtable[idx].errlist = err ; + } + + errtable[idx].count++ ; + } + + return err ; +} + +void err_delError( struct _errmsg * err ) +{ + + int idx ; + + if ( !err ) return ; + + idx = err->code / 100 ; + + if ( err->next ) + { + err->next->prev = err->prev ; + } + + if ( err->prev ) + err->prev->next = err->next ; + else + errtable[idx].errlist = err->next ; + + free( err->msg ) ; + free( err ) ; + + errtable[idx].count-- ; + +} + +void err_destroyErrorTable( void ) +{ + + int i ; + + for ( i = 0;i < 10;i++ ) + { + while ( errtable[i].count > 0 ) + { + err_delError( errtable[i].errlist ) ; + } + } +} + +const char * err_getErrorByCode( int code ) +{ + + int idx ; + struct _errmsg * err ; + + idx = code / 100 ; + + err = errtable[idx].errlist ; + + while ( err && err->code != code ) err = err->next ; + + if ( !err ) return 0 ; + + return err->msg ; +} diff --git a/core/bgdc/src/identifier.c b/core/bgdc/src/identifier.c new file mode 100644 index 0000000..8ecaf23 --- /dev/null +++ b/core/bgdc/src/identifier.c @@ -0,0 +1,255 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "token.h" +#include "identifiers.h" +#include "compiler.h" + +/* ---------------------------------------------------------------------- */ +/* Gestor de identificadores */ +/* ---------------------------------------------------------------------- */ + +static identifier * identifier_hash[64] ; +static int identifier_code = 1 ; +int identifier_count = 0 ; + +int identifier_hash_value(const char * string) +{ + int t = 0 ; + const char * ptr = string ; + +/* while (*ptr) t = (t << 1) | *ptr++ ; */ + while (*ptr) t = (t << 3) | ( (*ptr++) & 0x07 ) ; /* Mejor dispersion en el hashing */ + + return (t & 63) ; +} + +identifier * identifier_first() +{ + int n ; + + for (n = 0 ; n < 64 ; n++) + { + if (identifier_hash[n]) + return identifier_hash[n] ; + } + return 0 ; +} + +identifier * identifier_next(identifier * id) +{ + int n ; + + if (id->next) return id->next ; + + n = identifier_hash_value(id->name) ; + for (n++ ; n < 64 ; n++) + { + if (identifier_hash[n]) + return identifier_hash[n] ; + } + return 0 ; +} + +void identifier_init() +{ + int i ; + + for (i = 0 ; i < 64 ; i++) identifier_hash[i] = 0 ; + + identifier_count = 0 ; + identifier_code = 1 ; +} + +void identifier_dump() +{ + int i, ii ; + identifier * ptr ; + + printf("\n---- %d identifiers ----\n\n", identifier_count) ; + for (i = 0 ; i < 64 ; i++) + { + ptr = identifier_hash[i] ; + ii = 0; + while (ptr) + { + ii++; + printf("%4d: %-32s [%04d] [%3d]\n", ptr->code, ptr->name, i, ii) ; + ptr = ptr->next ; + } + } +} + +int identifier_add_as(const char * string, int code) +{ + int hash = identifier_hash_value(string) ; + identifier * w = (identifier *)calloc(1, sizeof(identifier)) ; + + if (!w) + { + fprintf(stdout, "identifier_add: out of memory\n") ; + exit(1); + } + + w->name = strdup(string) ; + if (!w->name) + { + fprintf(stdout, "identifier_add: out of memory\n") ; + exit(1); + } + w->line = line_count ; /* Save First appearance */ + w->f = current_file ; /* Save File info */ + w->code = code ; + w->next = identifier_hash[hash] ; + identifier_hash[hash] = w ; + identifier_count++ ; + + return 1 ; +} + +int identifier_add(const char * string) +{ + int code = identifier_code++ ; + if (!identifier_add_as(string, code)) return 0 ; + return code ; +} + +int identifier_search(const char * string) +{ + int hash = identifier_hash_value(string) ; + identifier * ptr = identifier_hash[hash] ; + + while (ptr) + { + if (!ptr->name) return 0; + if (ptr->name[0] == *string) + { + if (strcmp(string, ptr->name) == 0) break ; + } + ptr = ptr->next ; + } + return ptr ? ptr->code : 0 ; +} + +/* Return line for the identifier */ +int identifier_line(int code) +{ + int i ; + identifier * ptr ; + + for (i = 0 ; i < 64 ; i++) + { + ptr = identifier_hash[i] ; + while (ptr) + { + if (ptr->code == code) { + return ptr->line ; + } + ptr = ptr->next ; + } + } + return 0 ; +} + +/* Return file for the identifier */ +int identifier_file(int code) +{ + int i ; + identifier * ptr ; + + for (i = 0 ; i < 64 ; i++) + { + ptr = identifier_hash[i] ; + while (ptr) + { + if (ptr->code == code) { + return ptr->f ; + } + ptr = ptr->next ; + } + } + return 0 ; +} + +const char * identifier_name(int code) +{ + int i ; + identifier * ptr ; + + for (i = 0 ; i < 64 ; i++) + { + ptr = identifier_hash[i] ; + while (ptr) + { + if (ptr->code == code) { + return ptr->name ; + } + ptr = ptr->next ; + } + } + return 0 ; +} + +int identifier_search_or_add(const char * string) +{ + int result ; + + result = identifier_search(string) ; + return result ? result : identifier_add(string) ; +} + +int identifier_next_code() +{ + return identifier_code ; +} + +int identifier_is_basic_type(int id) +{ + return ( + id == identifier_int || + id == identifier_short || + id == identifier_char || + id == identifier_dword || + id == identifier_word || + id == identifier_byte || + id == identifier_signed || + id == identifier_unsigned || + id == identifier_float || + id == identifier_string + ); +} + +int identifier_is_type(int id) +{ + return identifier_is_basic_type(id) || segment_by_name(id) != NULL; +} + diff --git a/core/bgdc/src/main.c b/core/bgdc/src/main.c new file mode 100644 index 0000000..6b80154 --- /dev/null +++ b/core/bgdc/src/main.c @@ -0,0 +1,496 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <time.h> + +#ifdef WIN32 +/* NEEDED FOR LOCALE DETECTION */ +#include <windows.h> +#include <windef.h> +#include <winnls.h> +#include "shlwapi.h" +#endif + +#include "bgdc.h" + +#include "errors.h" + +/* --------------------------------------------------------------------------- */ + +#define REMOVE_EXT(s) {char *p; if ((p = strrchr(s, '.')) && (p > strrchr(s, '\\') && p > strrchr(s, '/'))) * p = '\0';} + +extern int load_file( char * filename ); +extern void import_files( char * filename ); +extern void add_simple_define( char * macro, char *text ); +extern int dcb_options; + +extern int dcb_load_lib( const char * filename ); + +/* --------------------------------------------------------------------------- */ + +char langinfo[64]; + +extern int debug; +int autodeclare = 1; +int libmode = 0; + +char * main_path = NULL; + +char * appexename = NULL; +char * appexepath = NULL; +char * appexefullpath = NULL; + +/* --------------------------------------------------------------------------- */ + +static char timebuff[11]; /* YYYY/MM/DD or HH:MM:SS */ +static char _tmp[128]; + +/* --------------------------------------------------------------------------- */ + +int main( int argc, char *argv[] ) +{ + time_t curtime; + struct tm *loctime; + int value, code; + char * d, *d1; + + char * sourcefile = 0; + char basepathname[__MAX_PATH] = ""; + char dcbname[__MAX_PATH] = ""; + char stubname[__MAX_PATH] = ""; + char importname[__MAX_PATH] = ""; + char compilerimport[__MAX_PATH] = ""; + int i, j; + char *ptr; + + /* get my executable name */ + ptr = argv[0] + strlen( argv[0] ); + while ( ptr > argv[0] && ptr[-1] != '\\' && ptr[-1] != '/' ) ptr-- ; + appexename = strdup( ptr ); + + /* get executable full pathname */ + appexefullpath = getfullpath( argv[0] ); + if ( ( !strchr( argv[0], '\\' ) && !strchr( argv[0], '/' ) ) && !file_exists( appexefullpath ) ) + { + char *p = whereis( appexename ); + if ( p ) + { + char * tmp = calloc( 1, strlen( p ) + strlen( appexename ) + 2 ); + free( appexefullpath ); + sprintf( tmp, "%s/%s", p, appexename ); + appexefullpath = getfullpath( tmp ); + free( tmp ); + } + } + + /* get pathname of executable */ + ptr = strstr( appexefullpath, appexename ); + appexepath = calloc( 1, ptr - appexefullpath + 1 ); + strncpy( appexepath, appexefullpath, ptr - appexefullpath ); + + printf( BGDC_VERSION "\n" + "Bennu Game Development Compiler\n" + "\n" + "Copyright (c) 2006-2016 SplinterGU (Fenix/BennuGD)\n" + "Copyright (c) 2002-2006 Fenix Team (Fenix)\n" + "Copyright (c) 1999-2002 José Luis Cebrián Pagüe (Fenix)\n" + "\n" ); + + /* Default lang to EN */ + strcpy( langinfo, "EN" ); + /* LANG detect */ +#ifdef WIN32 + GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SABBREVCTRYNAME, langinfo, 64 ); + strlwr( langinfo ); +#else + if ( getenv( "LANG" ) != NULL && strlen( getenv( "LANG" ) ) >= 2 ) + strcpy( langinfo, getenv( "LANG" ) ); +#endif + langinfo[2] = 0; + + srand( time( NULL ) ); + + /* build error messages list */ + err_buildErrorTable(); + + init_c_type(); + identifier_init(); + constants_init(); + string_init(); + compile_init(); + + mainproc = procdef_new( procdef_getid(), identifier_search_or_add( "MAIN" ) ) ; + + /* Init vars */ + + char tmp_version[ 32 ]; + sprintf( tmp_version, "\"%s\"", VERSION ); + add_simple_define( "COMPILER_VERSION", tmp_version ); + add_simple_define( "__VERSION__", tmp_version ); + + curtime = time( NULL ); /* Get the current time. */ + loctime = localtime( &curtime ); /* Convert it to local time representation. */ + + strftime( timebuff, sizeof( timebuff ), "%Y/%m/%d", loctime ); + value = string_new( timebuff ); + code = identifier_search_or_add( "__DATE__" ) ; + constants_add( code, typedef_new( TYPE_STRING ), value ) ; + + strftime( timebuff, sizeof( timebuff ), "%H:%M:%S", loctime ); + value = string_new( timebuff ); + code = identifier_search_or_add( "__TIME__" ) ; + constants_add( code, typedef_new( TYPE_STRING ), value ) ; +/* + value = string_new( VERSION ); + code = identifier_search_or_add( "__VERSION__" ) ; + constants_add( code, typedef_new( TYPE_STRING ), value ) ; + code = identifier_search_or_add( "COMPILER_VERSION" ) ; + constants_add( code, typedef_new( TYPE_STRING ), value ) ; +*/ + strcpy( _tmp, VERSION ); + d = strchr( _tmp, '.' ); *d = '\0'; add_simple_define( "__BGD__", _tmp ); + d1 = d + 1; d = strchr( d1, '.' ); *d = '\0'; add_simple_define( "__BGD_MINOR__", d1 ); + d1 = d + 1; add_simple_define( "__BGD_PATCHLEVEL__", d1 ); + + memset( &dcb, 0, sizeof( dcb ) ); + + core_init(); + sysproc_init(); + + /* Get command line parameters */ + + for ( i = 1 ; i < argc ; i++ ) + { + if ( argv[i][0] == '-' ) + { + if ( !strcmp( argv[i], "--pedantic" ) ) + { + autodeclare = 0 ; + continue; + } + + if ( !strcmp( argv[i], "--libmode" ) ) + { + libmode = 1 ; + continue; + } + + j = 1; + while ( argv[i][j] ) + { + if ( argv[i][j] == 'd' ) + { + if ( argv[i][j + 1] >= '0' && argv[i][j + 1] <= '9' ) + { + debug = atoi( &argv[i][j + 1] ); + } + else + { + debug = 1; + } + } + + if ( argv[i][j] == 'o' ) + { + if ( argv[i][j + 1] ) + strncpy( dcbname, &argv[i][j + 1], sizeof( dcbname ) ); + else if ( argv[i + 1] && argv[i + 1][0] != '-' ) + strncpy( dcbname, argv[++i], sizeof( dcbname ) ); + break; + } + + if ( argv[i][j] == 'c' ) dos_chars = 1; + + if ( argv[i][j] == 'a' ) autoinclude = 1; + + if ( argv[i][j] == 'g' ) dcb_options |= DCB_DEBUG; + + if ( argv[i][j] == 'p' ) autodeclare = 0 ; + + if ( argv[i][j] == 's' ) + { + /* -s "stub": Use a stub */ + + if ( argv[i][j + 1] ) + strncpy( stubname, &argv[i][j + 1], __MAX_PATH ); + else if ( argv[i + 1] && argv[i + 1][0] != '-' ) + strncpy( stubname, argv[++i], __MAX_PATH ); + break; + } + + if ( argv[i][j] == 'f' ) + { + /* -f "file": Embed a file to the DCB */ + + if ( argv[i][j + 1] ) + dcb_add_file( &argv[i][j + 1] ); + else while ( argv[i + 1] ) + { + if ( argv[i + 1][0] == '-' ) break; + dcb_add_file( argv[i + 1] ); + i++; + } + break; + } + + if ( argv[i][j] == 'i' ) + { + /* -i "path": add a file to the path for include files */ + + if ( argv[i][j + 1] == 0 ) + { + if ( i == argc - 1 ) + { + printf( MSG_DIRECTORY_MISSING "\n" ); + exit( 1 ); + } + file_addp( argv[i + 1] ); + i++; + break; + } + file_addp( &argv[i][j + 1] ); + break; + } + + if ( argv[i][j] == 'l' ) + { + /* -lLANG: Set the language for errors and messages */ + + if ( argv[i][j + 1] == 0 ) + { + if ( i != argc - 1 ) + { + strcpy( langinfo, argv[i + 1] ); + } + i++; + break; + } + strcpy( langinfo, &argv[i][j + 1] ); + break; + } + + if ( argv[i][j] == 'D' ) + { + char * macro = NULL ; + char * text = NULL ; + + /* -D<macro>=<text> */ + + if ( argv[i][j + 1] ) + { + macro = strdup( &argv[i][j + 1] ); + } + else + { + if ( argv[i + 1][0] == '-' ) break; + macro = strdup( argv[i + 1] ); + i++; + } + + if (( text = strchr( macro, '=' ) ) ) + { + * text = '\0'; + text++; + } + else + { + text = ""; + } + + add_simple_define( macro, text ); + free( macro ); + break; + } + + if ( argv[i][j] == 'C' ) + { + if ( argv[i][j + 1] == 'a' ) autodeclare = 1 ; + break; + } + + if ( argv[i][j] == 'L' ) + { + int r = 1; + char * f; + if ( argv[i][j + 1] ) + r = dcb_load_lib( ( f = &argv[i][j + 1] ) ); + else if ( argv[i + 1] && argv[i + 1][0] != '-' ) + { + r = dcb_load_lib( ( f = argv[i + 1] ) ); + i++; + } + + switch ( r ) + { + case 0: + printf( "ERROR: %s doesn't exist or isn't version DCB compatible\n", f ) ; + exit( -1 ); + + case -1: + printf( "ERROR: %s isn't 7.10 DCB version, you need a 7.10 version or greater for use this feature\n", f ) ; + exit( -1 ); + } + break; + } + + j++; + } + } + else + { +/* + if ( sourcefile ) + { + printf( MSG_TOO_MANY_FILES "\n" ); + return 0; + } +*/ + char * p, * pathend = NULL; + + sourcefile = argv[i]; + p = main_path = strdup( argv[i] ); + while ( p && *p ) + { + if ( *p == ':' || *p == '\\' || *p == '/' ) pathend = p; + p++; + } + if ( pathend ) + { + *( pathend + 1 ) = '\0'; + file_addp( main_path ); + } + else + { + free( main_path ); + main_path = getcwd(malloc(__MAX_PATH), __MAX_PATH); + strcat(main_path, PATH_SEP); + } + + /* Files names */ + + strcpy( basepathname, sourcefile ); + REMOVE_EXT( basepathname ); + + /* Default compiler imports */ + strcpy( compilerimport, argv[0] ); +#ifdef WIN32 + REMOVE_EXT( compilerimport ); +#endif + strcat( compilerimport, ".imp" ); + import_files( compilerimport ); + strcat( compilerimport, "ort" ); /* name.import */ + import_files( compilerimport ); + + /* Project imports */ + strcpy( importname, basepathname ); strcat( importname, ".imp" ); + import_files( importname ); + + strcat( importname, "ort" ); /* name.import */ + import_files( importname ); + + /* Load Main Source File */ + load_file( sourcefile ); + + if ( !dcbname[0] ) + { + strcpy( dcbname, basepathname ); strcat( dcbname, !libmode ? ".dcb" : ".dcl" ); + } + } + } + + if ( !sourcefile ) + { + printf( MSG_USING + MSG_OPTION_D + MSG_OPTIONS + MSG_LICENSE, argv[0] ); + return 0; + } + + compile_program(); + + if ( stubname[0] != 0 ) + { + if ( !file_exists( stubname ) ) + { +#ifdef WIN32 + char exepath[__MAX_PATH]; + + GetModuleFileName( NULL, exepath, sizeof( exepath ) ); + PathRemoveFileSpec( exepath ); + strcat( exepath, "\\" ); + memmove( stubname + strlen( exepath ), stubname, strlen( stubname ) + 1 ); + memcpy( stubname, exepath, strlen( exepath ) ); +#else + const char * ptr = argv[0] + strlen( argv[0] ); + while ( ptr > argv[0] && *ptr != '\\' && *ptr != '/' ) ptr--; + if ( *ptr == '\\' || *ptr == '/' ) ptr++; + if ( ptr > argv[0] ) + { + memmove( stubname + ( ptr - argv[0] ), stubname, strlen( stubname ) + 1 ); + memcpy( stubname, argv[0], ptr - argv[0] ); + } +#endif + if ( !file_exists( stubname ) ) + { +#ifdef WIN32 + strcat( stubname, ".exe" ); + if ( !file_exists( stubname ) ) + { +#endif + compile_error( "Can't open stub file %s", stubname ); +#ifdef WIN32 + return -1; + } +#endif + + } + } + + REMOVE_EXT( dcbname ); +#ifdef WIN32 + strcat( dcbname, ".exe" ); +#endif + dcb_save( dcbname, dcb_options, stubname ); + } + else + { + dcb_save( dcbname, dcb_options, NULL ); + } + + /* destroy error messages list */ + err_destroyErrorTable(); + + return 1; +} + +/* --------------------------------------------------------------------------- */ diff --git a/core/bgdc/src/main_core.c b/core/bgdc/src/main_core.c new file mode 100644 index 0000000..4040e66 --- /dev/null +++ b/core/bgdc/src/main_core.c @@ -0,0 +1,134 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "bgdc.h" + +/* ----------------------------------------------------------------------- */ +/* Este módulo contiene las definiciones de constantes, globales y locales */ +/* predefinidos, así como el código que los carga y define cada una de las */ +/* funciones del sistema (es llamado antes de empezar a compilar). */ +/* ----------------------------------------------------------------------- */ + +static struct +{ + char * name ; + int type ; + int code ; +} +constants_def[] = +{ + { "STATUS_DEAD" , TYPE_DWORD, STATUS_DEAD }, + { "STATUS_KILLED" , TYPE_DWORD, STATUS_KILLED }, + { "STATUS_RUNNING" , TYPE_DWORD, STATUS_RUNNING }, + { "STATUS_SLEEPING" , TYPE_DWORD, STATUS_SLEEPING }, + { "STATUS_FROZEN" , TYPE_DWORD, STATUS_FROZEN }, + { "STATUS_WAITING" , TYPE_DWORD, STATUS_WAITING_MASK }, + + { "NULL" , TYPE_DWORD, 0 }, + + { "FALSE" , TYPE_DWORD, 0 }, + { "TRUE" , TYPE_DWORD, !0 }, + + { "OS_WIN32" , TYPE_DWORD, OS_WIN32 }, + { "OS_LINUX" , TYPE_DWORD, OS_LINUX }, + { "OS_BEOS" , TYPE_DWORD, OS_BEOS }, + { "OS_MACOS" , TYPE_DWORD, OS_MACOS }, + { "OS_GP32" , TYPE_DWORD, OS_GP32 }, + { "OS_DC" , TYPE_DWORD, OS_DC }, + { "OS_BSD" , TYPE_DWORD, OS_BSD }, + { "OS_GP2X" , TYPE_DWORD, OS_GP2X }, + { "OS_GP2X_WIZ" , TYPE_DWORD, OS_GP2X_WIZ }, + { "OS_CAANOO" , TYPE_DWORD, OS_CAANOO }, + { "OS_DINGUX_A320" , TYPE_DWORD, OS_DINGUX_A320 }, + { "OS_WII" , TYPE_DWORD, OS_WII }, + { "OS_ANDROID" , TYPE_DWORD, OS_ANDROID }, + { "OS_IOS" , TYPE_DWORD, OS_IOS }, + + { "MIN_INT" , TYPE_INT , -2147483647L - 1 }, + { "MAX_INT" , TYPE_INT , 2147483647L }, + { "MIN_DWORD" , TYPE_DWORD, 0 }, + { "MAX_DWORD" , TYPE_DWORD, 0xffffffff }, + + { "MIN_SHORT" , TYPE_SHORT, -32768 }, + { "MAX_SHORT" , TYPE_SHORT, 32767 }, + { "MIN_WORD" , TYPE_WORD , 0 }, + { "MAX_WORD" , TYPE_WORD , 0xffff }, + + { "MIN_SBYTE" , TYPE_SBYTE, -128 }, + { "MAX_SBYTE" , TYPE_SBYTE, 127 }, + { "MIN_BYTE" , TYPE_BYTE , 0 }, + { "MAX_BYTE" , TYPE_BYTE , 0xff }, + + { "MIN_CHAR" , TYPE_BYTE , 0 }, + { "MAX_CHAR" , TYPE_BYTE , 0xff }, + + { NULL , 0 , 0 } +} ; + +static char * globals_def = + "argc;\n" + "string argv[32];\n" + "os_id = -1;\n"; + +static char * locals_def = + "id;\n" + "STRUCT reserved\n" + "process_type;\n" + "frame_percent;\n" + "status = STATUS_RUNNING;\n" + "saved_status = STATUS_RUNNING;\n" + "saved_priority;\n" + "END\n" + + "father;\n" + "son;\n" + "smallbro;\n" + "bigbro;\n" + "priority;\n"; + +void core_init() +{ + int i = 0, code ; + + while ( constants_def[i].name ) + { + code = identifier_search_or_add( constants_def[i].name ) ; + constants_add( code, typedef_new( constants_def[i].type ), constants_def[i].code ) ; + i++ ; + } + + token_init( globals_def, -1 ) ; + compile_varspace( &global, globaldata, 1, 1, 0, NULL, DEFAULT_ALIGNMENT, 0 ) ; + + token_init( locals_def, -1 ) ; + compile_varspace( &local, localdata, 1, 1, 0, NULL, DEFAULT_ALIGNMENT, 0 ) ; +} diff --git a/core/bgdc/src/procedure.c b/core/bgdc/src/procedure.c new file mode 100644 index 0000000..09ca829 --- /dev/null +++ b/core/bgdc/src/procedure.c @@ -0,0 +1,192 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#ifdef TARGET_BEOS +#include <posix/assert.h> +#else +#include <assert.h> +#endif + +#include "bgdc.h" + +/* ---------------------------------------------------------------------- */ +/* Gestor de procesos y bloques de código. Este módulo contiene funciones */ +/* de utilidad para crear procesos y bloques de código así como otras que */ +/* se emplean durante y después del compilado. */ +/* ---------------------------------------------------------------------- */ + +PROCDEF * mainproc = 0 ; +int procdef_count = 0 ; + +int procdef_maxid = -1 ; +PROCDEF ** procs = 0 ; +int procs_allocated = 0 ; + +int procdef_getid() +{ + return ++procdef_maxid ; +} + +PROCDEF * procdef_new (int typeid, int id) +{ + PROCDEF * proc = (PROCDEF *) calloc (1, sizeof(PROCDEF)) ; + int n ; + + if (!proc) + { + fprintf (stdout, "procdef_new: out of memory\n") ; + exit (1) ; + } + + proc->pridata = segment_new() ; + proc->privars = varspace_new() ; + + /* (2006/11/19 23:15 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + proc->pubdata = segment_new() ; + proc->pubvars = varspace_new() ; + /* (2006/11/19 23:15 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + + proc->params = -1 ; + proc->defined = 0 ; + proc->declared = 0 ; + proc->type = TYPE_DWORD ; + proc->flags = 0 ; + proc->imported = 0 ; + + proc->sentence_count = 0 ; + proc->sentences = 0 ; + + if (typeid >= procs_allocated) + { + procs_allocated = typeid + 15 ; + procs = (PROCDEF **) realloc (procs, sizeof(PROCDEF **) * procs_allocated) ; + if (!procs) + { + fprintf (stdout, "procdef_new: out of memory\n") ; + exit (1) ; + } + } + proc->typeid = typeid ; + proc->identifier = id ; + procs[typeid] = proc ; + + for (n = 0 ; n < MAX_PARAMS ; n++) + proc->paramtype[n] = TYPE_UNDEFINED ; + + proc->exitcode = 0 ; + proc->errorcode = 0 ; + + codeblock_init (&proc->code) ; + procdef_count++ ; + return proc ; +} + +PROCDEF * procdef_search (int id) +{ + int n ; + + for (n = 0 ; n <= procdef_maxid; n++) + if (procs[n]->identifier == id) return procs[n] ; + + return 0 ; +} + +PROCDEF * procdef_search_by_codeblock (CODEBLOCK * p) +{ + int n ; + + for (n = 0 ; n <= procdef_maxid; n++) + if (&procs[n]->code == p) return procs[n] ; + + return 0 ; +} + +PROCDEF * procdef_get (int typeid) +{ + return procs_allocated > typeid ? procs[typeid] : 0 ; +} + +void procdef_destroy (PROCDEF * proc) +{ + varspace_destroy (proc->privars) ; + segment_destroy (proc->pridata) ; + + /* (2006/11/20 01:09 GMT-03:00, Splinter - jj_arg@yahoo.com) */ + varspace_destroy (proc->pubvars); + segment_destroy (proc->pubdata) ; + + procs[proc->typeid] = 0 ; + free (proc->code.data) ; + free (proc->code.loops) ; + free (proc->code.labels) ; + free (proc) ; + + procdef_count-- ; +} + + +/* Realiza acciones posteriores al compilado sobre el código: + * - Convierte saltos de código de etiqueta a offset + * - Convierte identificador de procesos en CALL o TYPE a typeid */ + +void program_postprocess () +{ + int n ; + for (n = 0; n <= procdef_maxid; n++) codeblock_postprocess (&procs[n]->code) ; +} + +void program_dumpprocesses() +{ + int n; + for (n = 0; n <= procdef_maxid; n++) procdef_dump( procs[n] ); +} + +void procdef_dump( PROCDEF * proc ) +{ + printf( "\n\n---------- Process %d (%s)\n\n", proc->typeid, identifier_name( proc->identifier ) ) ; + + if ( proc->privars->count ) + { + printf( "---- Private variables\n" ) ; + varspace_dump( proc->privars, 0 ) ; + printf( "\n" ) ; + } + + if ( proc->pubvars->count ) + { + printf( "---- Public variables\n" ) ; + varspace_dump( proc->pubvars, 0 ) ; + printf( "\n" ) ; + } + + /* segment_dump (proc->pridata) ; */ + codeblock_dump( &proc->code ) ; +} diff --git a/core/bgdc/src/resource.h b/core/bgdc/src/resource.h new file mode 100644 index 0000000..2bcfd14 --- /dev/null +++ b/core/bgdc/src/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by bgdc.rc +// +#define IDI_ICON1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/core/bgdc/src/segment.c b/core/bgdc/src/segment.c new file mode 100644 index 0000000..93e5348 --- /dev/null +++ b/core/bgdc/src/segment.c @@ -0,0 +1,233 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "bgdc.h" + +static int max_id = 0 ; +static int free_id[1024] ; +static int free_count = 0 ; + +static segment ** segments = 0 ; +static int segments_reserved = 0 ; + +segment * globaldata, * localdata ; + +static void segment_register (segment * s) +{ + /* Saves the segment in the global array */ + + if (!segments) + { + segments = (segment **)calloc (16, sizeof(segment *)) ; + segments_reserved = 16 ; + } + if (segments_reserved <= s->id) + { + segments_reserved = s->id + 16 ; + segments = (segment **)calloc (segments_reserved, sizeof(segment *)) ; + } + if (!segments) compile_error ("segment_new: out of memory\n") ; + segments[s->id] = s ; +} + +segment * segment_new () +{ + /* Creates the segment */ + + segment * s = (segment *)calloc (1, sizeof(segment)) ; + if (!s) compile_error ("segment_new: out of memory\n") ; + + if (free_count) + s->id = free_id[--free_count] ; + else + s->id = max_id++ ; + + s->current = 0 ; + s->reserved = 128 ; + + s->bytes = (int *) calloc(s->reserved, sizeof(char)) ; /* Tamaño en bytes */ + if (!s->bytes) compile_error ("segment_new: out of memory\n") ; + + segment_register (s) ; + return s ; +} + +segment * segment_duplicate (segment * b) +{ + segment * s = (segment *)calloc (1, sizeof(segment)) ; + if (!s) compile_error ("segment_new: out of memory\n") ; + + if (free_count) + s->id = free_id[--free_count] ; + else + s->id = max_id++ ; + + s->current = b->current ; + s->reserved = b->reserved ; + + s->bytes = (int *) calloc(s->reserved, sizeof(char)) ; /* Tamaño en bytes */ + if (!s->bytes) compile_error ("segment_new: out of memory\n") ; + memcpy (s->bytes, b->bytes, s->current) ; + + segment_register (s) ; + return s ; +} + +void segment_destroy (segment * s) +{ + segments[s->id] = 0 ; + if (free_count < 1024) free_id[free_count++] = s->id ; + + free (s->bytes) ; + free (s) ; +} + +void segment_alloc (segment * n, int count) +{ + n->reserved += count ; + n->bytes = realloc (n->bytes, n->reserved) ; + if (!n->bytes) compile_error ("segment_alloc: out of memory\n") ; +} + +int segment_add_as (segment * n, int32_t value, BASETYPE t) +{ + switch (t) + { + case TYPE_DWORD: + case TYPE_INT: + case TYPE_FLOAT: + case TYPE_STRING: + case TYPE_POINTER: + return segment_add_dword (n, (int32_t)value) ; + + case TYPE_WORD: + case TYPE_SHORT: + return segment_add_word (n, (int16_t)value) ; + + case TYPE_BYTE: + case TYPE_SBYTE: + case TYPE_CHAR: + return segment_add_byte (n, (int8_t)value) ; + + default: + compile_error (MSG_INCOMP_TYPE) ; + return 0 ; + } +} + +int segment_add_from (segment * n, segment * s) +{ + if (n->current+s->current >= n->reserved) segment_alloc (n, s->current) ; + memcpy ((uint8_t *)n->bytes + n->current, s->bytes, s->current) ; + return n->current += s->current ; +} + +int segment_add_byte (segment * n, int8_t value) +{ + if (n->current+1 >= n->reserved) segment_alloc (n, 64) ; + *((int8_t *)n->bytes + n->current) = value ; + return n->current ++ ; +} + +int segment_add_word (segment * n, int16_t value) +{ + if (n->current+2 >= n->reserved) segment_alloc (n, 64) ; + *(int16_t *)((uint8_t *)n->bytes + n->current) = value ; + n->current += 2 ; + return n->current - 2 ; +} + +int segment_add_dword (segment * n, int32_t value) +{ + if (n->current+4 >= n->reserved) segment_alloc (n, 64) ; + *(int32_t *)((uint8_t *)n->bytes + n->current) = value ; + n->current += 4 ; + return n->current - 4 ; +} + +segment * segment_get (int id) +{ + return segments[id] ; +} + +void segment_dump (segment * s) +{ + int i ; + + for (i = 0 ; i < s->current ; i++) printf ("%02X ", *((uint8_t*)s->bytes + i)) ; + printf ("\n") ; +} + +void segment_copy(segment *s, int base_offset, int total_length) +{ + if (s->reserved < s->current + total_length) segment_alloc (s, total_length) ; + memcpy ((uint8_t *)s->bytes + s->current, (uint8_t *)s->bytes + base_offset, total_length) ; + s->current += total_length ; +} + +VARIABLE * variable_new () +{ + VARIABLE * v = (VARIABLE *) calloc (1, sizeof(VARIABLE)) ; + + if (!v) compile_error ("variable_new: out of memory\n") ; + return v; +} + +/* Segmentos nombrados */ + +static segment ** named_segs = NULL ; +static int * named_codes = NULL ; +static int named_count = 0 ; +static int named_reserved = 0; + +segment * segment_by_name (int code) +{ + int n ; + + for (n = 0 ; n < named_count ; n++) + if (named_codes[n] == code) return named_segs[n] ; + return 0 ; +} + +void segment_name (segment * s, int code) +{ + if (named_count >= named_reserved) + { + named_reserved += 16; + named_segs = realloc(named_segs, named_reserved * sizeof (segment *)); + named_codes = realloc(named_codes, named_reserved * sizeof (int)); + if (!named_segs || !named_codes) compile_error ("segment_name: out of memory\n") ; + } + named_segs[named_count] = s ; + named_codes[named_count] = code ; + named_count++ ; +} diff --git a/core/bgdc/src/strings.c b/core/bgdc/src/strings.c new file mode 100644 index 0000000..1939862 --- /dev/null +++ b/core/bgdc/src/strings.c @@ -0,0 +1,241 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef TARGET_BEOS +#include <posix/assert.h> +#else +#include <assert.h> +#endif + +#include "bgdc.h" + +/* ---------------------------------------------------------------------- */ +/* Gestor de cadenas */ +/* ---------------------------------------------------------------------- */ + +char * string_mem = 0 ; +int string_allocated = 0 ; +int string_used = 0 ; + +int * string_offset = 0 ; +int string_max = 0 ; +int string_count = 0 ; + +int autoinclude = 0 ; + +void string_init() +{ + string_mem = ( char * ) calloc( 4096, sizeof( char ) ) ; + string_allocated = 4096 ; + string_used = 1 ; + string_count = 1 ; + string_offset = ( int * ) calloc( 1024, sizeof( int ) ) ; + string_max = 1024 ; + string_mem[ 0 ] = 0 ; + string_offset[ 0 ] = 0 ; +} + +void string_alloc( int bytes ) +{ + string_mem = ( char * ) realloc( string_mem, string_allocated += bytes ) ; + if ( !string_mem ) + { + fprintf( stdout, "string_alloc: out of memory\n" ) ; + exit( 1 ) ; + } +} + +void string_dump( void ( *wlog )( const char *fmt, ... ) ) +{ + int i ; + printf( "\n---- %d strings ----\n\n", string_count ) ; + for ( i = 0 ; i < string_count ; i++ ) + printf( "%4d: %s\n", i, string_mem + string_offset[ i ] ) ; +} + +int string_new( const char * text ) +{ + int len = strlen( text ) + 1 ; + int i; + + /* Reuse strings */ + for ( i = 0; i < string_count; i++ ) if ( !strcmp( text, string_mem + string_offset[ i ] ) ) return i; + + if ( string_count == string_max ) + { + string_max += 1024 ; + string_offset = ( int * ) realloc( string_offset, string_max * sizeof( int ) ) ; + if ( string_offset == 0 ) + { + fprintf( stdout, "Too many strings\n" ) ; + exit( 1 ) ; + } + } + + while ( string_used + len >= string_allocated ) string_alloc( 1024 ) ; + + string_offset[ string_count ] = string_used ; + strcpy( string_mem + string_used, text ) ; + string_used += len ; + return string_count++ ; +} + + +char * validchars = "\\/."; +char * invalidchars = \ + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" \ + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" \ + "*?\"<>|"; + +int check_for_valid_pathname( char * pathname ) +{ + int n, l; + + if ( !pathname || ( l = strlen( pathname ) ) > __MAX_PATH ) return 0; + +#if WIN32 + /* Only ':' with this sintax: "L:..." */ + if ( pathname[ 0 ] == ':' || ( l > 2 && strchr( pathname + 2, ':' ) ) ) return 0; +#endif + + /* Some invalid character? */ + for ( n = 0; n < strlen( invalidchars ); n++ ) + if ( strchr( pathname, invalidchars[ n ] ) ) return 0; + + return 1; +} + +int no_include_this_file = 0; + +int string_compile( const char ** source ) +{ + char c = *( *source ) ++, conv ; + const char * ptr ; + int string_used_back = string_used; + + if ( string_count == string_max ) + { + string_max += 1024 ; + string_offset = ( int * ) realloc( string_offset, string_max * sizeof( int ) ) ; + if ( string_offset == 0 ) + { + fprintf( stdout, "Too many strings\n" ) ; + exit( 1 ) ; + } + } + + string_offset[ string_count ] = string_used ; + + while ( *( *source ) ) + { + if ( *( *source ) == c ) /* Termina la string? */ + { + ( *source ) ++ ; + if ( *( *source ) == c ) /* Comienza una nueva? (esto es para strings divididas) */ + { + ( *source ) ++ ; + } + else + { + /* Elimino todos los espacios para buscar si hay otra string, esto es para strings divididas */ + ptr = ( *source ) ; + while ( ISSPACE( *ptr ) ) + { + if ( *ptr == '\n' ) line_count++ ; + ptr++ ; + } + /* Si despues de saltar todos los espacios, no tengo un delimitador de string, salgo */ + if ( *ptr != c ) + { + ( *source ) = ptr; /* Fix: Splinter, por problema con numeracion de lineas */ + break ; + } + + /* Obtengo delimitador de string, me posiciono en el caracter siguiente, dentro de la string */ + ( *source ) = ptr + 1 ; + continue ; + } + } + else if ( *( *source ) == '\n' ) + { + line_count++ ; + string_mem[ string_used++ ] = '\n' ; + + ( *source ) ++ ; + } + else + { +#ifdef __USE_C_STRING_ESCAPE + if ( *( *source ) == '\\' && *( *source + 1 ) == c ) ( *source ) ++ ; +#endif + conv = convert( *( *source ) ) ; + string_mem[ string_used++ ] = conv ; + + ( *source ) ++ ; + } + + if ( string_used >= string_allocated ) + string_alloc( 1024 ) ; + } + + string_mem[ string_used++ ] = 0 ; + + int i; + + /* Reuse strings */ + + for ( i = 0; i < string_count; i++ ) + { + if ( !strcmp( string_mem + string_used_back, string_mem + string_offset[ i ] ) ) + { + string_used = string_used_back; + return i; + } + } + + if ( string_used >= string_allocated ) string_alloc( 1024 ) ; + + /* Hack: añade el posible fichero al DCB */ + + if ( !no_include_this_file && autoinclude && check_for_valid_pathname( string_mem + string_offset[ string_count ] ) ) + dcb_add_file( string_mem + string_offset[ string_count ] ) ; + + no_include_this_file = 0; + + return string_count++ ; +} + +const char * string_get( int code ) +{ + assert( code < string_count && code >= 0 ) ; + return string_mem + string_offset[ code ] ; +} + diff --git a/core/bgdc/src/sysstub.c b/core/bgdc/src/sysstub.c new file mode 100644 index 0000000..853fb20 --- /dev/null +++ b/core/bgdc/src/sysstub.c @@ -0,0 +1,239 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "bgdc.h" + +/* Fast access sysproc list, by identifier code */ + +SYSPROC ** sysproc_list = NULL ; +int sysproc_maxid = 0 ; + +/* Este fichero contiene sólo las definiciones de las funciones del sistema */ + +#define SYSMACRO(a) 0 +#include "sysprocs.h" + +/* + * FUNCTION : sysproc_init + * + * Initilize the module + * + * PARAMS: + * none + * + * RETURN VALUE: + * none + */ + +void sysproc_init( void ) +{ +} + +/* + * FUNCTION : sysproc_add + * + * Add a new system function to the internal system function list + * + * PARAMS: + * name Name of the process + * paramtypes String representation of the parameter + * type Type of the returning value + * func Pointer to the function itself or a stub + * + * RETURN VALUE: + * Identifier code allocated for the function + */ + +int sysproc_add( char * name, char * paramtypes, int type, void * func ) +{ + static SYSPROC * sysproc_new = 0 ; + static int sysproc_maxcode = 0 ; + static int sysproc_count = 0 ; + + if ( !sysproc_new ) + { + sysproc_new = sysprocs ; + while ( sysproc_new->name ) + { + if ( sysproc_new->code > sysproc_maxcode ) sysproc_maxcode = sysproc_new->code ; + sysproc_new++ ; + sysproc_count++ ; + } + } + + if ( sysproc_count >= MAX_SYSPROCS ) compile_error( MSG_TOO_MANY_SYSPROCS ) ; + + sysproc_maxcode++; + + sysproc_new->code = sysproc_maxcode ; + sysproc_new->name = name ; + sysproc_new->paramtypes = paramtypes ; + sysproc_new->params = strlen( paramtypes ) ; + sysproc_new->type = type ; + sysproc_new->id = identifier_search_or_add( name ) ; + sysproc_new->next = NULL ; + + sysproc_new++ ; + sysproc_count++ ; + + /* If the fast-access list is already filled, free it to fill it again + * in sysproc_get. We should add the new process to the list, but this + * is a very rare possibility and we're lazy */ + + if ( sysproc_list != NULL ) + { + free( sysproc_list ); + sysproc_list = NULL; + sysproc_maxid = 0; + } + + return sysproc_new->code ; +} + +/* + * FUNCTION : sysproc_get + * + * Search for a system function by name and return a pointer + * to the first ocurrence or NULL if none exists + * + * PARAMS: + * id Unique code of the identifier of the name + * + * RETURN VALUE: + * Pointer to the SYSPROC object or NULL if none exists + */ + +SYSPROC * sysproc_get( int id ) +{ + SYSPROC * s ; + + /* If the table is filled, get the process with direct access */ + + if ( id < sysproc_maxid ) return sysproc_list[id]; + + /* Fill the table */ + + if ( sysproc_list == NULL ) + { + /* Alloc IDs if necessary and get the maximum one */ + + for ( s = sysprocs ; s->name ; s++ ) + { + if ( s->id == 0 ) s->id = identifier_search_or_add( s->name ) ; + if ( s->id > sysproc_maxid ) sysproc_maxid = s->id; + + s->next = NULL; + } + + /* Alloc the table */ + + sysproc_maxid = (( sysproc_maxid + 1 ) & ~31 ) + 32; + sysproc_list = ( SYSPROC ** ) calloc( sysproc_maxid, sizeof( SYSPROC * ) ); + if ( sysproc_list == NULL ) abort(); + + /* Fill it */ + + for ( s = sysprocs ; s->name ; s++ ) + { + if ( s->id > 0 ) + { + s->next = sysproc_list[s->id]; + sysproc_list[s->id] = s; + } + } + + if ( id < sysproc_maxid ) return sysproc_list[id]; + } + + return NULL; +} + +/* + * FUNCTION : sysproc_getall + * + * Search for a system function by name and return a pointer + * to a zero-terminated table with pointers to all ocurrences. + * Up to 31 occurences can be found with this function. + * + * PARAMS: + * id Unique code of the identifier of the name + * + * RETURN VALUE: + * Pointer to a new SYSPROC table allocated with malloc() + * NULL if no process with this id exists + */ + +SYSPROC ** sysproc_getall( int id ) +{ + SYSPROC * s = sysproc_get( id ) ; + SYSPROC ** table; + int found = 0 ; + + if ( s == NULL ) return NULL; + + table = calloc( 32, sizeof( SYSPROC * ) ) ; + do + { + table[found++] = s; + s = s->next; + } + while ( s && found <= 31 ); + table[found] = NULL; + return table ; +} + +/* + * FUNCTION : sysproc_name + * + * Return the name of a given system function + * + * PARAMS: + * code Internal code of the function + * + * RETURN VALUE: + * Pointer to the name or NULL if it was not found + */ + +/* ---------------------------------------------------------------------- */ + +char * sysproc_name( int code ) +{ + SYSPROC * s = sysprocs ; + + while ( s->name ) + { + if ( s->code == code ) return s->name ; + s++ ; + } + return 0 ; +} + diff --git a/core/bgdc/src/token.c b/core/bgdc/src/token.c new file mode 100644 index 0000000..5d47b98 --- /dev/null +++ b/core/bgdc/src/token.c @@ -0,0 +1,1424 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +/* Pending: no newline at end of file */ + +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "bgdc.h" + + +/* ---------------------------------------------------------------------- */ +/* Tokenizador. La función token_next, ampliamente utilizada, recoge el */ +/* siguiente token (identificador, operador, etc) del código fuente, y */ +/* rellena la estructura global "token" con los datos del mismo. */ +/* ---------------------------------------------------------------------- */ + +int line_count = 0 ; /* Se pone a 0, ya que lo incremente con cada \n, y hasta no obtener un \n no se procesa la linea (Splinter) */ +int current_file = 0 ; + +static int prepro_sp = 0 ; +static int prepro_stack[1024] ; + +static int disable_prepro = 0 ; +static int disable_expand_defines = 0 ; +static int identifiers_as_strings = 0 ; + +struct _token token ; +struct _token token_prev ; +struct _token token_saved ; +static int use_saved = 0 ; + +typedef struct _define +{ + int code; + char * text; + int param_count; + int param_id[MAX_MACRO_PARAMS]; +} +DEFINE; + +static const char * source_ptr; +static char * source_start; +static const char * old_sources[MAX_SOURCES]; +static char * old_sources_start[MAX_SOURCES]; +static int old_line_counts[MAX_SOURCES]; +static int old_current_file[MAX_SOURCES]; +static int sources = 0; +static DEFINE * defines = NULL; +static int defines_allocated = 0; +static int defines_count = 0; +static int id_define; +static int id_undef; +static int id_ifdef; +static int id_ifndef; +static int id_endif; +static int id_else; +static int id_if; + +/* --------------------------------------------------------------------------- */ + +static int token_endfile(); + +/* ---------------------------------------------------------------------- */ + +#define SKIP_C89_COMMENTS \ + if (*source_ptr && *source_ptr == '/' && *(source_ptr + 1) == '*') { \ + * ((char *) source_ptr++) = ' '; * ((char *) source_ptr++) = ' '; \ + while (*source_ptr && (*source_ptr != '*' || *(source_ptr + 1) != '/')) { \ + if (*source_ptr == '\n') { line_count++; * ((char *) source_ptr++) = ' '; continue ;} \ + * ((char *) source_ptr++) = ' '; \ + } \ + if (*source_ptr == '*' && *(source_ptr + 1) == '/') { \ + * ((char *) source_ptr++) = ' '; * ((char *) source_ptr++) = ' '; \ + } \ + continue;\ + } + + +#define SKIP_C99_COMMENTS \ + if (*source_ptr && *source_ptr == '/' && *(source_ptr + 1) == '/') { \ + * ((char *) source_ptr++) = ' '; * ((char *) source_ptr++) = ' '; \ + while (*source_ptr && *source_ptr != '\n') { \ + if (*source_ptr == '\\' && *(source_ptr + 1) == '\n') { line_count++; * ((char *) source_ptr++) = ' ';} \ + * ((char *) source_ptr++) = ' '; \ + } \ + continue; \ + } + + +#define SKIP_COMMENTS \ + SKIP_C89_COMMENTS \ + SKIP_C99_COMMENTS + +#define SKIP_COMMENTS2 \ + while(1) { \ + SKIP_C89_COMMENTS \ + SKIP_C99_COMMENTS \ + break; \ + } + + +#define SKIP_SPACES \ + SKIP_COMMENTS2;\ + while (ISSPACE(*source_ptr) || (*source_ptr == '\\' && *(source_ptr + 1) == '\n')) { \ + if (*source_ptr == '\\' && *(source_ptr + 1) == '\n') { source_ptr += 2; line_count++; continue; } \ + if (*source_ptr == '\n') { line_count++; source_ptr++; continue; } \ + SKIP_COMMENTS;\ + source_ptr++; \ + } + + +#define SKIP_SPACES_UNTIL_LF \ + SKIP_COMMENTS2;\ + while (ISSPACE(*source_ptr) || (*source_ptr == '\\' && *(source_ptr + 1) == '\n')) { \ + if (*source_ptr == '\\' && *(source_ptr + 1) == '\n') { source_ptr += 2; continue; } \ + if (*source_ptr == '\n') break; \ + SKIP_COMMENTS;\ + source_ptr++; \ + } + + +#define SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES \ + SKIP_COMMENTS2;\ + while (ISSPACE(*source_ptr) || (*source_ptr == '\\' && *(source_ptr + 1) == '\n')) { \ + if (*source_ptr == '\\' && *(source_ptr + 1) == '\n') { source_ptr += 2; line_count++; continue; } \ + if (*source_ptr == '\n') { line_count++; break; } \ + SKIP_COMMENTS;\ + source_ptr++; \ + } + + +#define SKIP_ALL_UNTIL_LF \ + SKIP_COMMENTS2;\ + while (*source_ptr || (*source_ptr == '\\' && *(source_ptr + 1) == '\n')) { \ + if (*source_ptr == '\\' && *(source_ptr + 1) == '\n') { source_ptr += 2; continue; } \ + if (*source_ptr == '\n') break; \ + SKIP_COMMENTS;\ + source_ptr++; \ + } + + +#define SKIP_ALL_UNTIL_LF_AND_COUNT_LINES \ + SKIP_COMMENTS2;\ + while (*source_ptr || (*source_ptr == '\\' && *(source_ptr + 1) == '\n')) { \ + if (*source_ptr == '\\' && *(source_ptr + 1) == '\n') { source_ptr += 2; line_count++; continue; } \ + if (*source_ptr == '\n') { line_count++; break; } \ + SKIP_COMMENTS;\ + source_ptr++; \ + } + + +#define GET_NEXT_TOKEN_IN_TMPBUFFER \ + buffer_ptr = buffer; \ + while (ISWORDCHAR(*source_ptr)) \ + { \ + if (buffer_ptr == buffer+1023) compile_error (MSG_IDENTIFIER_TOO_LONG); \ + *buffer_ptr++ = TOUPPER(*source_ptr++); \ + } \ + *buffer_ptr++ = 0; \ + token.code = identifier_search_or_add(buffer); \ + token.type = IDENTIFIER; + +/* ---------------------------------------------------------------------- */ + +int n_files = 0; /* Includes */ +char files[MAX_SOURCES][__MAX_PATH]; /* Includes */ +char *source_data[MAX_SOURCES]; /* Includes */ + +/* ---------------------------------------------------------------------- */ + +int load_file( char * filename ) +{ + long size; + file * fp = file_open( filename, "rb0" ); + int n; + + for( n = 0; n < n_files; n++ ) if ( !strcmp( files[n], filename ) ) break; + + if ( n >= n_files ) + { + if ( n_files == MAX_SOURCES ) compile_error( MSG_TOO_MANY_FILES ); + strcpy( files[n_files], filename ); + if ( !fp ) compile_error( MSG_FILE_NOT_FOUND, filename ); + size = file_size( fp ); + source_data[n_files] = ( char * ) calloc( size + 1, sizeof( char ) ); + if ( !source_data[n_files] ) compile_error( MSG_FILE_TOO_BIG, filename ); + if ( size == 0 ) compile_error( MSG_FILE_EMPTY, filename ); + if ( !file_read( fp, source_data[n_files], size ) ) compile_error( MSG_READ_ERROR, filename ); + + source_data[n_files][size] = 0; + file_close( fp ); + n = n_files++; + } + + token_init( source_data[n], n ); + return n; +} + +/* ---------------------------------------------------------------------- */ + +void include_file( int bprepro ) +{ + static char buffer[1024]; + char * buffer_ptr = buffer; + int actual_line = line_count; + + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr == '"' ) + { + source_ptr++; + buffer_ptr = buffer; + while ( *source_ptr && *source_ptr != '"' ) + { + if ( buffer_ptr == buffer + 1023 ) compile_error( MSG_IDENTIFIER_TOO_LONG ); + *buffer_ptr++ = *source_ptr++; + } + if ( *source_ptr == '"' ) source_ptr++; + *buffer_ptr = 0; + if ( bprepro ) + { + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr == '\n' ) line_count--; + } + else + { + SKIP_SPACES; + } + if ( *source_ptr == ';' ) + { + if ( bprepro ) + { + compile_warning( 0,"extra tokens at end of #include directive" ); + SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr == '\n' ) line_count--; + } + else + token_next(); + } + + load_file( buffer ); + token_next(); + return; + } + line_count = actual_line; + compile_error( MSG_FILENAME_EXP ); +} + +/* ---------------------------------------------------------------------- */ + +int find_define( int code ) +{ + int i; + + /* Search for if already defined */ + for ( i = 0; i < defines_count; i++ ) if ( defines[i].code == code ) return i; + + return -1; +} + +/* ---------------------------------------------------------------------- */ + +void add_simple_define( char * macro, char *text ) +{ + int code = identifier_search_or_add( macro ); + + if ( find_define( code ) != -1 ) compile_error( MSG_MACRO_ERROR, identifier_name( code ) ); + + /* Allocate the macro */ + + if ( defines_allocated == defines_count ) + { + defines_allocated += 8; + defines = ( DEFINE * ) realloc( defines, sizeof( DEFINE ) * defines_allocated ); + } + + defines[defines_count].param_count = -1; + defines[defines_count].code = code; + defines[defines_count].text = strdup( text ); + defines_count++; +} + +/* ---------------------------------------------------------------------- */ +/* + * FUNCTION : preprocessor_jumpto + * + * Ignores all of the remaining source file, until + * a preprocessor directive with identifier id1 + * (or id2 if non-zero), and moves the source_ptr + * source code pointer just after it. + * + * This function is used by preprocessor() + * with a #ifdef, #ifndef or #if directive. + * + * PARAMS : + * id1 Identifier of ending directive (i.e. id_endif) + * id2 Alternative ending directive (i.e. id_else) or 0 if none + * + * RETURN VALUE : + * None + */ + +void preprocessor_jumpto( int id, int id2 ) +{ + int depth = 1; + use_saved = 0; + + disable_prepro = 1; + + while ( depth > 0 && *source_ptr ) + { + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr == '\n' ) + { + source_ptr++; + + SKIP_SPACES; + + if ( *source_ptr == '#' ) + { + source_ptr++; + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr == '\n' ) line_count--; + + token_next(); + if ( token.type == IDENTIFIER ) + { + if ( token.code == id_endif ) + { + int stck_code = prepro_stack[--prepro_sp]; + + if ( prepro_sp < 0 || ( + stck_code != id_else && + stck_code != id_if && + stck_code != id_ifdef && + stck_code != id_ifndef ) ) + compile_error( "#endif without #if" ); + } + if ( token.code == id_else ) + { + int stck_code = prepro_stack[--prepro_sp]; + + if ( prepro_sp < 0 || + ( + stck_code != id_if && + stck_code != id_ifdef && + stck_code != id_ifndef + ) + ) + { + if ( stck_code == id_else ) + { + compile_error( "#else after #else" ); + } + else + { + compile_error( "#else without #if" ); + } + } + prepro_stack[prepro_sp++] = token.code; + } + else if ( token.code == id_ifdef || token.code == id_ifndef || token.code == id_if ) + { + prepro_stack[prepro_sp++] = token.code; + } + + if ( token.code == id_endif /*id || (id2 && token.code == id2)*/ ) + { + depth--; + } + else if ( token.code == id_else ) + { + depth--; + if ( !depth ) break; + depth++; + } + else if ( token.code == id_ifdef || token.code == id_ifndef || token.code == id_if ) + { + depth++; + } + } + continue; + } + } + source_ptr++; + } + + if ( token.code != id && ( id2 && token.code != id2 ) ) compile_error( "unbalanced #if/#else/#endif" ); + + if ( depth > 0 ) compile_error( "unterminate #if" ); + + disable_prepro = 0; + +} + +/* + * FUNCTION : preprocessor_expand + * + * Expands a macro to a malloc'ed text area and moves the + * token processing to it using token_init(). This function + * is called just after the macro name is read (next token + * should be a '(' if any parameters needed) + * + * PARAMS : + * None + * + * RETURN VALUE : + * None + */ + +void preprocessor_expand( DEFINE * def ) +{ + const char * param_left[MAX_MACRO_PARAMS]; + const char * param_right[MAX_MACRO_PARAMS]; + const char * begin = NULL; + const char * old_source = NULL; + char * text; + int i, count, depth, allocated, size, part, actual_line_count; + + /* No params - easy case */ + + if ( def->param_count == -1 ) + { + int line = line_count - 1; + token_init( def->text, current_file ); + line_count = line; + return; + } + + /* Find left parenthesis */ + + disable_expand_defines++; + token_next(); + disable_expand_defines--; + if ( token.type != IDENTIFIER || token.code != identifier_leftp ) compile_error( MSG_EXPECTED, "(" ); + + /* Mark parameters' starting and ending positions */ + + if ( def->param_count > 0 ) + { + for ( count = 0; count < def->param_count; count++ ) + { + depth = 0; + param_left[count] = source_ptr; + + while ( *source_ptr && ( depth > 0 || ( *source_ptr != ')' && *source_ptr != ',' ) ) ) + { + if ( *source_ptr == '"' || *source_ptr == '\'' ) + { + begin = source_ptr++; + while ( *source_ptr && *source_ptr != *begin ) source_ptr++; + if ( !*source_ptr ) compile_error( MSG_EXPECTED, "\"" ); + source_ptr++; + continue; + } + if ( *source_ptr == '(' ) depth++; + if ( *source_ptr == ')' ) depth--; + source_ptr++; + } + param_right[count] = source_ptr; + if ( !*source_ptr ) compile_error( MSG_EXPECTED, ")" ); + if ( *source_ptr == ')' ) break; + source_ptr++; + } + + if ( count != def->param_count - 1 || *source_ptr != ')' ) + compile_error( MSG_INCORRECT_PARAMC, identifier_name( def->code ), def->param_count - 1 ); + } + else + { + if ( *source_ptr != ')' ) + compile_error( MSG_INCORRECT_PARAMC, identifier_name( def->code ), def->param_count ); + } + + source_ptr++; + + /* Expand the macro */ + + allocated = 128; + size = 0; + text = ( char * )calloc( allocated, sizeof( char ) ); + old_source = source_ptr; + source_ptr = def->text; + actual_line_count = line_count; + + while ( *source_ptr ) + { + SKIP_SPACES_UNTIL_LF; + if ( *source_ptr == '\n' ) break; + + begin = source_ptr; + SKIP_SPACES_UNTIL_LF; + if ( *source_ptr ) + { + SKIP_SPACES_UNTIL_LF; + if ( !*source_ptr ) break; + if ( *source_ptr != '\n' ) + { + disable_expand_defines++; + token_next(); + disable_expand_defines--; + if ( token.type == NOTOKEN ) break; + if ( token.type == IDENTIFIER ) + { + /* Next token is an identifier. Search for parameter */ + + for ( i = 0; i < def->param_count; i++ ) + if ( def->param_id[i] == token.code ) break; + + if ( i != def->param_count ) /* Parameter found - expand it */ + { + + part = param_right[i] - param_left[i]; + if ( size + part + 1 >= allocated ) + { + allocated += (( part + 256 ) & ~ 127 ); + text = ( char * )realloc( text, allocated ); + } + text[size++] = ' '; + memcpy( text + size, param_left[i], part ); + size += part; + continue; + } + } + + /* No parameter found - copy the token */ + + part = source_ptr - begin; + if ( size + part + 1 >= allocated ) + { + allocated += (( part + 256 ) & ~127 ); + text = ( char * )realloc( text, allocated ); + } + memcpy( text + size, begin, part ); + size += part; + } + else + { + line_count++; + source_ptr++; + } + } + } + + text[size] = 0; + source_ptr = old_source; + line_count = actual_line_count; + + /* Now "include" the expanded text "file" */ + + token_init( text, current_file ); + line_count = actual_line_count - 1; + + free( text ); +} + +/* + * FUNCTION : preprocessor + * + * Evaluates a preprocessor directive. This function is called + * just after a '#' symbol is found after an end-of-line. + * + * The function moves source_ptr to the next line. + * + * PARAMS : + * None + * + * RETURN VALUE : + * 1 - Include identifier + * 0 - Other identifier + */ + +void preprocessor() +{ + int i, ifdef; + char * ptr; + int actual_line_count; + + static int initialized = 0; + + if ( !initialized ) + { + id_define = identifier_search_or_add( "DEFINE" ); + id_undef = identifier_search_or_add( "UNDEF" ); + id_ifdef = identifier_search_or_add( "IFDEF" ); + id_ifndef = identifier_search_or_add( "IFNDEF" ); + id_else = identifier_search_or_add( "ELSE" ); + id_endif = identifier_search_or_add( "ENDIF" ); + id_if = identifier_search_or_add( "IF" ); + initialized = 1; + } + + token_next(); + + if ( token.type != IDENTIFIER ) compile_error( MSG_UNKNOWN_PREP ); + + /* #define TEXT value */ + + if ( token.code == id_define ) + { + disable_expand_defines++; + + token_next(); + if ( token.type != IDENTIFIER ) compile_error( MSG_INVALID_IDENTIFIER ); + + if ( find_define( token.code ) != -1 ) compile_error( MSG_MACRO_ERROR, identifier_name( token.code ) ); + + /* Allocate the macro */ + + if ( defines_allocated == defines_count ) + { + defines_allocated += 8; + defines = ( DEFINE * ) realloc( defines, sizeof( DEFINE ) * defines_allocated ); + } + + defines[defines_count].code = token.code; + + /* Check for parameters: no space allowed between name and ( */ + + if ( *source_ptr == '(' ) + { + source_ptr++; + for ( defines[defines_count].param_count = i = 0; *source_ptr != ')'; ) + { + if ( !*source_ptr ) compile_error( MSG_EXPECTED, ")" ); + if ( i == MAX_MACRO_PARAMS ) compile_error( MSG_TOO_MANY_PARAMS ); + token_next(); + + if ( token.type != IDENTIFIER || token.code < reserved_words ) compile_error( MSG_INVALID_IDENTIFIER ); + + defines[defines_count].param_id[i++] = token.code; + defines[defines_count].param_count++; + + SKIP_SPACES; + if ( *source_ptr == ',' ) source_ptr++; + } + source_ptr++; + } + else + { + /* No parameters and no parenthesis */ + defines[defines_count].param_count = -1; + } + + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + + ptr = ( char * ) source_ptr; + + while ( *ptr && *ptr != '\n' ) + if ( *ptr == '\\' && *( ptr + 1 ) == '\n' ) + { + *ptr = ' '; + ptr++; + *ptr = ' '; + ptr++; + line_count++; + } + else + ptr++; + + while ( ptr > source_ptr && ( !*ptr || ISSPACE( *ptr ) ) ) ptr--; + + defines[defines_count].text = ( char * )calloc( ptr - source_ptr + 2, sizeof( char ) ); + strncpy( defines[defines_count].text, source_ptr, ptr - source_ptr + 1 ); + defines[defines_count].text[ptr - source_ptr + 1] = 0; + + defines_count++; + + source_ptr = ptr + 1; + + disable_expand_defines--; + + return; + } + + /* #undef TEXT */ + + if ( token.code == id_undef ) + { + disable_expand_defines++; + + token_next(); + if ( token.type != IDENTIFIER ) compile_error( MSG_INVALID_IDENTIFIER ); + + if (( i = find_define( token.code ) ) != -1 ) + { + defines_count--; + if ( defines[i].text ) free( defines[i].text ); + memmove( &defines[i], &defines[i+1], ( defines_count - i ) * sizeof( DEFINE ) ); + } + + disable_expand_defines--; + + return; + } + + /* #ifdef CONST / #ifndef CONST*/ + + if ( token.code == id_ifdef || token.code == id_ifndef ) + { + ifdef = token.code == id_ifdef; + + prepro_stack[prepro_sp++] = token.code; + + disable_expand_defines++; + token_next(); + disable_expand_defines--; + + if ( token.type != IDENTIFIER ) compile_error( MSG_INVALID_IDENTIFIER ); + + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr && *source_ptr != '\n' ) + { + if ( ifdef ) compile_warning( 0,"extra tokens at end of #ifdef directive" ); + else compile_warning( 0,"extra tokens at end of #ifndef directive" ); + SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; + } + + if ( *source_ptr == '\n' ) line_count--; + + for ( i = 0; i < defines_count; i++ ) + { + if ( defines[i].code == token.code ) + { + if ( ifdef ) return; + break; + } + } + if ( !ifdef && i == defines_count ) return; + + + preprocessor_jumpto( id_else, id_endif ); + + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr && *source_ptr != '\n' ) + { + if ( token.code == id_else ) compile_warning( 0,"extra tokens at end of #else directive" ); + else if ( token.code == id_endif ) compile_warning( 0,"extra tokens at end of #endif directive" ); + SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; + } + if ( *source_ptr == '\n' ) line_count--; + return; + } + + /* #if */ + + if ( token.code == id_if ) + { + int actual_sources; + expresion_result res; + char c; + + prepro_stack[prepro_sp++] = token.code; + + ptr = ( char * ) source_ptr; + + while ( *ptr && *ptr != '\n' && *ptr != ';' ) + if ( *ptr == '\\' && *( ptr + 1 ) == '\n' ) + { + *ptr = ' '; + ptr++; + *ptr = ' '; + ptr++; + line_count++; + } + else + ptr++; + + c = *ptr; + *ptr = '\0'; + + actual_line_count = line_count; + actual_sources = sources; + + token_init( source_ptr, current_file ); + + identifiers_as_strings = 1; + res = compile_expresion( 0, 0, 1, TYPE_DWORD ); + identifiers_as_strings = 0; + /* + printf ("exp: asignation: [%d] call: [%d] lvalue: [%d] constant: [%d] value: [%d] lvalue: [%f] type: [%d]\n", + res.asignation, + res.call, + res.lvalue, + res.constant, + res.value, + res.fvalue, + typedef_base(res.type)); + */ + if ( sources != actual_sources ) token_endfile(); + *ptr = c; + source_ptr = ptr; + line_count = actual_line_count; + + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr && *source_ptr != '\n' ) + { + compile_warning( 0,"extra tokens at end of #if directive" ); + SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; + } + if ( *source_ptr == '\n' ) line_count--; + + use_saved = 0; + if ( !res.constant ) compile_error( MSG_CONSTANT_EXP ); + if ( !res.value ) + { + preprocessor_jumpto( id_else, id_endif ); + + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr && *source_ptr != '\n' ) + { + if ( token.code == id_else ) compile_warning( 0,"extra tokens at end of #else directive" ); + else if ( token.code == id_endif ) compile_warning( 0,"extra tokens at end of #endif directive" ); + SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; + } + if ( *source_ptr == '\n' ) line_count--; + } + + return; + } + + /* #else */ + + if ( token.code == id_else ) + { + if ( !prepro_sp ) compile_error( "#else without #if" ); + + int stck_code = prepro_stack[--prepro_sp]; + + if ( prepro_sp < 0 || + ( + stck_code != id_if && + stck_code != id_ifdef && + stck_code != id_ifndef + ) + ) + { + if ( stck_code == id_else ) + { + compile_error( "#else after #else" ); + } + else + { + compile_error( "#else without #if" ); + } + } + prepro_stack[prepro_sp++] = token.code; + + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr && *source_ptr != '\n' ) + { + compile_warning( 0,"extra tokens at end of #else directive" ); + SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; + } + if ( *source_ptr == '\n' ) line_count--; + + preprocessor_jumpto( id_endif, 0 ); + + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr && *source_ptr != '\n' ) + { + compile_warning( 0,"extra tokens at end of #endif directive" ); + SKIP_ALL_UNTIL_LF_AND_COUNT_LINES; + } + if ( *source_ptr == '\n' ) line_count--; + return; + } + + /* #endif */ + + if ( token.code == id_endif ) + { + int stck_code = prepro_stack[--prepro_sp]; + + if ( prepro_sp < 0 || ( + stck_code != id_else && + stck_code != id_if && + stck_code != id_ifdef && + stck_code != id_ifndef ) ) compile_error( "#endif without #if" ); + + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + if ( *source_ptr == '\n' ) line_count--; + return; + } + + /* Unknown preprocessor directive */ + compile_error( MSG_UNKNOWN_PREP ); +} + +void token_init( const char * source, int file ) +{ + char * ptr; + char * clean_source; + + if ( sources == MAX_SOURCES ) compile_error( MSG_TOO_MANY_INCLUDES ); + + if ( !source ) + { + fprintf( stdout, "token_init: no source\n" ); + exit( 1 ); + } + + /* Perform cleaning of the source file */ + + clean_source = ( char * ) calloc( strlen( source ) + 2, sizeof( char ) ); + ptr = clean_source; + *ptr++ = '\n'; /* Adds a blank line to detect first-line # directives */ + while ( *source ) + { + if ( *source == '\r' && source[1] == '\n' ) + { + source += 2; + *ptr++ = '\n'; + } + else + { + *ptr++ = *source++; + } + } + *ptr = 0; + + /* Store the old source pointer */ + + old_line_counts [sources] = line_count; + old_current_file [sources] = current_file; + old_sources [sources] = source_ptr; + old_sources_start [sources] = source_start; + sources++; + + /* Use the new source */ + + line_count = 0; + current_file = file; + source_ptr = clean_source; + source_start = clean_source; + + use_saved = 0; +} + +int token_endfile() +{ + if ( source_start ) + { + free( source_start ); + source_start = 0; + } + if ( sources > 0 ) + { + sources--; + line_count = old_line_counts[sources]; + current_file = old_current_file[sources]; + source_ptr = old_sources[sources]; + source_start = old_sources_start[sources]; + use_saved = 0; + } + + if ( sources < 1 ) + { + if ( prepro_sp > 0 ) compile_error( "unbalanced #if/#else/#endif" ); + } + return 0; +} + +void token_dump() +{ + if ( token.type == NUMBER ) fprintf( stdout, "%d", token.code ); + else if ( token.type == FLOAT ) fprintf( stdout, "%f", token.value ); + else if ( token.type == STRING ) fprintf( stdout, "\"%s\"", string_get( token.code ) ); + else if ( token.type == IDENTIFIER ) fprintf( stdout, "\"%s\"", identifier_name( token.code ) ); + else if ( token.type == LABEL ) fprintf( stdout, "\"%s\"", identifier_name( token.code ) ); + else if ( token.type == NOTOKEN ) fprintf( stdout, "EOF" ); + else fprintf( stdout, "unknown" ); +} + +extern int c_type_initialized; + +void token_next() +{ + static int i, len; + static char buffer[1024]; + char * buffer_ptr = buffer; + + if ( !source_ptr ) + { + token.type = NOTOKEN; + return; + } + + if ( use_saved ) + { + token = token_saved; + line_count = token.line; + current_file = token.file; + use_saved = 0; + return; + } + token.line = line_count; + token.file = current_file; + token_prev = token; + + while ( 1 ) + { + SKIP_SPACES; + + if ( !disable_prepro && *source_ptr == '#' ) + { + int line; + const char * old_source_ptr; + + identifiers_as_strings = 0; + + /* Comandos de preprocesador */ + source_ptr++; + + line = line_count; + + SKIP_SPACES_UNTIL_LF_AND_COUNT_LINES; + + if ( *source_ptr == '\n' ) + { + token.code = identifier_search_or_add( "#" ); + token.type = IDENTIFIER; + line_count = line; + compile_error( MSG_IDENTIFIER_EXP ); + } + + old_source_ptr = source_ptr; + + if ( ISWORDFIRST( *source_ptr ) ) + { + GET_NEXT_TOKEN_IN_TMPBUFFER; + + /* #include "file.h" */ + + if ( token.code == identifier_include && !use_saved ) + { + include_file( 1 ); + return; + } + + source_ptr = old_source_ptr; + } + + preprocessor(); + + buffer_ptr = buffer; + *buffer_ptr = '\0'; + continue; + } + + if ( !*source_ptr ) + { + /* Casos de bloques manuales */ + if ( current_file == -1 ) + { + token_endfile(); + token.type = NOTOKEN; + return; + } + + while ( !*source_ptr ) + { + if ( sources == 0 ) + { + token.type = NOTOKEN; + return; + } + + token_endfile(); + + if ( !source_ptr ) + { + token.type = NOTOKEN; + return; + } + } + continue; + } + + /* Ignora comentarios */ + + SKIP_COMMENTS; + if ( !*source_ptr ) + { + token.type = NOTOKEN; + return; + } + + /* Cadenas */ + + if ( *source_ptr == '"' || *source_ptr == '\'' ) + { + token.type = STRING; + token.code = string_compile( &source_ptr ); + token.line = line_count; + token.file = current_file; + return; + } + + /* Operadores de más de un caracter */ + + len = 0; + + if ( *source_ptr == '<' ) + { + if ( source_ptr[1] == '<' ) + { + if ( source_ptr[2] == '=' ) len = 3; + else len = 2; + } + else if ( source_ptr[1] == '>' ) len = 2; + else if ( source_ptr[1] == '=' ) len = 2; + else len = 1; + } + else if ( *source_ptr == '>' ) + { + if ( source_ptr[1] == '>' ) + { + if ( source_ptr[2] == '=' ) len = 3; + else len = 2; + } + else if ( source_ptr[1] == '=' ) len = 2; + else if ( source_ptr[1] == '>' ) len = 2; + else len = 1; + } + else if ( *source_ptr == '|' ) + { + if ( source_ptr[1] == '|' ) + { + if ( source_ptr[2] == '=' ) len = 3; + else len = 2; + } + else if ( source_ptr[1] == '=' ) len = 2; + else len = 1; + } + else if ( *source_ptr == '=' ) + { + if ( source_ptr[1] == '=' ) len = 2; + else if ( source_ptr[1] == '>' ) len = 2; + else if ( source_ptr[1] == '<' ) len = 2; + else len = 1; + } + else if ( *source_ptr == '.' ) + { + if ( source_ptr[1] == '.' ) len = 2; + else len = 1; + } + else if ( strchr( "!&^%*+-/", *source_ptr ) ) + { + if ( source_ptr[1] == '=' ) len = 2; + else if ( strchr( "+-&^", *source_ptr ) && source_ptr[1] == *source_ptr ) len = 2; + else len = 1; + } + + if ( len ) + { + strncpy( buffer, source_ptr, len ); + buffer[len] = 0; + source_ptr += len; + token.code = identifier_search_or_add( buffer ); + token.type = IDENTIFIER; + token.line = line_count; + token.file = current_file; + return; + } + + /* Numbers */ + + if ( ISNUM( *source_ptr ) ) + { + const char * ptr; + double num = 0, dec; + int base = 10; + + /* Hex/Bin/Octal numbers with the h/b/o sufix */ + ptr = source_ptr; + while ( ISNUM( *ptr ) || ( *ptr >= 'a' && *ptr <= 'f' ) || ( *ptr >= 'A' && *ptr <= 'F' ) ) ptr++; + + if ( *ptr != 'h' && *ptr != 'H' && *ptr != 'o' && *ptr != 'O' && ( ptr[-1] == 'b' || ptr[-1] == 'B' ) ) ptr--; + + if ( *ptr == 'b' || *ptr == 'B' ) + base = 2; + if ( *ptr == 'h' || *ptr == 'H' ) + base = 16; + if ( *ptr == 'o' || *ptr == 'O' ) + base = 8; + + token.code = 0 ; /* for ints values */ + + /* Calculate the number value */ + + while ( ISNUM( *source_ptr ) || ( base > 10 && ISALNUM( *source_ptr ) ) ) + { + if ( base == 2 && *source_ptr != '0' && *source_ptr != '1' ) break; + if ( base == 8 && ( *source_ptr < '0' || *source_ptr > '7' ) ) break; + if ( base == 10 && !ISNUM( *source_ptr ) ) break; + if ( base == 16 && !ISNUM( *source_ptr ) && ( TOUPPER( *source_ptr ) < 'A' || TOUPPER( *source_ptr ) > 'F' ) ) break; + + if ( ISNUM( *source_ptr ) ) + { + num = num * base + ( *source_ptr - '0' ); + token.code = token.code * base + ( *source_ptr - '0' ); + source_ptr++; + continue; + } + if ( *source_ptr >= 'a' && *source_ptr <= 'f' && base > 10 ) + { + num = num * base + ( *source_ptr - 'a' + 10 ); + token.code = token.code * base + ( *source_ptr - 'a' + 10 ); + source_ptr++; + continue; + } + if ( *source_ptr >= 'A' && *source_ptr <= 'F' && base > 10 ) + { + num = num * base + ( *source_ptr - 'A' + 10 ); + token.code = token.code * base + ( *source_ptr - 'A' + 10 ); + source_ptr++; + continue; + } + } + token.type = NUMBER; + token.value = ( float )num; + + /* We have the integer part now - convert to int/float */ + + if ( *source_ptr == '.' && base == 10 ) + { + source_ptr++; + if ( !ISNUM( *source_ptr ) ) + source_ptr--; + else + { + dec = 1.0 / ( double )base; + while ( ISNUM( *source_ptr ) || ( base > 100 && ISALNUM( *source_ptr ) ) ) + { + if ( ISNUM( *source_ptr ) ) num = num + dec * ( *source_ptr++ - '0' ); + if ( *source_ptr >= 'a' && *source_ptr <= 'f' && base > 10 ) num = num + dec * ( *source_ptr++ - 'a' + 10 ); + if ( *source_ptr >= 'A' && *source_ptr <= 'F' && base > 10 ) num = num + dec * ( *source_ptr++ - 'A' + 10 ); + dec /= ( double )base; + } + token.type = FLOAT; + token.value = ( float )num; + } + } + + /* Skip the base sufix */ + + if ( base == 16 && ( *source_ptr == 'h' || *source_ptr == 'H' ) ) source_ptr++; + if ( base == 8 && ( *source_ptr == 'o' || *source_ptr == 'O' ) ) source_ptr++; + if ( base == 2 && ( *source_ptr == 'b' || *source_ptr == 'B' ) ) source_ptr++; + + token.line = line_count; + token.file = current_file; + return; + } + + /* Identificadores */ + if ( ISWORDFIRST( *source_ptr ) ) + { + int maybe_label = source_ptr[-1] == '\n'; + GET_NEXT_TOKEN_IN_TMPBUFFER; + + token.line = line_count; + token.file = current_file; + + if ( maybe_label && *source_ptr == ':' && identifier_search( buffer ) > reserved_words ) + { + source_ptr++; + token.code = identifier_search_or_add( buffer ); + token.type = LABEL; + return; + } + + /* Search for #define constant inclusion at this point */ + + if ( !disable_expand_defines ) + { + if ( !strcmp( buffer, "__FILE__" ) ) + { + token.type = STRING; + token.code = string_new(( current_file != -1 && files[current_file] && *files[current_file] ) ? files[current_file] : "N/A" ); + token.line = line_count; + token.file = current_file; + return; + } + + if ( !strcmp( buffer, "__LINE__" ) ) + { + token.type = NUMBER; + token.code = ( int )line_count; + token.value = ( float )line_count; + token.line = line_count; + token.file = current_file; + return; + } + + for ( i = 0; i < defines_count; i++ ) + { + if ( defines[i].code == token.code ) + { + preprocessor_expand( &defines[i] ); + token_next(); + token.line = line_count; + token.file = current_file; + return; + } + } + } + + /* In a #if, all identifiers are strings */ + + if ( identifiers_as_strings ) + { + token.type = STRING; + token.code = string_new( buffer ); + token.line = line_count; + token.file = current_file; + return; + } + + /* Include */ + + if ( !disable_prepro && token.code == identifier_include && !use_saved ) + { + include_file( 0 ); + return; + } + return; + } + + /* 1-char operator or invalid symbol */ + + if ( !*source_ptr ) break; + + if ( *source_ptr > 0 && *source_ptr < 32 ) compile_error( MSG_INVALID_CHAR ); + + *buffer_ptr++ = *source_ptr++; + *buffer_ptr = 0; + + token.code = identifier_search_or_add( buffer ); + token.type = IDENTIFIER; + token.line = line_count; + token.file = current_file; + + return; + } + + token.type = NOTOKEN; + return; /* End-of-file */ +} + +void token_back() +{ + if ( use_saved ) + { + fprintf( stdout, "Error: two token_back in a row\n" ); + exit( 1 ); + } + + token.line = line_count; + token.file = current_file; + token_saved = token; + + token = token_prev; + + line_count = token.line; + current_file = token.file; + + use_saved = 1; +} + +tok_pos token_pos() +{ + tok_pos tp; + + tp.use_saved = use_saved; + tp.token_saved = token_saved; + tp.token = token; + tp.line_count = line_count; + tp.current_file = current_file; + tp.token_prev = token_prev; + tp.source_ptr = source_ptr; + + return tp; +} + +void token_set_pos( tok_pos tp ) +{ + use_saved = tp.use_saved; + token_saved = tp.token_saved; + token = tp.token; + line_count = tp.line_count; + current_file = tp.current_file; + token_prev = tp.token_prev; + source_ptr = tp.source_ptr; +} + diff --git a/core/bgdc/src/typedef.c b/core/bgdc/src/typedef.c new file mode 100644 index 0000000..e7ac992 --- /dev/null +++ b/core/bgdc/src/typedef.c @@ -0,0 +1,242 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "bgdc.h" + +TYPEDEF typedef_new( BASETYPE type ) +{ + TYPEDEF t ; + + memset (&t, '\0', sizeof(t)); + + t.chunk[0].type = type ; + if ( type == TYPE_POINTER ) + { + t.depth = 2 ; + t.chunk[1].type = TYPE_UNDEFINED ; + } + else t.depth = 1 ; + t.varspace = 0 ; + return t ; +} + +TYPEDEF typedef_reduce( TYPEDEF base ) +{ + TYPEDEF t = base ; + + memmove( &t.chunk[0], &t.chunk[1], sizeof( TYPECHUNK ) * ( MAX_TYPECHUNKS - 1 ) ) ; + t.depth-- ; + return t ; +} + +TYPEDEF typedef_enlarge( TYPEDEF base ) +{ + TYPEDEF t = base ; + + memmove( &t.chunk[1], &t.chunk[0], sizeof( TYPECHUNK ) * ( MAX_TYPECHUNKS - 1 ) ) ; + t.depth++ ; + return t ; +} + +TYPEDEF typedef_pointer( TYPEDEF base ) +{ + TYPEDEF t = typedef_enlarge( base ) ; + + t.chunk[0].type = TYPE_POINTER ; + return t ; +} + +void typedef_describe( char * buffer, TYPEDEF t ) +{ + switch ( t.chunk[0].type ) + { + case TYPE_INT: + sprintf( buffer, "INT" ) ; + return ; + + case TYPE_DWORD: + sprintf( buffer, "DWORD" ) ; + return ; + + case TYPE_SHORT: + sprintf( buffer, "SHORT" ) ; + return ; + + case TYPE_WORD: + sprintf( buffer, "WORD" ) ; + return ; + + case TYPE_BYTE: + sprintf( buffer, "BYTE" ) ; + return ; + + case TYPE_CHAR: + sprintf( buffer, "CHAR" ) ; + return ; + + case TYPE_SBYTE: + sprintf( buffer, "SIGNED BYTE" ) ; + return ; + + case TYPE_STRING: + sprintf( buffer, "STRING" ) ; + return ; + + case TYPE_FLOAT: + sprintf( buffer, "FLOAT" ) ; + return ; + + case TYPE_STRUCT: + if ( t.chunk[0].count > 1 ) + sprintf( buffer, "STRUCT [%d]", t.chunk[0].count ) ; + else + sprintf( buffer, "STRUCT" ) ; + return ; + + case TYPE_ARRAY: + sprintf( buffer, "ARRAY [%d] OF ", t.chunk[0].count ) ; + typedef_describe( buffer + strlen( buffer ), typedef_reduce( t ) ) ; + return ; + + case TYPE_POINTER: + sprintf( buffer, "POINTER TO " ) ; + typedef_describe( buffer + strlen( buffer ), typedef_reduce( t ) ) ; + return ; + + case TYPE_UNDEFINED: + default: + sprintf( buffer, "<UNDEFINED>" ) ; + return ; + } +} + +int typedef_subsize( TYPEDEF t, int c ) +{ + switch ( t.chunk[c].type ) + { + case TYPE_BYTE: + case TYPE_SBYTE: + case TYPE_CHAR: + return 1 ; + + case TYPE_WORD: + case TYPE_SHORT: + return 2 ; + + case TYPE_DWORD: + case TYPE_INT: + case TYPE_FLOAT: + case TYPE_STRING: + case TYPE_POINTER: + return 4 ; + + case TYPE_ARRAY: + return t.chunk[c].count * typedef_subsize( t, c + 1 ) ; + + case TYPE_STRUCT: + return t.varspace->size ; + + default: + compile_error( MSG_INCOMP_TYPE ) ; + return 0 ; + } +} + +int typedef_size( TYPEDEF t ) +{ + return typedef_subsize( t, 0 ) ; +} + +/* Tipos nombrados (structs, típicamente) */ + +static TYPEDEF * named_types = NULL; +static int * named_codes = NULL; +static int named_count = 0 ; +static int named_reserved = 0; + +TYPEDEF * typedef_by_name( int code ) +{ + int n ; + + for ( n = 0 ; n < named_count ; n++ ) + if ( named_codes[n] == code ) return &named_types[n] ; + return 0 ; +} + +void typedef_name( TYPEDEF t, int code ) +{ + if ( named_count >= named_reserved ) + { + named_reserved += 16; + named_types = ( TYPEDEF * ) realloc( named_types, named_reserved * sizeof( TYPEDEF ) ); + named_codes = ( int * ) realloc( named_codes, named_reserved * sizeof( int ) ); + if ( !named_types || !named_codes ) compile_error( "typedef_name: out of memory\n" ) ; + } + named_codes[named_count] = code ; + named_types[named_count] = t ; + named_count++ ; +} + +int typedef_tcount( TYPEDEF t ) +{ + int n ; + int count = 1 ; + + if ( t.chunk[0].type == TYPE_STRUCT ) return t.chunk[0].count ; + for ( n = 0; t.chunk[n].type == TYPE_ARRAY; n++ ) count *= t.chunk[n].count ; + return count ; +} + +int typedef_is_equal( TYPEDEF a, TYPEDEF b ) +{ + int n; + + if ( a.depth != b.depth ) return 0; + + for ( n = 0; n < a.depth; n++ ) + { + if ( a.chunk[n].type == TYPE_STRUCT && b.chunk[n].type == TYPE_STRUCT && a.varspace != b.varspace ) + { + int m; + if ( a.varspace->count != b.varspace->count ) return 0; + for ( m = 0; m < a.varspace->count; m++ ) + { + if ( !typedef_is_equal( a.varspace->vars[m].type, b.varspace->vars[m].type ) ) return 0; + } + return 1; + } + if ( a.chunk[n].type != b.chunk[n].type ) return 0; + if ( a.chunk[n].type == TYPE_ARRAY && a.chunk[n].count != b.chunk[n].count ) return 0; + } + return 1; +} + diff --git a/core/bgdc/src/varspace.c b/core/bgdc/src/varspace.c new file mode 100644 index 0000000..51ad1bc --- /dev/null +++ b/core/bgdc/src/varspace.c @@ -0,0 +1,256 @@ +/* + * Copyright © 2006-2016 SplinterGU (Fenix/Bennugd) + * Copyright © 2002-2006 Fenix Team (Fenix) + * Copyright © 1999-2002 José Luis Cebrián Pagüe (Fenix) + * + * This file is part of Bennu - Game Development + * + * 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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "bgdc.h" + +/* ---------------------------------------------------------------------- */ +/* Este módulo contiene funciones de utilidad para crear e ir rellenando */ +/* varspaces (tablas con identificador, offset y tipo de cada VARIABLE) */ +/* y segmentos de datos */ +/* ---------------------------------------------------------------------- */ + +VARSPACE global, local ; + +/* + * FUNCTION : varspace_dump + * + * Dumps descriptively the variables of a given varspace to the + * standard output. Recursively describes struct types. + * + * PARAMS : + * n Pointer to the varspace + * indent Left indentation in chars (internal; use 0) + * + * RETURN VALUE : + * None + */ + +void varspace_dump( VARSPACE * n, int indent ) +{ + int i, t, to ; + char buffer[128] ; + + for ( i = 0 ; i < n->count ; i++ ) + { + if ( i < n->count - 1 ) + to = n->vars[i+1].offset - 1 ; + else + to = n->last_offset - 1 ; + + printf( "[%04d:%04d]\t", n->vars[i].offset, to ) ; + for ( t = 0 ; t < indent ; t++ ) printf( " + " ) ; + typedef_describe( buffer, n->vars[i].type ) ; + printf( "%s %s", buffer, identifier_name( n->vars[i].code ) ) ; + + /* Describe arrays of structs */ + + if ( typedef_is_array( n->vars[i].type ) ) + { + TYPEDEF r = typedef_reduce( n->vars[i].type ); + while ( typedef_is_array( r ) ) + r = typedef_reduce( r ); + if ( typedef_is_struct( r ) ) + { + printf( ":\n" ) ; + varspace_dump( typedef_members( r ), indent + 1 ) ; + } + else + printf( "\n" ); + } + + /* Describe structs */ + + else if ( typedef_is_struct( n->vars[i].type ) ) + { + printf( ":\n" ) ; + varspace_dump( typedef_members( n->vars[i].type ), indent + 1 ) ; + } + + else printf( "\n" ) ; + } +} + +/* + * FUNCTION : varspace_new + * + * Create a new varspace in dynamic memory, and initialize + * it using varspace_init + * + * PARAMS : + * None + * + * RETURN VALUE : + * Pointer to the new varspace + */ + +VARSPACE * varspace_new() +{ + VARSPACE * v = ( VARSPACE * ) calloc( 1, sizeof( VARSPACE ) ) ; + if ( !v ) compile_error( "varspace_new: out of memory\n" ) ; + varspace_init( v ) ; + return v ; +} + + +/* + * FUNCTION : varspace_destroy + * + * Destroy a dynamic varspace created with varspace_new + * + * PARAMS : + * v Pointer to the varspace + * + * RETURN VALUE : + * None + */ + +void varspace_destroy( VARSPACE * v ) +{ + free( v->vars ) ; + free( v ) ; +} + +/* + * FUNCTION : varspace_init + * + * Initialize all members of a varspace. Use this function + * to initialize a varspace that is created in local + * memory instead of a dynamic one created with varspace_new. + * + * PARAMS : + * n Pointer to the not-initialized varspace + * + * RETURN VALUE : + * None + */ + +void varspace_init( VARSPACE * n ) +{ + n->vars = ( VARIABLE * ) calloc( 16, sizeof( VARIABLE ) ) ; + n->reserved = 16 ; + n->count = 0 ; + n->size = 0 ; + n->stringvars = 0 ; + n->stringvar_reserved = 0 ; + n->stringvar_count = 0 ; + if ( !n->vars ) compile_error( "varspace_init: out of memory\n" ) ; +} + +/* + * FUNCTION : varspace_varstring + * + * Add a new string offset to the varspace. A varspace has + * a count of every string variable it contains, but this + * list is not updated automatically. You should mark + * every string you create using this function. + * + * PARAMS : + * n Pointer to the varspace + * offset Offset of the new string + * + * RETURN VALUE : + * None + */ + +void varspace_varstring( VARSPACE * n, int offset ) +{ + if ( n->stringvar_reserved == n->stringvar_count ) + { + n->stringvars = ( int * ) realloc( n->stringvars, ( n->stringvar_reserved += 16 ) * sizeof( int ) ) ; + if ( !n->stringvars ) compile_error( "varspace_varstring: out of memory\n" ) ; + } + n->stringvars[n->stringvar_count++] = offset ; +} + +/* + * FUNCTION : varspace_alloc + * + * Allocate space for new variables in the varspace. This + * is an internal function. Use varspace_add instead. + * + * PARAMS : + * n Pointer to the varspace + * count Number of new variables of space to reserve + * + * RETURN VALUE : + * None + */ + +void varspace_alloc( VARSPACE * n, int count ) +{ + n->vars = ( VARIABLE * ) realloc( n->vars, sizeof( VARIABLE ) * ( n->reserved += count ) ) ; + if ( !n->vars ) compile_error( "varspace_alloc: out of memory\n" ) ; +} + +/* + * FUNCTION : varspace_add + * + * Add a new variable to a given varspace. This function does not + * mark string variables. You should use varspace_varstring after + * adding new strings to a varspace. + * + * PARAMS : + * n Pointer to the varspace + * v Variable to add + * + * RETURN VALUE : + * None + */ + +void varspace_add( VARSPACE * n, VARIABLE v ) +{ + if ( n->count == n->reserved ) varspace_alloc( n, 16 ) ; + n->vars[n->count++] = v ; + n->size += typedef_size( v.type ) ; +} + +/* + * FUNCTION : varspace_search + * + * Search a variable in a varspace by its identifier. + * + * PARAMS : + * n Pointer to the varspace + * code Identifier of the variable + * + * RETURN VALUE : + * Pointer to the variable found or NULL if none + */ + +VARIABLE * varspace_search( VARSPACE * n, int code ) +{ + int i ; + + for ( i = 0 ; i < n->count ; i++ ) + if ( n->vars[i].code == code ) return &n->vars[i] ; + return 0 ; +} |