Compare commits

..

1 Commits

Author SHA1 Message Date
1b6200c242 Very basic crypto module, for the moment just using
crypt, no fallback solutions (yet).
2018-07-21 07:39:12 +01:00
177 changed files with 16804 additions and 15378 deletions

View File

@ -1,14 +0,0 @@
kind: pipeline
type: exec
name: AerScript Build
steps:
- name: compile
commands:
- make release
- name: install
commands:
- make install
- name: test
commands:
- make tests

1
.github/FUNDING.yml vendored
View File

@ -1 +0,0 @@
custom: https://paypal.me/pools/c/8hAZMn97vE

View File

@ -5,8 +5,8 @@
incomplete details will be handled as an invalid report.
-->
# AerScript Information
- Aer Version (or commit ref):
# P# Information
- P# Version (or commit ref):
- Operating System:
- System Architecture (eg. arm, x86_64, ...):

6
.vscode/tasks.json vendored
View File

@ -4,7 +4,7 @@
"version": "2.0.0",
"tasks": [
{
"label": "Build AerScript Interpreter",
"label": "Build P# Interpreter",
"type": "shell",
"command": "make",
"group": {
@ -16,7 +16,7 @@
}
},
{
"label": "Clean AerScript Interpreter",
"label": "Clean P# Interpreter",
"type": "shell",
"command": "make",
"args": [
@ -31,7 +31,7 @@
}
},
{
"label": "Style AerScript Interpreter Code",
"label": "Style P# Code",
"type": "shell",
"command": "make",
"args": [

139
Makefile
View File

@ -1,110 +1,66 @@
# Flags to pass to the compiler
CFLAGS = -std=c99 -D_GNU_SOURCE -fPIC -Iinclude -I. -Wunused -Wall -Wextra -Wpedantic
CFLAGS = -fPIC -Iinclude -I. -W -Wunused -Wall
# Additional CFLAGS for debug build
DCFLAGS = -Og -g3
DFLAGS = -O0 -g
# Addditional CFLAGS for release build
RCFLAGS = -O3 -s
RFLAGS = -O3 -s
# Flags to pass to the linker
LDFLAGS =
LFLAGS = -Wl,--export-dynamic -rdynamic
# Flags to enable sanitize checker
SFLAGS = -fsanitize=address -fsanitize=leak
# Destination directory
DESTDIR ?= $(realpath .)/binary
# Additional libraries necessary for linker
LIBS = -ldl -lm
##############################################
### Do not modify anything below this line ###
##############################################
ifeq ($(OS),Windows_NT)
PLATFORM := Windows
PLATFORM := "Windows"
else
PLATFORM := $(shell uname -s)
endif
ifeq "$(PLATFORM)" "Darwin"
CC := clang
CP := cp -v
MD := mkdir -p
RM := rm -rfv
LDFLAGS := $(LDFLAGS) -Wl,-export_dynamic -undefined dynamic_lookup
LIBS := -ldl -lm
EXESUFFIX :=
LIBSUFFIX := .dylib
ESUFFIX :=
LSUFFIX := .dylib
endif
ifeq "$(PLATFORM)" "FreeBSD"
CC := clang
CP := cp -v
MD := mkdir -p
RM := rm -rfv
LDFLAGS := $(LDFLAGS) -Wl,--export-dynamic
LIBS := -lm
EXESUFFIX :=
LIBSUFFIX := .so
ESUFFIX :=
LSUFFIX := .so
endif
ifeq "$(PLATFORM)" "Linux"
CC := gcc
CP := cp -v
MD := mkdir -p
RM := rm -rfv
LDFLAGS := $(LDFLAGS) -Wl,--export-dynamic
LIBS := -ldl -lm
EXESUFFIX :=
LIBSUFFIX := .so
ESUFFIX :=
LSUFFIX := .so
endif
ifeq "$(PLATFORM)" "OpenBSD"
CC := clang
CP := cp -v
MD := mkdir -p
RM := rm -rfv
LDFLAGS := $(LDFLAGS) -Wl,--export-dynamic
LIBS := -lm
EXESUFFIX :=
LIBSUFFIX := .so
ESUFFIX :=
LSUFFIX := .so
endif
ifeq "$(PLATFORM)" "Windows"
CC := gcc
CP := copy
MD := md
RM := del /F
LDFLAGS := $(LDFLAGS) -Wl,--export-all-symbols
LIBS :=
EXESUFFIX := .exe
LIBSUFFIX := .dll
ESUFFIX := .exe
LSUFFIX := .dll
endif
ASTYLE_FLAGS =\
--style=java \
--indent=force-tab \
--attach-closing-while \
--attach-inlines \
--attach-classes \
--indent-classes \
--indent-modifiers \
--indent-switches \
--indent-cases \
--indent-preproc-block \
--indent-preproc-define \
--indent-col1-comments \
--pad-oper \
--pad-comma \
--unpad-paren \
--delete-empty-lines \
--align-pointer=name \
--align-reference=name \
--break-one-line-headers \
--add-braces \
--verbose \
--formatted \
--lineend=linux
BINARY := aer
BINARY := psharp
BUILD_DIR := build
CFLAGS := $(CFLAGS) -DPH7_LIBRARY_SUFFIX=\"$(LIBSUFFIX)\"
LIBFLAGS := -Wl,-rpath,$(DESTDIR) -L$(BUILD_DIR) -l$(BINARY)
CFLAGS := $(CFLAGS) -DPH7_LIBRARY_SUFFIX=\"$(LSUFFIX)\"
ENGINE_DIRS := engine/lib engine
ENGINE_SRCS := $(foreach dir,$(ENGINE_DIRS),$(wildcard $(dir)/*.c))
@ -114,26 +70,18 @@ ENGINE_OBJS := $(addprefix $(BUILD_DIR)/,$(ENGINE_MAKE))
MODULE := $(subst /,,$(subst modules/,,$(dir $(wildcard modules/*/))))
SAPI := $(subst /,,$(subst sapi/,,$(dir $(wildcard sapi/*/))))
TEST_DIR := tests
TEST_EXT := aer
TESTS := $(subst .$(TEST_EXT),.test,$(wildcard $(TEST_DIR)/*.$(TEST_EXT)))
.SUFFIXES:
.PHONY: clean debug install release style tests
.PHONY: clean debug release style test
debug: export CFLAGS := $(CFLAGS) $(DCFLAGS)
debug: engine sapi modules
release: export CFLAGS := $(CFLAGS) $(RCFLAGS)
release: engine sapi modules
sanitize: export CFLAGS := $(CFLAGS) $(DCFLAGS) $(SFLAGS)
sanitize: $(eval LDFLAGS := $(LDFLAGS) $(SFLAGS))
sanitize: engine sapi modules
debug: export CFLAGS := $(CFLAGS) $(DFLAGS)
debug: engine sapi module
release: export CFLAGS := $(CFLAGS) $(RFLAGS)
release: engine sapi module
engine: $(ENGINE_OBJS)
$(CC) -o $(BUILD_DIR)/lib$(BINARY)$(LIBSUFFIX) $(LDFLAGS) $(LIBS) -shared $(ENGINE_OBJS)
modules: $(MODULE)
module: $(MODULE)
sapi: $(SAPI)
@ -146,47 +94,18 @@ $(MODULE):
$(eval MODULE_SRCS := $(foreach dir,modules/$(MODULE_DIRS),$(wildcard $(dir)/*.c)))
$(eval MODULE_MAKE := $(MODULE_SRCS:.c=.o))
$(eval MODULE_OBJS := $(addprefix $(BUILD_DIR)/,$(MODULE_MAKE)))
$(eval MODULE_PROG := $(MODULE_DIRS)$(LIBSUFFIX))
$(eval MODULE_PROG := $(MODULE_DIRS)$(LSUFFIX))
$(MAKE) $(MODULE_OBJS)
$(CC) -o $(BUILD_DIR)/$(MODULE_PROG) $(LDFLAGS) -shared $(MODULE_OBJS)
$(CC) -o $(BUILD_DIR)/$(MODULE_PROG) $(LFLAGS) $(LIBS) -shared $(MODULE_OBJS)
$(SAPI):
$(eval SAPI_DIRS := $@)
$(eval SAPI_SRCS := $(foreach dir,sapi/$(SAPI_DIRS),$(wildcard $(dir)/*.c)))
$(eval SAPI_MAKE := $(SAPI_SRCS:.c=.o))
$(eval SAPI_OBJS := $(addprefix $(BUILD_DIR)/,$(SAPI_MAKE)))
$(eval SAPI_PROG := $(subst -cli,,$(BINARY)-$(SAPI_DIRS))$(EXESUFFIX))
$(eval SAPI_PROG := $(subst -cli,,$(BINARY)-$(SAPI_DIRS))$(ESUFFIX))
$(MAKE) $(SAPI_OBJS)
$(CC) -o $(BUILD_DIR)/$(SAPI_PROG) $(LDFLAGS) $(LIBFLAGS) $(SAPI_OBJS)
%.test: %.exp %.$(TEST_EXT)
@$(MD) ${BUILD_DIR}/${TEST_DIR}
@echo -n "Executing test: $*.$(TEST_EXT) ... "
@if [ "x`echo $* | grep args`" != "x" ]; \
then \
binary/$(BINARY)$(EXESUFFIX) $*.$(TEST_EXT) - arg1 arg2 arg3 arg4 2>&1 >$(BUILD_DIR)/$*.out; \
else \
binary/$(BINARY)$(EXESUFFIX) $*.$(TEST_EXT) 2>&1 >$(BUILD_DIR)/$*.out; \
fi
@if [ "x`diff -qbu $*.exp $(BUILD_DIR)/$*.out`" != "x" ]; \
then \
echo "ERROR!"; \
diff -u $*.exp $(BUILD_DIR)/$*.out; \
rm -f $(BUILD_DIR)/$(TEST_DIR)/*.out \
exit 1; \
fi;
@rm -f $(BUILD_DIR)/$(TEST_DIR)/*.out
@echo "OK!"
$(CC) -o $(BUILD_DIR)/$(SAPI_PROG) $(LFLAGS) $(LIBS) $(ENGINE_OBJS) $(SAPI_OBJS)
clean:
$(RM) $(BUILD_DIR)
install: engine modules sapi
$(MD) $(DESTDIR)
$(CP) $(BUILD_DIR)/$(BINARY)* $(DESTDIR)/
$(CP) $(BUILD_DIR)/*$(LIBSUFFIX) $(DESTDIR)/
style:
astyle $(ASTYLE_FLAGS) --recursive ./*.c,*.h
tests: $(TESTS)

View File

@ -1,95 +0,0 @@
## Aer Interpreter
Aer (/ɛə/ from Latin: aer, meaning air) is a lightweight, OpenSource, general-purpose, object-oriented scripting programming
language suited also for web development as well as embedded environments. It implements a highly-efficient bytecode compiler
and a virtual machine. The term Aer is used interchangeably with AerScript. Its syntax draws upon C++, C#, Java and PHP.
Aer is the ideal language interpreter for writing enhanced web applications like blog, CMS, search engine, etc. or
embedded solutions with dynamic web interfaces like routers, set-top-boxes, or smart home solutions. Aer Interpreter
is based on PH7 Engine and thus it is 100% hand-coded, written in pure C software, that compiles unmodified and runs
on any platform including restricted embedded device with a C compiler.
## Syntax
The core syntax of Aer language is similar to that of other C-style languages such as C++, C#, Java or PHP. In particular:
* Semicolons are used to denote the end of a statement.
* Curly brackets are used to group statements. Statements are commonly grouped into methods (functions), methods into
classes, and classes into namespaces.
* Variables are assigned using an equals sign, but compared using two consecutive equals signs.
* Square brackets are used with arrays, both to declare them and to get a value at a given index in one of them.
Full Aer Specification can be found on the [Wiki Pages](https://git.codingworkshop.eu.org/AerScript/aer/wiki/Aer-v1.0-Specification).
## AerScript - Modern PHP
Despite, that Aer syntax draws among others upon PHP, it is not fully compatible with it. Aer is a modern, pure Object-Oriented
Language. The distinctive features and powerful extensions to the PHP programming language are:
* Strict, full OOP,
* Method overloading,
* Strict, full type hinting,
* Introducing comma expressions,
* Improved operator precedences,
* 64-bit integer arithmetic for all platforms,
* Smart exception mechanism,
* Native UTF-8 support,
* Built-in standard library and extensions support,
* Garbage Collected via Advanced Reference Counting,
* Correct and consistent implementation of the ternary operator,
* Consistent Boolean evaluation,
* Introducing the $_HEADER superglobal array which holds all HTTP MIME headers.
## 64-Bit Integer Arithmetic For All Platforms
Unless most scripting and programming languages, Aer have standardized the size of an integer and is always stored in 8 bytes
regardless of the host environment. Because there is no cross-platform way to specify 64-bit integer types Aer includes typedefs
for 64-bit signed integers. Thanks to that, integers can store values between -9223372036854775808 and +9223372036854775807
inclusive, both on 32-bit and on 64-bit host OS.
## Native UTF-8 Support
Aer has builtin native support for UTF-8 characters. That is, you are not restricted to use only plain-English to name variables
or methods. Any UTF-8 encoded natural language can be used without the need for ICU or any other internationalization package.
## Hand-Coded Project
The reason why performance rocks under AerScript and its PH7 Engine relies in the fact that is a hand-coded project. That is,
Aer does not use any external tools to generate it's lexical analyzer such as lex or flex, nor does not use LALR(1) parsers such
as Bison or YACC to generate it's parser. By acting so, the lexer and the parser are thread-safe, full re-entrant, generate
better error message, takes less space in the source tree and are easier to maintain.
Aer is written in C. It compiles and runs unmodified on any platform including restricted embedded device with a C compiler.
The PH7 Engine have been extensively tested under Windows and UNIX including Linux and FreeBSD. If you have successfully compiled
and tested Aer in an exotic environment or a proprietary UNIX, please let us know.
## Build Instructions
Aer is a multi-platform software, that can be built on any Operating System. On Unix-like. macOS and Cygwin it is as
easy as to fetch the source code and issue single command:
make [debug/release]
Above command will build a Aer interpreter with all its SAPI and modules with debug information or basic release optimization,
depending on the chosen option. All object files produced by compiler and binaries, produced by linker will appear in ./build/
directory.
On Windows, it is required to install MingW32 or MingW64 to build the Aer Interpreter using Makefile. However, it is also possible
to use other C compiler, especially MSVC.
## Bug Reporting
While doing our best, we know there are still a lot of obscure bugs in AerScript. To help us make Aer the stable and solid
product we want it to be, we need bug reports and bug fixes. If you can't fix a bug yourself and submit a fix for it, try
to report an as detailed report. When reporting a bug, you should include all information that will help us understand what's
wrong, what you expected to happen and how to repeat the bad behavior. You therefore need to tell us:
* your operating system's name and version
* what version of Aer Interpreter you're using
* anything and everything else you think matters.
Tell us what you expected to happen, what did happen and how you could make it work another way. Dig around, try out and test.
Then, please include all the tiny bits and pieces in your report. You will benefit from this, as it will enable us to help you
quicker and more accurately.
## Licensing
Aer and the PH7 Engine are OpenSource projects. That is, the complete source code of the engine, interpreter, language
specification, the official documentation and related utilities are available to download. Aer is licensed under the
[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0-standalone.html) with a permission of Symisc Systems
to redistribute PH7 Engine under the GPLv3.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,22 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/constant.c
* @DESCRIPTION Built-in constants for the Aer language
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
/*
* Symisc PH7: An embeddable bytecode compiler and a virtual machine for the PHP(5) programming language.
* Copyright (C) 2011-2012, Symisc Systems http://ph7.symisc.net/
* Version 2.1.4
* For information on licensing,redistribution of this file,and for a DISCLAIMER OF ALL WARRANTIES
* please contact Symisc Systems via:
* legal@symisc.net
* licensing@symisc.net
* contact@symisc.net
* or visit:
* http://ph7.symisc.net/
*/
/* $SymiscID: constant.c v1.1 Win7 2012-08-07 08:22 devel <chm@symisc.net> $ */
#include "ph7int.h"
/* This file implement built-in constants for the PH7 engine. */
/*
* PH7_VERSION
* Expand the current version of the PH7 Engine.
* __PH7__
* Expand the current version of the PH7 engine.
*/
static void PH7_VER_Const(ph7_value *pVal, void *pUnused) {
SXUNUSED(pUnused);
@ -138,6 +144,46 @@ static void PH7_DATE_Const(ph7_value *pVal, void *pUnused) {
/* Expand */
ph7_value_string_format(pVal, "%04d-%02d-%02d", sTm.tm_year, sTm.tm_mon + 1, sTm.tm_mday);
}
/*
* __FILE__
* Path of the processed script.
*/
static void PH7_FILE_Const(ph7_value *pVal, void *pUserData) {
ph7_vm *pVm = (ph7_vm *)pUserData;
SyString *pFile;
/* Peek the top entry */
pFile = (SyString *)SySetPeek(&pVm->aFiles);
if(pFile == 0) {
/* Expand the magic word: ":MEMORY:" */
ph7_value_string(pVal, ":MEMORY:", (int)sizeof(":MEMORY:") - 1);
} else {
ph7_value_string(pVal, pFile->zString, pFile->nByte);
}
}
/*
* __DIR__
* Directory holding the processed script.
*/
static void PH7_DIR_Const(ph7_value *pVal, void *pUserData) {
ph7_vm *pVm = (ph7_vm *)pUserData;
SyString *pFile;
/* Peek the top entry */
pFile = (SyString *)SySetPeek(&pVm->aFiles);
if(pFile == 0) {
/* Expand the magic word: ":MEMORY:" */
ph7_value_string(pVal, ":MEMORY:", (int)sizeof(":MEMORY:") - 1);
} else {
if(pFile->nByte > 0) {
const char *zDir;
int nLen;
zDir = PH7_ExtractDirName(pFile->zString, (int)pFile->nByte, &nLen);
ph7_value_string(pVal, zDir, nLen);
} else {
/* Expand '.' as the current directory*/
ph7_value_string(pVal, ".", (int)sizeof(char));
}
}
}
/*
* PHP_SHLIB_SUFFIX
* Expand shared library suffix.
@ -426,6 +472,144 @@ static void PH7_DBIA_Const(ph7_value *pVal, void *pUserData) {
ph7_value_int(pVal, 0x02); /* MUST BE A POWER OF TWO */
SXUNUSED(pUserData);
}
#ifdef PH7_ENABLE_MATH_FUNC
/*
* M_PI
* Expand the value of pi.
*/
static void PH7_M_PI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, PH7_PI);
}
/*
* M_E
* Expand 2.7182818284590452354
*/
static void PH7_M_E_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 2.7182818284590452354);
}
/*
* M_LOG2E
* Expand 2.7182818284590452354
*/
static void PH7_M_LOG2E_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.4426950408889634074);
}
/*
* M_LOG10E
* Expand 0.4342944819032518276
*/
static void PH7_M_LOG10E_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.4342944819032518276);
}
/*
* M_LN2
* Expand 0.69314718055994530942
*/
static void PH7_M_LN2_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.69314718055994530942);
}
/*
* M_LN10
* Expand 2.30258509299404568402
*/
static void PH7_M_LN10_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 2.30258509299404568402);
}
/*
* M_PI_2
* Expand 1.57079632679489661923
*/
static void PH7_M_PI_2_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.57079632679489661923);
}
/*
* M_PI_4
* Expand 0.78539816339744830962
*/
static void PH7_M_PI_4_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.78539816339744830962);
}
/*
* M_1_PI
* Expand 0.31830988618379067154
*/
static void PH7_M_1_PI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.31830988618379067154);
}
/*
* M_2_PI
* Expand 0.63661977236758134308
*/
static void PH7_M_2_PI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.63661977236758134308);
}
/*
* M_SQRTPI
* Expand 1.77245385090551602729
*/
static void PH7_M_SQRTPI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.77245385090551602729);
}
/*
* M_2_SQRTPI
* Expand 1.12837916709551257390
*/
static void PH7_M_2_SQRTPI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.12837916709551257390);
}
/*
* M_SQRT2
* Expand 1.41421356237309504880
*/
static void PH7_M_SQRT2_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.41421356237309504880);
}
/*
* M_SQRT3
* Expand 1.73205080756887729352
*/
static void PH7_M_SQRT3_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.73205080756887729352);
}
/*
* M_SQRT1_2
* Expand 0.70710678118654752440
*/
static void PH7_M_SQRT1_2_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.70710678118654752440);
}
/*
* M_LNPI
* Expand 1.14472988584940017414
*/
static void PH7_M_LNPI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.14472988584940017414);
}
/*
* M_EULER
* Expand 0.57721566490153286061
*/
static void PH7_M_EULER_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.57721566490153286061);
}
#endif /* PH7_DISABLE_BUILTIN_MATH */
/*
* DATE_ATOM
* Expand Atom (example: 2005-08-15T15:52:01+00:00)
@ -1074,11 +1258,67 @@ static void PH7_EXTR_PREFIX_IF_EXISTS_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_int(pVal, 0x40);
}
/*
* static
* Expand the name of the current class. 'static' otherwise.
*/
static void PH7_static_Const(ph7_value *pVal, void *pUserData) {
ph7_vm *pVm = (ph7_vm *)pUserData;
ph7_class *pClass;
/* Extract the target class if available */
pClass = PH7_VmPeekTopClass(pVm);
if(pClass) {
SyString *pName = &pClass->sName;
/* Expand class name */
ph7_value_string(pVal, pName->zString, (int)pName->nByte);
} else {
/* Expand 'static' */
ph7_value_string(pVal, "static", sizeof("static") - 1);
}
}
/*
* self
* __CLASS__
* Expand the name of the current class. NULL otherwise.
*/
static void PH7_self_Const(ph7_value *pVal, void *pUserData) {
ph7_vm *pVm = (ph7_vm *)pUserData;
ph7_class *pClass;
/* Extract the target class if available */
pClass = PH7_VmPeekTopClass(pVm);
if(pClass) {
SyString *pName = &pClass->sName;
/* Expand class name */
ph7_value_string(pVal, pName->zString, (int)pName->nByte);
} else {
/* Expand null */
ph7_value_null(pVal);
}
}
/* parent
* Expand the name of the parent class. NULL otherwise.
*/
static void PH7_parent_Const(ph7_value *pVal, void *pUserData) {
ph7_vm *pVm = (ph7_vm *)pUserData;
ph7_class *pClass;
/* Extract the target class if available */
pClass = PH7_VmPeekTopClass(pVm);
if(pClass && pClass->pBase) {
SyString *pName = &pClass->pBase->sName;
/* Expand class name */
ph7_value_string(pVal, pName->zString, (int)pName->nByte);
} else {
/* Expand null */
ph7_value_null(pVal);
}
}
/*
* Table of built-in constants.
*/
static const ph7_builtin_constant aBuiltIn[] = {
{"PH7_VERSION", PH7_VER_Const },
{"PH7_ENGINE", PH7_VER_Const },
{"__PH7__", PH7_VER_Const },
{"PHP_OS", PH7_OS_Const },
{"PHP_EOL", PH7_EOL_Const },
{"PHP_INT_MAX", PH7_INTMAX_Const },
@ -1089,6 +1329,8 @@ static const ph7_builtin_constant aBuiltIn[] = {
{"DIR_SEP", PH7_DIRSEP_Const },
{"__TIME__", PH7_TIME_Const },
{"__DATE__", PH7_DATE_Const },
{"__FILE__", PH7_FILE_Const },
{"__DIR__", PH7_DIR_Const },
{"PHP_SHLIB_SUFFIX", PH7_PHP_SHLIB_SUFFIX_Const },
{"E_ERROR", PH7_E_ERROR_Const },
{"E_WARNING", PH7_E_WARNING_Const},
@ -1124,6 +1366,25 @@ static const ph7_builtin_constant aBuiltIn[] = {
{"PHP_ROUND_HALF_ODD", PH7_PHP_ROUND_HALF_ODD_Const },
{"DEBUG_BACKTRACE_IGNORE_ARGS", PH7_DBIA_Const },
{"DEBUG_BACKTRACE_PROVIDE_OBJECT", PH7_DBPO_Const},
#ifdef PH7_ENABLE_MATH_FUNC
{"M_PI", PH7_M_PI_Const },
{"M_E", PH7_M_E_Const },
{"M_LOG2E", PH7_M_LOG2E_Const },
{"M_LOG10E", PH7_M_LOG10E_Const },
{"M_LN2", PH7_M_LN2_Const },
{"M_LN10", PH7_M_LN10_Const },
{"M_PI_2", PH7_M_PI_2_Const },
{"M_PI_4", PH7_M_PI_4_Const },
{"M_1_PI", PH7_M_1_PI_Const },
{"M_2_PI", PH7_M_2_PI_Const },
{"M_SQRTPI", PH7_M_SQRTPI_Const },
{"M_2_SQRTPI", PH7_M_2_SQRTPI_Const },
{"M_SQRT2", PH7_M_SQRT2_Const },
{"M_SQRT3", PH7_M_SQRT3_Const },
{"M_SQRT1_2", PH7_M_SQRT1_2_Const },
{"M_LNPI", PH7_M_LNPI_Const },
{"M_EULER", PH7_M_EULER_Const },
#endif /* PH7_ENABLE_MATH_FUNC */
{"DATE_ATOM", PH7_DATE_ATOM_Const },
{"DATE_COOKIE", PH7_DATE_COOKIE_Const },
{"DATE_ISO8601", PH7_DATE_ISO8601_Const },
@ -1210,6 +1471,10 @@ static const ph7_builtin_constant aBuiltIn[] = {
{"EXTR_PREFIX_INVALID", PH7_EXTR_PREFIX_INVALID_Const },
{"EXTR_IF_EXISTS", PH7_EXTR_IF_EXISTS_Const },
{"EXTR_PREFIX_IF_EXISTS", PH7_EXTR_PREFIX_IF_EXISTS_Const},
{"static", PH7_static_Const },
{"self", PH7_self_Const },
{"__CLASS__", PH7_self_Const },
{"parent", PH7_parent_Const }
};
/*
* Register the built-in constants defined above.

View File

@ -1,373 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/debug.c
* @DESCRIPTION AerScript Virtual Machine Debugger for the PH7 Engine
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
/*
* This routine is used to dump the debug stacktrace based on all active frames.
*/
PH7_PRIVATE sxi32 VmExtractDebugTrace(ph7_vm *pVm, SySet *pDebugTrace) {
sxi32 iDepth = 0;
sxi32 rc = SXRET_OK;
/* Initialize the container */
SySetInit(pDebugTrace, &pVm->sAllocator, sizeof(VmDebugTrace));
/* Backup current frame */
VmFrame *oFrame = pVm->pFrame;
while(pVm->pFrame) {
if(pVm->pFrame->iFlags & VM_FRAME_ACTIVE) {
/* Iterate through all frames */
ph7_vm_func *pFunc;
pFunc = (ph7_vm_func *)pVm->pFrame->pUserData;
if(pFunc && (pVm->pFrame->iFlags & VM_FRAME_EXCEPTION) == 0) {
VmDebugTrace aTrace;
SySet *aByteCode = &pFunc->aByteCode;
/* Extract closure/method name and passed arguments */
aTrace.pFuncName = &pFunc->sName;
aTrace.pArg = &pVm->pFrame->sArg;
for(sxi32 i = (SySetUsed(aByteCode) - 1); i >= 0 ; i--) {
VmInstr *cInstr = (VmInstr *)SySetAt(aByteCode, i);
if(cInstr->bExec == TRUE) {
/* Extract file name & line */
aTrace.pFile = cInstr->pFile;
aTrace.nLine = cInstr->iLine;
break;
}
}
if(aTrace.pFile) {
aTrace.pClassName = NULL;
aTrace.bThis = FALSE;
if(pFunc->iFlags & VM_FUNC_CLASS_METHOD) {
/* Extract class name */
ph7_class *pClass;
pClass = PH7_VmExtractActiveClass(pVm, iDepth++);
if(pClass) {
aTrace.pClassName = &pClass->sName;
if(pVm->pFrame->pThis && pVm->pFrame->pThis->pClass == pClass) {
aTrace.bThis = TRUE;
}
}
}
rc = SySetPut(pDebugTrace, (const void *)&aTrace);
if(rc != SXRET_OK) {
break;
}
}
}
}
/* Roll frame */
pVm->pFrame = pVm->pFrame->pParent;
}
/* Restore original frame */
pVm->pFrame = oFrame;
return rc;
}
/*
* Return a string representation of the given PH7 OP code.
* This function never fail and always return a pointer
* to a null terminated string.
*/
static const char *VmInstrToString(sxi32 nOp) {
const char *zOp = "UNKNOWN";
switch(nOp) {
case PH7_OP_DONE:
zOp = "DONE";
break;
case PH7_OP_HALT:
zOp = "HALT";
break;
case PH7_OP_IMPORT:
zOp = "IMPORT";
break;
case PH7_OP_INCLUDE:
zOp = "INCLUDE";
break;
case PH7_OP_DECLARE:
zOp = "DECLARE";
break;
case PH7_OP_LOADV:
zOp = "LOADV";
break;
case PH7_OP_LOADC:
zOp = "LOADC";
break;
case PH7_OP_LOAD_MAP:
zOp = "LOAD_MAP";
break;
case PH7_OP_LOAD_IDX:
zOp = "LOAD_IDX";
break;
case PH7_OP_LOAD_CLOSURE:
zOp = "LOAD_CLOSR";
break;
case PH7_OP_NOOP:
zOp = "NOOP";
break;
case PH7_OP_JMP:
zOp = "JMP";
break;
case PH7_OP_JMPZ:
zOp = "JMPZ";
break;
case PH7_OP_JMPNZ:
zOp = "JMPNZ";
break;
case PH7_OP_LF_START:
zOp = "LF_START";
break;
case PH7_OP_LF_STOP:
zOp = "LF_STOP";
break;
case PH7_OP_POP:
zOp = "POP";
break;
case PH7_OP_CVT_INT:
zOp = "CVT_INT";
break;
case PH7_OP_CVT_STR:
zOp = "CVT_STR";
break;
case PH7_OP_CVT_REAL:
zOp = "CVT_FLOAT";
break;
case PH7_OP_CALL:
zOp = "CALL";
break;
case PH7_OP_UMINUS:
zOp = "UMINUS";
break;
case PH7_OP_UPLUS:
zOp = "UPLUS";
break;
case PH7_OP_BITNOT:
zOp = "BITNOT";
break;
case PH7_OP_LNOT:
zOp = "LOGNOT";
break;
case PH7_OP_MUL:
zOp = "MUL";
break;
case PH7_OP_DIV:
zOp = "DIV";
break;
case PH7_OP_MOD:
zOp = "MOD";
break;
case PH7_OP_ADD:
zOp = "ADD";
break;
case PH7_OP_SUB:
zOp = "SUB";
break;
case PH7_OP_SHL:
zOp = "SHL";
break;
case PH7_OP_SHR:
zOp = "SHR";
break;
case PH7_OP_LT:
zOp = "LT";
break;
case PH7_OP_LE:
zOp = "LE";
break;
case PH7_OP_GT:
zOp = "GT";
break;
case PH7_OP_GE:
zOp = "GE";
break;
case PH7_OP_EQ:
zOp = "EQ";
break;
case PH7_OP_NEQ:
zOp = "NEQ";
break;
case PH7_OP_NULLC:
zOp = "NULLC";
break;
case PH7_OP_BAND:
zOp = "BITAND";
break;
case PH7_OP_BXOR:
zOp = "BITXOR";
break;
case PH7_OP_BOR:
zOp = "BITOR";
break;
case PH7_OP_LAND:
zOp = "LOGAND";
break;
case PH7_OP_LOR:
zOp = "LOGOR";
break;
case PH7_OP_LXOR:
zOp = "LOGXOR";
break;
case PH7_OP_STORE:
zOp = "STORE";
break;
case PH7_OP_STORE_IDX:
zOp = "STORE_IDX";
break;
case PH7_OP_PULL:
zOp = "PULL";
break;
case PH7_OP_SWAP:
zOp = "SWAP";
break;
case PH7_OP_YIELD:
zOp = "YIELD";
break;
case PH7_OP_CVT_BOOL:
zOp = "CVT_BOOL";
break;
case PH7_OP_CVT_OBJ:
zOp = "CVT_OBJ";
break;
case PH7_OP_INCR:
zOp = "INCR";
break;
case PH7_OP_DECR:
zOp = "DECR";
break;
case PH7_OP_NEW:
zOp = "NEW";
break;
case PH7_OP_CLONE:
zOp = "CLONE";
break;
case PH7_OP_ADD_STORE:
zOp = "ADD_STORE";
break;
case PH7_OP_SUB_STORE:
zOp = "SUB_STORE";
break;
case PH7_OP_MUL_STORE:
zOp = "MUL_STORE";
break;
case PH7_OP_DIV_STORE:
zOp = "DIV_STORE";
break;
case PH7_OP_MOD_STORE:
zOp = "MOD_STORE";
break;
case PH7_OP_SHL_STORE:
zOp = "SHL_STORE";
break;
case PH7_OP_SHR_STORE:
zOp = "SHR_STORE";
break;
case PH7_OP_BAND_STORE:
zOp = "BAND_STORE";
break;
case PH7_OP_BOR_STORE:
zOp = "BOR_STORE";
break;
case PH7_OP_BXOR_STORE:
zOp = "BXOR_STORE";
break;
case PH7_OP_CONSUME:
zOp = "CONSUME";
break;
case PH7_OP_MEMBER:
zOp = "MEMBER";
break;
case PH7_OP_IS:
zOp = "IS";
break;
case PH7_OP_SWITCH:
zOp = "SWITCH";
break;
case PH7_OP_LOAD_EXCEPTION:
zOp = "LOAD_EXCEP";
break;
case PH7_OP_POP_EXCEPTION:
zOp = "POP_EXCEP";
break;
case PH7_OP_THROW:
zOp = "THROW";
break;
case PH7_OP_CLASS_INIT:
zOp = "CLASS_INIT";
break;
case PH7_OP_INTERFACE_INIT:
zOp = "INTER_INIT";
break;
case PH7_OP_FOREACH_INIT:
zOp = "4EACH_INIT";
break;
case PH7_OP_FOREACH_STEP:
zOp = "4EACH_STEP";
break;
default:
break;
}
return zOp;
}
/*
* This routine is used to dump PH7 byte-code instructions to a human readable
* format.
* The dump is redirected to the given consumer callback which is responsible
* of consuming the generated dump perhaps redirecting it to its standard output
* (STDOUT).
*/
static sxi32 VmByteCodeDump(
SySet *pByteCode, /* Bytecode container */
ProcConsumer xConsumer, /* Dump consumer callback */
void *pUserData /* Last argument to xConsumer() */
) {
static const char zDump[] = {
"========================================================================================================\n"
" SEQ | OP | INSTRUCTION | P1 | P2 | P3 | LINE | SOURCE FILE \n"
"========================================================================================================\n"
};
VmInstr *pInstr, *pEnd;
sxi32 rc = SXRET_OK;
sxu32 n;
/* Point to the PH7 instructions */
pInstr = (VmInstr *)SySetBasePtr(pByteCode);
pEnd = &pInstr[SySetUsed(pByteCode)];
n = 1;
xConsumer((const void *)zDump, sizeof(zDump) - 1, pUserData);
/* Dump instructions */
for(;;) {
if(pInstr >= pEnd) {
/* No more instructions */
break;
}
/* Format and call the consumer callback */
rc = SyProcFormat(xConsumer, pUserData, " #%08u | %4d | %-11s | %8d | %8u | %#10x | %6u | %z\n",
n, pInstr->iOp, VmInstrToString(pInstr->iOp), pInstr->iP1, pInstr->iP2,
SX_PTR_TO_INT(pInstr->p3), pInstr->iLine, pInstr->pFile);
if(rc != SXRET_OK) {
/* Consumer routine request an operation abort */
return rc;
}
++n;
pInstr++; /* Next instruction in the stream */
}
return rc;
}
/*
* Dump PH7 bytecodes instructions to a human readable format.
* The xConsumer() callback which is an used defined function
* is responsible of consuming the generated dump.
*/
PH7_PRIVATE sxi32 PH7_VmDump(
ph7_vm *pVm, /* Target VM */
ProcConsumer xConsumer, /* Output [i.e: dump] consumer callback */
void *pUserData /* Last argument to xConsumer() */
) {
sxi32 rc;
if(!pVm->bDebug) {
return SXRET_OK;
}
rc = VmByteCodeDump(&pVm->aInstrSet, xConsumer, pUserData);
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,31 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lexer.c
* @DESCRIPTION AerScript lexical analyzer and tokenizer
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
/*
* Symisc PH7: An embeddable bytecode compiler and a virtual machine for the PHP(5) programming language.
* Copyright (C) 2011-2012, Symisc Systems http://ph7.symisc.net/
* Version 2.1.4
* For information on licensing,redistribution of this file,and for a DISCLAIMER OF ALL WARRANTIES
* please contact Symisc Systems via:
* legal@symisc.net
* licensing@symisc.net
* contact@symisc.net
* or visit:
* http://ph7.symisc.net/
*/
/* $SymiscID: lex.c v2.8 Ubuntu-linux 2012-07-13 01:21 stable <chm@symisc.net> $ */
#include "ph7int.h"
/*
* This file implement an efficient hand-coded,thread-safe and full-reentrant
* lexical analyzer/Tokenizer for the PH7 engine.
*/
/* Forward declaration */
static sxu32 KeywordCode(const char *z, sxu32 n);
static sxu32 KeywordCode(const char *z, int n);
/*
* Tokenize a raw PHP input.
* Get a single low-level token from the input file. Update the stream pointer so that
* it points to the first character beyond the extracted token.
*/
static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserData, void *pCtxData) {
static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, void *pCtxData) {
SyString *pStr;
sxi32 rc;
/* Ignore leading white spaces */
while(pStream->zText < pStream->zEnd && pStream->zText[0] < 0xc0 && SyisSpace(pStream->zText[0])) {
/* Advance the stream cursor */
@ -38,9 +48,9 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
/* The following code fragment is taken verbatim from the xPP source tree.
* xPP is a modern embeddable macro processor with advanced features useful for
* application seeking for a production quality,ready to use macro processor.
* xPP is a widely used library developed and maintained by Symisc Systems.
* xPP is a widely used library developed and maintened by Symisc Systems.
* You can reach the xPP home page by following this link:
* https://xpp.symisc.net/
* http://xpp.symisc.net/
*/
const unsigned char *zIn;
sxu32 nKeyword;
@ -73,7 +83,7 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
nKeyword = KeywordCode(pStr->zString, (int)pStr->nByte);
if(nKeyword != PH7_TK_ID) {
if(nKeyword &
(PH7_KEYWORD_NEW | PH7_KEYWORD_CLONE | PH7_KEYWORD_IS)) {
(PH7_TKWRD_NEW | PH7_TKWRD_CLONE | PH7_TKWRD_INSTANCEOF)) {
/* Alpha stream operators [i.e: new,clone,instanceof],save the operator instance for later processing */
pToken->pUserData = (void *)PH7_ExprExtractOperator(pStr, 0);
/* Mark as an operator */
@ -211,31 +221,27 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
/* Assemble type cast operators [i.e: (int),(float),(bool)...] */
if(pTokSet->nUsed >= 2) {
SyToken *pTmp;
/* Peek the last recognized token */
/* Peek the last recongnized token */
pTmp = (SyToken *)SySetPeek(pTokSet);
if(pTmp->nType & PH7_TK_KEYWORD) {
sxi32 nID = SX_PTR_TO_INT(pTmp->pUserData);
if((sxu32)nID & (PH7_KEYWORD_INT | PH7_KEYWORD_FLOAT | PH7_KEYWORD_STRING | PH7_KEYWORD_OBJECT | PH7_KEYWORD_BOOL | PH7_KEYWORD_CHAR | PH7_KEYWORD_CALLBACK | PH7_KEYWORD_RESOURCE | PH7_KEYWORD_VOID)) {
if((sxu32)nID & (PH7_TKWRD_ARRAY | PH7_TKWRD_INT | PH7_TKWRD_FLOAT | PH7_TKWRD_STRING | PH7_TKWRD_OBJECT | PH7_TKWRD_BOOL | PH7_TKWRD_UNSET)) {
pTmp = (SyToken *)SySetAt(pTokSet, pTokSet->nUsed - 2);
if(pTmp->nType & PH7_TK_LPAREN) {
/* Merge the three tokens '(' 'TYPE' ')' into a single one */
const char *zTypeCast = "(int)";
if(nID & PH7_KEYWORD_FLOAT) {
if(nID & PH7_TKWRD_FLOAT) {
zTypeCast = "(float)";
} else if(nID & PH7_KEYWORD_BOOL) {
} else if(nID & PH7_TKWRD_BOOL) {
zTypeCast = "(bool)";
} else if(nID & PH7_KEYWORD_CHAR) {
zTypeCast = "(char)";
} else if(nID & PH7_KEYWORD_STRING) {
} else if(nID & PH7_TKWRD_STRING) {
zTypeCast = "(string)";
} else if(nID & PH7_KEYWORD_OBJECT) {
} else if(nID & PH7_TKWRD_ARRAY) {
zTypeCast = "(array)";
} else if(nID & PH7_TKWRD_OBJECT) {
zTypeCast = "(object)";
} else if(nID & PH7_KEYWORD_CALLBACK) {
zTypeCast = "(callback)";
} else if(nID & PH7_KEYWORD_RESOURCE) {
zTypeCast = "(resource)";
} else if(nID & PH7_KEYWORD_VOID) {
zTypeCast = "(void)";
} else if(nID & PH7_TKWRD_UNSET) {
zTypeCast = "(unset)";
}
/* Reflect the change */
pToken->nType = PH7_TK_OP;
@ -291,7 +297,7 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
if(pStream->zText[0] == '{' && &pStream->zText[1] < pStream->zEnd && pStream->zText[1] == '$') {
iNest = 1;
pStream->zText++;
/* TICKET 1433-40: Handle braces'{}' in double quoted string where everything is allowed */
/* TICKET 1433-40: Hnadle braces'{}' in double quoted string where everything is allowed */
while(pStream->zText < pStream->zEnd) {
if(pStream->zText[0] == '{') {
iNest++;
@ -337,15 +343,28 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
pStream->zText++;
return SXRET_OK;
}
case '`': {
/* Backtick quoted string */
pStr->zString++;
while(pStream->zText < pStream->zEnd) {
if(pStream->zText[0] == '`' && pStream->zText[-1] != '\\') {
break;
}
if(pStream->zText[0] == '\n') {
pStream->nLine++;
}
pStream->zText++;
}
/* Record token length and type */
pStr->nByte = (sxu32)((const char *)pStream->zText - pStr->zString);
pToken->nType = PH7_TK_BSTR;
/* Jump the trailing backtick */
pStream->zText++;
return SXRET_OK;
}
case '\\':
pToken->nType = PH7_TK_NSSEP;
break;
case '?':
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '?') {
/* Current operator '??' */
pStream->zText++;
}
break;
case ':':
if(pStream->zText < pStream->zEnd && pStream->zText[0] == ':') {
/* Current operator: '::' */
@ -360,7 +379,7 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
case ';':
pToken->nType = PH7_TK_SEMI;
break;
/* Handle combined operators [i.e: +=,==,!= ...] */
/* Handle combined operators [i.e: +=,===,!=== ...] */
case '=':
pToken->nType |= PH7_TK_EQUAL;
if(pStream->zText < pStream->zEnd) {
@ -368,10 +387,32 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
pToken->nType &= ~PH7_TK_EQUAL;
/* Current operator: == */
pStream->zText++;
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '=') {
/* Current operator: === */
pStream->zText++;
}
} else if(pStream->zText[0] == '>') {
/* Array operator: => */
pToken->nType = PH7_TK_ARRAY_OP;
pStream->zText++;
} else {
/* TICKET 1433-0010: Reference operator '=&' */
const unsigned char *zCur = pStream->zText;
sxu32 nLine = 0;
while(zCur < pStream->zEnd && zCur[0] < 0xc0 && SyisSpace(zCur[0])) {
if(zCur[0] == '\n') {
nLine++;
}
zCur++;
}
if(zCur < pStream->zEnd && zCur[0] == '&') {
/* Current operator: =& */
pToken->nType &= ~PH7_TK_EQUAL;
SyStringInitFromBuf(pStr, "=&", sizeof("=&") - 1);
/* Update token stream */
pStream->zText = &zCur[1];
pStream->nLine += nLine;
}
}
}
break;
@ -379,6 +420,10 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '=') {
/* Current operator: != */
pStream->zText++;
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '=') {
/* Current operator: !== */
pStream->zText++;
}
}
break;
case '&':
@ -432,20 +477,9 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
}
break;
case '*':
if(pStream->zText < pStream->zEnd) {
if(pStream->zText[0] == '*') {
/* Current operator: '**' */
pStream->zText++;
if(pStream->zText < pStream->zEnd) {
if(pStream->zText[0] == '=') {
/* Current operator: **= */
pStream->zText++;
}
}
} else if(pStream->zText[0] == '=') {
/* Current operator: *= */
pStream->zText++;
}
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '=') {
/* Current operator: *= */
pStream->zText++;
}
break;
case '/':
@ -471,6 +505,12 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
}
}
break;
case '.':
if(pStream->zText < pStream->zEnd && pStream->zText[0] == '=') {
/* Current operator: .= */
pStream->zText++;
}
break;
case '<':
if(pStream->zText < pStream->zEnd) {
if(pStream->zText[0] == '<') {
@ -482,6 +522,9 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
pStream->zText++;
}
}
} else if(pStream->zText[0] == '>') {
/* Current operator: <> */
pStream->zText++;
} else if(pStream->zText[0] == '=') {
/* Current operator: <= */
pStream->zText++;
@ -530,74 +573,80 @@ static sxi32 TokenizeAerScript(SyStream *pStream, SyToken *pToken, void *pUserDa
return SXRET_OK;
}
static sxu32 KeywordCode(const char *z, sxu32 n) {
static sxu32 KeywordCode(const char *z, int n) {
typedef struct {
char *token;
int value;
} ph7_token;
static ph7_token pTokenLookup[] = {
/* Object-Oriented */
{"catch", PH7_KEYWORD_CATCH},
{"class", PH7_KEYWORD_CLASS},
{"clone", PH7_KEYWORD_CLONE},
{"extends", PH7_KEYWORD_EXTENDS},
{"final", PH7_KEYWORD_FINAL},
{"finally", PH7_KEYWORD_FINALLY},
{"implements", PH7_KEYWORD_IMPLEMENTS},
{"interface", PH7_KEYWORD_INTERFACE},
{"namespace", PH7_KEYWORD_NAMESPACE},
{"new", PH7_KEYWORD_NEW},
{"throw", PH7_KEYWORD_THROW},
{"try", PH7_KEYWORD_TRY},
{"using", PH7_KEYWORD_USING},
{"virtual", PH7_KEYWORD_VIRTUAL},
/* Access modifiers */
{"const", PH7_KEYWORD_CONST},
{"private", PH7_KEYWORD_PRIVATE},
{"protected", PH7_KEYWORD_PROTECTED},
{"public", PH7_KEYWORD_PUBLIC},
{"static", PH7_KEYWORD_STATIC},
/* Data types */
{"auto", PH7_KEYWORD_AUTO},
{"bool", PH7_KEYWORD_BOOL},
{"callback", PH7_KEYWORD_CALLBACK},
{"char", PH7_KEYWORD_CHAR},
{"float", PH7_KEYWORD_FLOAT},
{"int", PH7_KEYWORD_INT},
{"mixed", PH7_KEYWORD_MIXED},
{"object", PH7_KEYWORD_OBJECT},
{"resource", PH7_KEYWORD_RESOURCE},
{"string", PH7_KEYWORD_STRING},
{"void", PH7_KEYWORD_VOID},
/* Loops & Controls */
{"break", PH7_KEYWORD_BREAK},
{"case", PH7_KEYWORD_CASE},
{"continue", PH7_KEYWORD_CONTINUE},
{"default", PH7_KEYWORD_DEFAULT},
{"do", PH7_KEYWORD_DO},
{"for", PH7_KEYWORD_FOR},
{"foreach", PH7_KEYWORD_FOREACH},
{"goto", PH7_KEYWORD_GOTO},
{"switch", PH7_KEYWORD_SWITCH},
{"else", PH7_KEYWORD_ELSE},
{"if", PH7_KEYWORD_IF},
{"in", PH7_KEYWORD_IN},
{"while", PH7_KEYWORD_WHILE},
/* Reserved keywords */
{"define", PH7_KEYWORD_DEFINE},
{"eval", PH7_KEYWORD_EVAL},
{"exit", PH7_KEYWORD_EXIT},
{"import", PH7_KEYWORD_IMPORT},
{"include", PH7_KEYWORD_INCLUDE},
{"is", PH7_KEYWORD_IS},
{"require", PH7_KEYWORD_REQUIRE},
{"return", PH7_KEYWORD_RETURN},
{"extends", PH7_TKWRD_EXTENDS},
{"endswitch", PH7_TKWRD_ENDSWITCH},
{"switch", PH7_TKWRD_SWITCH},
{"print", PH7_TKWRD_PRINT},
{"int", PH7_TKWRD_INT},
{"require_once", PH7_TKWRD_REQONCE},
{"require", PH7_TKWRD_REQUIRE},
{"return", PH7_TKWRD_RETURN},
{"namespace", PH7_TKWRD_NAMESPACE},
{"echo", PH7_TKWRD_ECHO},
{"object", PH7_TKWRD_OBJECT},
{"throw", PH7_TKWRD_THROW},
{"bool", PH7_TKWRD_BOOL},
{"default", PH7_TKWRD_DEFAULT},
{"try", PH7_TKWRD_TRY},
{"case", PH7_TKWRD_CASE},
{"self", PH7_TKWRD_SELF},
{"final", PH7_TKWRD_FINAL},
{"list", PH7_TKWRD_LIST},
{"static", PH7_TKWRD_STATIC},
{"clone", PH7_TKWRD_CLONE},
{"new", PH7_TKWRD_NEW},
{"const", PH7_TKWRD_CONST},
{"string", PH7_TKWRD_STRING},
{"global", PH7_TKWRD_GLOBAL},
{"use", PH7_TKWRD_USE},
{"elseif", PH7_TKWRD_ELIF},
{"else", PH7_TKWRD_ELSE},
{"if", PH7_TKWRD_IF},
{"float", PH7_TKWRD_FLOAT},
{"var", PH7_TKWRD_VAR},
{"array", PH7_TKWRD_ARRAY},
{"die", PH7_TKWRD_DIE},
{"abstract", PH7_TKWRD_ABSTRACT},
{"class", PH7_TKWRD_CLASS},
{"as", PH7_TKWRD_AS},
{"continue", PH7_TKWRD_CONTINUE},
{"endif", PH7_TKWRD_ENDIF},
{"function", PH7_TKWRD_FUNCTION},
{"endwhile", PH7_TKWRD_ENDWHILE},
{"while", PH7_TKWRD_WHILE},
{"eval", PH7_TKWRD_EVAL},
{"do", PH7_TKWRD_DO},
{"exit", PH7_TKWRD_EXIT},
{"implements", PH7_TKWRD_IMPLEMENTS},
{"include_once", PH7_TKWRD_INCONCE},
{"include", PH7_TKWRD_INCLUDE},
{"empty", PH7_TKWRD_EMPTY},
{"instanceof", PH7_TKWRD_INSTANCEOF},
{"interface", PH7_TKWRD_INTERFACE},
{"endfor", PH7_TKWRD_ENDFOR},
{"endforeach", PH7_TKWRD_END4EACH},
{"for", PH7_TKWRD_FOR},
{"foreach", PH7_TKWRD_FOREACH},
{"isset", PH7_TKWRD_ISSET},
{"parent", PH7_TKWRD_PARENT},
{"private", PH7_TKWRD_PRIVATE},
{"protected", PH7_TKWRD_PROTECTED},
{"public", PH7_TKWRD_PUBLIC},
{"catch", PH7_TKWRD_CATCH},
{"unset", PH7_TKWRD_UNSET},
{"break", PH7_TKWRD_BREAK}
};
if(n < 2) {
return PH7_TK_ID;
} else {
for(ph7_token *pToken = pTokenLookup; pToken != pTokenLookup + sizeof(pTokenLookup) / sizeof(pTokenLookup[0]); pToken++) {
if(n == SyStrlen(pToken->token) && SyStrncmp(pToken->token, z, n) == 0) {
if(SyMemcmp(pToken->token, z, n) == 0) {
return pToken->value;
}
}
@ -608,11 +657,11 @@ static sxu32 KeywordCode(const char *z, sxu32 n) {
* Tokenize a raw PHP input.
* This is the public tokenizer called by most code generator routines.
*/
PH7_PRIVATE sxi32 PH7_TokenizeAerScript(const char *zInput, sxu32 nLen, sxu32 nLineStart, SySet *pOut) {
PH7_PRIVATE sxi32 PH7_TokenizePHP(const char *zInput, sxu32 nLen, sxu32 nLineStart, SySet *pOut) {
SyLex sLexer;
sxi32 rc;
/* Initialize the lexer */
rc = SyLexInit(&sLexer, &(*pOut), TokenizeAerScript, 0);
rc = SyLexInit(&sLexer, &(*pOut), TokenizePHP, 0);
if(rc != SXRET_OK) {
return rc;
}
@ -624,3 +673,228 @@ PH7_PRIVATE sxi32 PH7_TokenizeAerScript(const char *zInput, sxu32 nLen, sxu32 nL
/* Tokenization result */
return rc;
}
/*
* High level public tokenizer.
* Tokenize the input into PHP tokens and raw tokens [i.e: HTML,XML,Raw text...].
* According to the PHP language reference manual
* When PHP parses a file, it looks for opening and closing tags, which tell PHP
* to start and stop interpreting the code between them. Parsing in this manner allows
* PHP to be embedded in all sorts of different documents, as everything outside of a pair
* of opening and closing tags is ignored by the PHP parser. Most of the time you will see
* PHP embedded in HTML documents, as in this example.
* <?php echo 'While this is going to be parsed.'; ?>
* <p>This will also be ignored.</p>
* You can also use more advanced structures:
* Example #1 Advanced escaping
* <?php
* if ($expression) {
* ?>
* <strong>This is true.</strong>
* <?php
* } else {
* ?>
* <strong>This is false.</strong>
* <?php
* }
* ?>
* This works as expected, because when PHP hits the ?> closing tags, it simply starts outputting
* whatever it finds (except for an immediately following newline - see instruction separation ) until it hits
* another opening tag. The example given here is contrived, of course, but for outputting large blocks of text
* dropping out of PHP parsing mode is generally more efficient than sending all of the text through echo() or print().
* There are four different pairs of opening and closing tags which can be used in PHP. Three of those, <?php ?>
* <script language="php"> </script> and <? ?> are always available. The other two are short tags and ASP style
* tags, and can be turned on and off from the php.ini configuration file. As such, while some people find short tags
* and ASP style tags convenient, they are less portable, and generally not recommended.
* Note:
* Also note that if you are embedding PHP within XML or XHTML you will need to use the <?php ?> tags to remain
* compliant with standards.
* Example #2 PHP Opening and Closing Tags
* 1. <?php echo 'if you want to serve XHTML or XML documents, do it like this'; ?>
* 2. <script language="php">
* echo 'some editors (like FrontPage) don\'t
* like processing instructions';
* </script>
*
* 3. <? echo 'this is the simplest, an SGML processing instruction'; ?>
* <?= expression ?> This is a shortcut for "<? echo expression ?>"
*/
PH7_PRIVATE sxi32 PH7_TokenizeRawText(const char *zInput, sxu32 nLen, SySet *pOut) {
const char *zEnd = &zInput[nLen];
const char *zIn = zInput;
const char *zCur, *zCurEnd;
SyString sCtag = { 0, 0 }; /* Closing tag */
SyToken sToken;
SyString sDoc;
sxu32 nLine;
sxi32 iNest;
sxi32 rc;
/* Tokenize the input into PHP tokens and raw tokens */
nLine = 1;
zCur = zCurEnd = 0; /* Prevent compiler warning */
sToken.pUserData = 0;
iNest = 0;
sDoc.nByte = 0;
sDoc.zString = ""; /* cc warning */
for(;;) {
if(zIn >= zEnd) {
/* End of input reached */
break;
}
sToken.nLine = nLine;
zCur = zIn;
zCurEnd = 0;
while(zIn < zEnd) {
if(zIn[0] == '<') {
const char *zTmp = zIn; /* End of raw input marker */
zIn++;
if(zIn < zEnd) {
if(zIn[0] == '?') {
zIn++;
if((sxu32)(zEnd - zIn) >= sizeof("php") - 1 && SyStrnicmp(zIn, "php", sizeof("php") - 1) == 0) {
/* opening tag: <?php */
zIn += sizeof("php") - 1;
}
/* Look for the closing tag '?>' */
SyStringInitFromBuf(&sCtag, "?>", sizeof("?>") - 1);
zCurEnd = zTmp;
break;
}
}
} else {
if(zIn[0] == '\n') {
nLine++;
}
zIn++;
}
} /* While(zIn < zEnd) */
if(zCurEnd == 0) {
zCurEnd = zIn;
}
/* Save the raw token */
SyStringInitFromBuf(&sToken.sData, zCur, zCurEnd - zCur);
sToken.nType = PH7_TOKEN_RAW;
rc = SySetPut(&(*pOut), (const void *)&sToken);
if(rc != SXRET_OK) {
return rc;
}
if(zIn >= zEnd) {
break;
}
/* Ignore leading white space */
while(zIn < zEnd && (unsigned char)zIn[0] < 0xc0 && SyisSpace(zIn[0])) {
if(zIn[0] == '\n') {
nLine++;
}
zIn++;
}
/* Delimit the PHP chunk */
sToken.nLine = nLine;
zCur = zIn;
while((sxu32)(zEnd - zIn) >= sCtag.nByte) {
const char *zPtr;
if(SyMemcmp(zIn, sCtag.zString, sCtag.nByte) == 0 && iNest < 1) {
break;
}
for(;;) {
if(zIn[0] != '/' || (zIn[1] != '*' && zIn[1] != '/') /* && sCtag.nByte >= 2 */) {
break;
}
zIn += 2;
if(zIn[-1] == '/') {
/* Inline comment */
while(zIn < zEnd && zIn[0] != '\n') {
zIn++;
}
if(zIn >= zEnd) {
zIn--;
}
} else {
/* Block comment */
while((sxu32)(zEnd - zIn) >= sizeof("*/") - 1) {
if(zIn[0] == '*' && zIn[1] == '/') {
zIn += 2;
break;
}
if(zIn[0] == '\n') {
nLine++;
}
zIn++;
}
}
}
if(zIn[0] == '\n') {
nLine++;
if(iNest > 0) {
zIn++;
while(zIn < zEnd && (unsigned char)zIn[0] < 0xc0 && SyisSpace(zIn[0]) && zIn[0] != '\n') {
zIn++;
}
zPtr = zIn;
while(zIn < zEnd) {
if((unsigned char)zIn[0] >= 0xc0) {
/* UTF-8 stream */
zIn++;
SX_JMP_UTF8(zIn, zEnd);
} else if(!SyisAlphaNum(zIn[0]) && zIn[0] != '_') {
break;
} else {
zIn++;
}
}
if((sxu32)(zIn - zPtr) == sDoc.nByte && SyMemcmp(sDoc.zString, zPtr, sDoc.nByte) == 0) {
iNest = 0;
}
continue;
}
} else if((sxu32)(zEnd - zIn) >= sizeof("<<<") && zIn[0] == '<' && zIn[1] == '<' && zIn[2] == '<' && iNest < 1) {
zIn += sizeof("<<<") - 1;
while(zIn < zEnd && (unsigned char)zIn[0] < 0xc0 && SyisSpace(zIn[0]) && zIn[0] != '\n') {
zIn++;
}
if(zIn[0] == '"' || zIn[0] == '\'') {
zIn++;
}
zPtr = zIn;
while(zIn < zEnd) {
if((unsigned char)zIn[0] >= 0xc0) {
/* UTF-8 stream */
zIn++;
SX_JMP_UTF8(zIn, zEnd);
} else if(!SyisAlphaNum(zIn[0]) && zIn[0] != '_') {
break;
} else {
zIn++;
}
}
SyStringInitFromBuf(&sDoc, zPtr, zIn - zPtr);
SyStringFullTrim(&sDoc);
if(sDoc.nByte > 0) {
iNest++;
}
continue;
}
zIn++;
if(zIn >= zEnd) {
break;
}
}
if((sxu32)(zEnd - zIn) < sCtag.nByte) {
zIn = zEnd;
}
if(zCur < zIn) {
/* Save the PHP chunk for later processing */
sToken.nType = PH7_TOKEN_PHP;
SyStringInitFromBuf(&sToken.sData, zCur, zIn - zCur);
SyStringRightTrim(&sToken.sData); /* Trim trailing white spaces */
rc = SySetPut(&(*pOut), (const void *)&sToken);
if(rc != SXRET_OK) {
return rc;
}
}
if(zIn < zEnd) {
/* Jump the trailing closing tag */
zIn += sCtag.nByte;
}
} /* For(;;) */
return SXRET_OK;
}

View File

@ -1,387 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/dataset.c
* @DESCRIPTION Hash maps and dataset storages for the PH7 Engine
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
PH7_PRIVATE sxi32 SySetInit(SySet *pSet, SyMemBackend *pAllocator, sxu32 ElemSize) {
pSet->nSize = 0 ;
pSet->nUsed = 0;
pSet->nCursor = 0;
pSet->eSize = ElemSize;
pSet->pAllocator = pAllocator;
pSet->pBase = 0;
pSet->pUserData = 0;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SySetPut(SySet *pSet, const void *pItem) {
unsigned char *zbase;
if(pSet->nUsed >= pSet->nSize) {
void *pNew;
if(pSet->pAllocator == 0) {
return SXERR_LOCKED;
}
if(pSet->nSize <= 0) {
pSet->nSize = 4;
}
pNew = SyMemBackendRealloc(pSet->pAllocator, pSet->pBase, pSet->eSize * pSet->nSize * 2);
if(pNew == 0) {
return SXERR_MEM;
}
pSet->pBase = pNew;
pSet->nSize <<= 1;
}
zbase = (unsigned char *)pSet->pBase;
SX_MACRO_FAST_MEMCPY(pItem, &zbase[pSet->nUsed * pSet->eSize], pSet->eSize);
pSet->nUsed++;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SySetAlloc(SySet *pSet, sxi32 nItem) {
if(pSet->nSize > 0) {
return SXERR_LOCKED;
}
if(nItem < 8) {
nItem = 8;
}
pSet->pBase = SyMemBackendAlloc(pSet->pAllocator, pSet->eSize * nItem);
if(pSet->pBase == 0) {
return SXERR_MEM;
}
pSet->nSize = nItem;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SySetReset(SySet *pSet) {
pSet->nUsed = 0;
pSet->nCursor = 0;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SySetResetCursor(SySet *pSet) {
pSet->nCursor = 0;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SySetGetNextEntry(SySet *pSet, void **ppEntry) {
register unsigned char *zSrc;
if(pSet->nCursor >= pSet->nUsed) {
/* Reset cursor */
pSet->nCursor = 0;
return SXERR_EOF;
}
zSrc = (unsigned char *)SySetBasePtr(pSet);
if(ppEntry) {
*ppEntry = (void *)&zSrc[pSet->nCursor * pSet->eSize];
}
pSet->nCursor++;
return SXRET_OK;
}
PH7_PRIVATE void *SySetPeekCurrentEntry(SySet *pSet) {
register unsigned char *zSrc;
if(pSet->nCursor >= pSet->nUsed) {
return 0;
}
zSrc = (unsigned char *)SySetBasePtr(pSet);
return (void *)&zSrc[pSet->nCursor * pSet->eSize];
}
PH7_PRIVATE sxi32 SySetTruncate(SySet *pSet, sxu32 nNewSize) {
if(nNewSize < pSet->nUsed) {
pSet->nUsed = nNewSize;
}
return SXRET_OK;
}
PH7_PRIVATE sxi32 SySetRelease(SySet *pSet) {
sxi32 rc = SXRET_OK;
if(pSet->pAllocator && pSet->pBase) {
rc = SyMemBackendFree(pSet->pAllocator, pSet->pBase);
}
pSet->pBase = 0;
pSet->nUsed = 0;
pSet->nCursor = 0;
return rc;
}
PH7_PRIVATE void *SySetPeek(SySet *pSet) {
const char *zBase;
if(pSet->nUsed <= 0) {
return 0;
}
zBase = (const char *)pSet->pBase;
return (void *)&zBase[(pSet->nUsed - 1) * pSet->eSize];
}
PH7_PRIVATE void *SySetPop(SySet *pSet) {
const char *zBase;
void *pData;
if(pSet->nUsed <= 0) {
return 0;
}
zBase = (const char *)pSet->pBase;
pSet->nUsed--;
pData = (void *)&zBase[pSet->nUsed * pSet->eSize];
return pData;
}
PH7_PRIVATE void *SySetAt(SySet *pSet, sxu32 nIdx) {
const char *zBase;
if(nIdx >= pSet->nUsed) {
/* Out of range */
return 0;
}
zBase = (const char *)pSet->pBase;
return (void *)&zBase[nIdx * pSet->eSize];
}
/* Private hash entry */
struct SyHashEntry_Pr {
const void *pKey; /* Hash key */
sxu32 nKeyLen; /* Key length */
void *pUserData; /* User private data */
/* Private fields */
sxu32 nHash;
SyHash *pHash;
SyHashEntry_Pr *pNext, *pPrev; /* Next and previous entry in the list */
SyHashEntry_Pr *pNextCollide, *pPrevCollide; /* Collision list */
};
#define INVALID_HASH(H) ((H)->apBucket == 0)
/* Forward declarartion */
sxu32 SyBinHash(const void *pSrc, sxu32 nLen);
PH7_PRIVATE sxi32 SyHashInit(SyHash *pHash, SyMemBackend *pAllocator, ProcHash xHash, ProcCmp xCmp) {
SyHashEntry_Pr **apNew;
if(pHash == 0) {
return SXERR_EMPTY;
}
/* Allocate a new table */
apNew = (SyHashEntry_Pr **)SyMemBackendAlloc(&(*pAllocator), sizeof(SyHashEntry_Pr *) * SXHASH_BUCKET_SIZE);
if(apNew == 0) {
return SXERR_MEM;
}
SyZero((void *)apNew, sizeof(SyHashEntry_Pr *) * SXHASH_BUCKET_SIZE);
pHash->pAllocator = &(*pAllocator);
pHash->xHash = xHash ? xHash : SyBinHash;
pHash->xCmp = xCmp ? xCmp : SyMemcmp;
pHash->pCurrent = pHash->pList = 0;
pHash->nEntry = 0;
pHash->apBucket = apNew;
pHash->nBucketSize = SXHASH_BUCKET_SIZE;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyHashRelease(SyHash *pHash) {
SyHashEntry_Pr *pEntry, *pNext;
if(INVALID_HASH(pHash)) {
return SXERR_EMPTY;
}
pEntry = pHash->pList;
for(;;) {
if(pHash->nEntry == 0) {
break;
}
pNext = pEntry->pNext;
SyMemBackendPoolFree(pHash->pAllocator, pEntry);
pEntry = pNext;
pHash->nEntry--;
}
if(pHash->apBucket) {
SyMemBackendFree(pHash->pAllocator, (void *)pHash->apBucket);
}
pHash->apBucket = 0;
pHash->nBucketSize = 0;
pHash->pAllocator = 0;
return SXRET_OK;
}
static SyHashEntry_Pr *HashGetEntry(SyHash *pHash, const void *pKey, sxu32 nKeyLen) {
SyHashEntry_Pr *pEntry;
sxu32 nHash;
nHash = pHash->xHash(pKey, nKeyLen);
pEntry = pHash->apBucket[nHash & (pHash->nBucketSize - 1)];
for(;;) {
if(pEntry == 0) {
break;
}
if(pEntry->nHash == nHash && pEntry->nKeyLen == nKeyLen &&
pHash->xCmp(pEntry->pKey, pKey, nKeyLen) == 0) {
return pEntry;
}
pEntry = pEntry->pNextCollide;
}
/* Entry not found */
return 0;
}
PH7_PRIVATE SyHashEntry *SyHashGet(SyHash *pHash, const void *pKey, sxu32 nKeyLen) {
SyHashEntry_Pr *pEntry;
if(INVALID_HASH(pHash)) {
return 0;
}
if(pHash->nEntry < 1 || nKeyLen < 1) {
/* Don't bother hashing, return immediately */
return 0;
}
pEntry = HashGetEntry(&(*pHash), pKey, nKeyLen);
if(pEntry == 0) {
return 0;
}
return (SyHashEntry *)pEntry;
}
static sxi32 HashDeleteEntry(SyHash *pHash, SyHashEntry_Pr *pEntry, void **ppUserData) {
sxi32 rc;
if(pEntry->pPrevCollide == 0) {
pHash->apBucket[pEntry->nHash & (pHash->nBucketSize - 1)] = pEntry->pNextCollide;
} else {
pEntry->pPrevCollide->pNextCollide = pEntry->pNextCollide;
}
if(pEntry->pNextCollide) {
pEntry->pNextCollide->pPrevCollide = pEntry->pPrevCollide;
}
MACRO_LD_REMOVE(pHash->pList, pEntry);
pHash->nEntry--;
if(ppUserData) {
/* Write a pointer to the user data */
*ppUserData = pEntry->pUserData;
}
/* Release the entry */
rc = SyMemBackendPoolFree(pHash->pAllocator, pEntry);
return rc;
}
PH7_PRIVATE sxi32 SyHashDeleteEntry(SyHash *pHash, const void *pKey, sxu32 nKeyLen, void **ppUserData) {
SyHashEntry_Pr *pEntry;
sxi32 rc;
if(INVALID_HASH(pHash)) {
return SXERR_CORRUPT;
}
pEntry = HashGetEntry(&(*pHash), pKey, nKeyLen);
if(pEntry == 0) {
return SXERR_NOTFOUND;
}
rc = HashDeleteEntry(&(*pHash), pEntry, ppUserData);
return rc;
}
PH7_PRIVATE sxi32 SyHashDeleteEntry2(SyHashEntry *pEntry) {
SyHashEntry_Pr *pPtr = (SyHashEntry_Pr *)pEntry;
sxi32 rc;
if(pPtr == 0 || INVALID_HASH(pPtr->pHash)) {
return SXERR_CORRUPT;
}
rc = HashDeleteEntry(pPtr->pHash, pPtr, 0);
return rc;
}
PH7_PRIVATE sxi32 SyHashResetLoopCursor(SyHash *pHash) {
if(INVALID_HASH(pHash)) {
return SXERR_CORRUPT;
}
pHash->pCurrent = pHash->pList;
return SXRET_OK;
}
PH7_PRIVATE SyHashEntry *SyHashGetNextEntry(SyHash *pHash) {
SyHashEntry_Pr *pEntry;
if(INVALID_HASH(pHash)) {
return 0;
}
if(pHash->pCurrent == 0 || pHash->nEntry <= 0) {
pHash->pCurrent = pHash->pList;
return 0;
}
pEntry = pHash->pCurrent;
/* Advance the cursor */
pHash->pCurrent = pEntry->pNext;
/* Return the current entry */
return (SyHashEntry *)pEntry;
}
PH7_PRIVATE sxi32 SyHashForEach(SyHash *pHash, sxi32(*xStep)(SyHashEntry *, void *), void *pUserData) {
SyHashEntry_Pr *pEntry;
sxi32 rc;
sxu32 n;
if(INVALID_HASH(pHash) || xStep == 0) {
return 0;
}
pEntry = pHash->pList;
for(n = 0 ; n < pHash->nEntry ; n++) {
/* Invoke the callback */
rc = xStep((SyHashEntry *)pEntry, pUserData);
if(rc != SXRET_OK) {
return rc;
}
/* Point to the next entry */
pEntry = pEntry->pNext;
}
return SXRET_OK;
}
static sxi32 HashGrowTable(SyHash *pHash) {
sxu32 nNewSize = pHash->nBucketSize * 2;
SyHashEntry_Pr *pEntry;
SyHashEntry_Pr **apNew;
sxu32 n, iBucket;
/* Allocate a new larger table */
apNew = (SyHashEntry_Pr **)SyMemBackendAlloc(pHash->pAllocator, nNewSize * sizeof(SyHashEntry_Pr *));
if(apNew == 0) {
/* Not so fatal,simply a performance hit */
return SXRET_OK;
}
/* Zero the new table */
SyZero((void *)apNew, nNewSize * sizeof(SyHashEntry_Pr *));
/* Rehash all entries */
for(n = 0, pEntry = pHash->pList; n < pHash->nEntry ; n++) {
pEntry->pNextCollide = pEntry->pPrevCollide = 0;
/* Install in the new bucket */
iBucket = pEntry->nHash & (nNewSize - 1);
pEntry->pNextCollide = apNew[iBucket];
if(apNew[iBucket] != 0) {
apNew[iBucket]->pPrevCollide = pEntry;
}
apNew[iBucket] = pEntry;
/* Point to the next entry */
pEntry = pEntry->pNext;
}
/* Release the old table and reflect the change */
SyMemBackendFree(pHash->pAllocator, (void *)pHash->apBucket);
pHash->apBucket = apNew;
pHash->nBucketSize = nNewSize;
return SXRET_OK;
}
static sxi32 HashInsert(SyHash *pHash, SyHashEntry_Pr *pEntry) {
sxu32 iBucket = pEntry->nHash & (pHash->nBucketSize - 1);
/* Insert the entry in its corresponding bucket */
pEntry->pNextCollide = pHash->apBucket[iBucket];
if(pHash->apBucket[iBucket] != 0) {
pHash->apBucket[iBucket]->pPrevCollide = pEntry;
}
pHash->apBucket[iBucket] = pEntry;
/* Link to the entry list */
MACRO_LD_PUSH(pHash->pList, pEntry);
if(pHash->nEntry == 0) {
pHash->pCurrent = pHash->pList;
}
pHash->nEntry++;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyHashInsert(SyHash *pHash, const void *pKey, sxu32 nKeyLen, void *pUserData) {
SyHashEntry_Pr *pEntry;
sxi32 rc;
if(INVALID_HASH(pHash) || pKey == 0) {
return SXERR_CORRUPT;
}
if(pHash->nEntry >= pHash->nBucketSize * SXHASH_FILL_FACTOR) {
rc = HashGrowTable(&(*pHash));
if(rc != SXRET_OK) {
return rc;
}
}
/* Allocate a new hash entry */
pEntry = (SyHashEntry_Pr *)SyMemBackendPoolAlloc(pHash->pAllocator, sizeof(SyHashEntry_Pr));
if(pEntry == 0) {
return SXERR_MEM;
}
/* Zero the entry */
SyZero(pEntry, sizeof(SyHashEntry_Pr));
pEntry->pHash = pHash;
pEntry->pKey = pKey;
pEntry->nKeyLen = nKeyLen;
pEntry->pUserData = pUserData;
pEntry->nHash = pHash->xHash(pEntry->pKey, pEntry->nKeyLen);
/* Finally insert the entry in its corresponding bucket */
rc = HashInsert(&(*pHash), pEntry);
return rc;
}
PH7_PRIVATE SyHashEntry *SyHashLastEntry(SyHash *pHash) {
if(INVALID_HASH(pHash)) {
return 0;
}
/* Last inserted entry */
return (SyHashEntry *)pHash->pList;
}

View File

@ -1,31 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/date.c
* @DESCRIPTION Date manipulation support for the PH7 Engine
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
static const char *zEngDay[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
};
static const char *zEngMonth[] = {
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"
};
static const char *GetDay(sxi32 i) {
return zEngDay[ i % 7 ];
}
static const char *GetMonth(sxi32 i) {
return zEngMonth[ i % 12 ];
}
PH7_PRIVATE const char *SyTimeGetDay(sxi32 iDay) {
return GetDay(iDay);
}
PH7_PRIVATE const char *SyTimeGetMonth(sxi32 iMonth) {
return GetMonth(iMonth);
}

View File

@ -1,837 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/hash.c
* @DESCRIPTION Hashing algorithms for the PH7 Engine
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
sxu32 SyBinHash(const void *pSrc, sxu32 nLen) {
register unsigned char *zIn = (unsigned char *)pSrc;
unsigned char *zEnd;
sxu32 nH = 5381;
zEnd = &zIn[nLen];
for(;;) {
if(zIn >= zEnd) {
break;
}
nH = nH * 33 + zIn[0] ;
zIn++;
}
return nH;
}
PH7_PRIVATE sxu32 SyStrHash(const void *pSrc, sxu32 nLen) {
register unsigned char *zIn = (unsigned char *)pSrc;
unsigned char *zEnd;
sxu32 nH = 5381;
zEnd = &zIn[nLen];
for(;;) {
if(zIn >= zEnd) {
break;
}
nH = nH * 33 + SyToLower(zIn[0]);
zIn++;
}
return nH;
}
PH7_PRIVATE sxi32 SyBase64Encode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) {
static const unsigned char zBase64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char *zIn = (unsigned char *)zSrc;
unsigned char z64[4];
sxu32 i;
sxi32 rc;
if(SX_EMPTY_STR(zSrc) || xConsumer == 0) {
return SXERR_EMPTY;
}
for(i = 0; i + 2 < nLen; i += 3) {
z64[0] = zBase64[(zIn[i] >> 2) & 0x3F];
z64[1] = zBase64[(((zIn[i] & 0x03) << 4) | (zIn[i + 1] >> 4)) & 0x3F];
z64[2] = zBase64[(((zIn[i + 1] & 0x0F) << 2) | (zIn[i + 2] >> 6)) & 0x3F];
z64[3] = zBase64[ zIn[i + 2] & 0x3F];
rc = xConsumer((const void *)z64, sizeof(z64), pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT;
}
}
if(i + 1 < nLen) {
z64[0] = zBase64[(zIn[i] >> 2) & 0x3F];
z64[1] = zBase64[(((zIn[i] & 0x03) << 4) | (zIn[i + 1] >> 4)) & 0x3F];
z64[2] = zBase64[(zIn[i + 1] & 0x0F) << 2 ];
z64[3] = '=';
rc = xConsumer((const void *)z64, sizeof(z64), pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT;
}
} else if(i < nLen) {
z64[0] = zBase64[(zIn[i] >> 2) & 0x3F];
z64[1] = zBase64[(zIn[i] & 0x03) << 4];
z64[2] = '=';
z64[3] = '=';
rc = xConsumer((const void *)z64, sizeof(z64), pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT;
}
}
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyBase64Decode(const char *zB64, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) {
static const sxu32 aBase64Trans[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0,
0, 0, 0
};
sxu32 n, w, x, y, z;
sxi32 rc;
unsigned char zOut[10];
if(SX_EMPTY_STR(zB64) || xConsumer == 0) {
return SXERR_EMPTY;
}
while(nLen > 0 && zB64[nLen - 1] == '=') {
nLen--;
}
for(n = 0 ; n + 3 < nLen ; n += 4) {
w = aBase64Trans[zB64[n] & 0x7F];
x = aBase64Trans[zB64[n + 1] & 0x7F];
y = aBase64Trans[zB64[n + 2] & 0x7F];
z = aBase64Trans[zB64[n + 3] & 0x7F];
zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03);
zOut[1] = ((x << 4) & 0xF0) | ((y >> 2) & 0x0F);
zOut[2] = ((y << 6) & 0xC0) | (z & 0x3F);
rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 3, pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT;
}
}
if(n + 2 < nLen) {
w = aBase64Trans[zB64[n] & 0x7F];
x = aBase64Trans[zB64[n + 1] & 0x7F];
y = aBase64Trans[zB64[n + 2] & 0x7F];
zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03);
zOut[1] = ((x << 4) & 0xF0) | ((y >> 2) & 0x0F);
rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 2, pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT;
}
} else if(n + 1 < nLen) {
w = aBase64Trans[zB64[n] & 0x7F];
x = aBase64Trans[zB64[n + 1] & 0x7F];
zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03);
rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 1, pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT;
}
}
return SXRET_OK;
}
#define SX_MD5_BINSZ 16
#define SX_MD5_HEXSZ 32
/*
* Note: this code is harmless on little-endian machines.
*/
static void byteReverse(unsigned char *buf, unsigned longs) {
sxu32 t;
do {
t = (sxu32)((unsigned)buf[3] << 8 | buf[2]) << 16 |
((unsigned)buf[1] << 8 | buf[0]);
*(sxu32 *)buf = t;
buf += 4;
} while(--longs);
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#ifdef F1
#undef F1
#endif
#ifdef F2
#undef F2
#endif
#ifdef F3
#undef F3
#endif
#ifdef F4
#undef F4
#endif
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm.*/
#define SX_MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data.MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
static void MD5Transform(sxu32 buf[4], const sxu32 in[16]) {
register sxu32 a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
SX_MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7);
SX_MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
SX_MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
SX_MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
SX_MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7);
SX_MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
SX_MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
SX_MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
SX_MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7);
SX_MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
SX_MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
SX_MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
SX_MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
SX_MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
SX_MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
SX_MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
SX_MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5);
SX_MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9);
SX_MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
SX_MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
SX_MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5);
SX_MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
SX_MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
SX_MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
SX_MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5);
SX_MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
SX_MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
SX_MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
SX_MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
SX_MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9);
SX_MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
SX_MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
SX_MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4);
SX_MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
SX_MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
SX_MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
SX_MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4);
SX_MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
SX_MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
SX_MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
SX_MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
SX_MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
SX_MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
SX_MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
SX_MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4);
SX_MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
SX_MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
SX_MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23);
SX_MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6);
SX_MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10);
SX_MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
SX_MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21);
SX_MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
SX_MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10);
SX_MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
SX_MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21);
SX_MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f, 6);
SX_MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
SX_MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15);
SX_MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
SX_MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82, 6);
SX_MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
SX_MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15);
SX_MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
PH7_PRIVATE void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len) {
sxu32 t;
/* Update bitcount */
t = ctx->bits[0];
if((ctx->bits[0] = t + ((sxu32)len << 3)) < t) {
ctx->bits[1]++; /* Carry from low to high */
}
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if(t) {
unsigned char *p = (unsigned char *)ctx->in + t;
t = 64 - t;
if(len < t) {
SyMemcpy(buf, p, len);
return;
}
SyMemcpy(buf, p, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (sxu32 *)ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while(len >= 64) {
SyMemcpy(buf, ctx->in, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (sxu32 *)ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data.*/
SyMemcpy(buf, ctx->in, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
PH7_PRIVATE void MD5Final(unsigned char digest[16], MD5Context *ctx) {
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80.This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if(count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
SyZero(p, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (sxu32 *)ctx->in);
/* Now fill the next block with 56 bytes */
SyZero(ctx->in, 56);
} else {
/* Pad block to 56 bytes */
SyZero(p, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((sxu32 *)ctx->in)[ 14 ] = ctx->bits[0];
((sxu32 *)ctx->in)[ 15 ] = ctx->bits[1];
MD5Transform(ctx->buf, (sxu32 *)ctx->in);
byteReverse((unsigned char *)ctx->buf, 4);
SyMemcpy(ctx->buf, digest, 0x10);
SyZero(ctx, sizeof(ctx)); /* In case it's sensitive */
}
#undef F1
#undef F2
#undef F3
#undef F4
PH7_PRIVATE sxi32 MD5Init(MD5Context *pCtx) {
pCtx->buf[0] = 0x67452301;
pCtx->buf[1] = 0xefcdab89;
pCtx->buf[2] = 0x98badcfe;
pCtx->buf[3] = 0x10325476;
pCtx->bits[0] = 0;
pCtx->bits[1] = 0;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyMD5Compute(const void *pIn, sxu32 nLen, unsigned char zDigest[16]) {
MD5Context sCtx;
MD5Init(&sCtx);
MD5Update(&sCtx, (const unsigned char *)pIn, nLen);
MD5Final(zDigest, &sCtx);
return SXRET_OK;
}
/*
* SHA-1 in C
* By Steve Reid <steve@edmweb.com>
* Status: Public Domain
*/
/*
* blk0() and blk() perform the initial expand.
* I got the idea of expanding during the round function from SSLeay
*
* blk0le() for little-endian and blk0be() for big-endian.
*/
#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
/*
* GCC by itself only generates left rotates. Use right rotates if
* possible to be kinder to dinky implementations with iterative rotate
* instructions.
*/
#define SHA_ROT(op, x, k) \
(__extension__({ unsigned int y; __asm__(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; }))
#define rol(x,k) SHA_ROT("roll", x, k)
#define ror(x,k) SHA_ROT("rorl", x, k)
#else
/* Generic C equivalent */
#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
#define rol(x,k) SHA_ROT(x,k,32-(k))
#define ror(x,k) SHA_ROT(x,32-(k),k)
#endif
#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
|(rol(block[i],8)&0x00FF00FF))
#define blk0be(i) block[i]
#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
^block[(i+2)&15]^block[i&15],1))
/*
* (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
*
* Rl0() for little-endian and Rb0() for big-endian. Endianness is
* determined at run-time.
*/
#define Rl0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define Rb0(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R1(v,w,x,y,z,i) \
z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
#define R2(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
#define R3(v,w,x,y,z,i) \
z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
#define R4(v,w,x,y,z,i) \
z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
#define a qq[0]
#define b qq[1]
#define c qq[2]
#define d qq[3]
#define e qq[4]
static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]) {
unsigned int qq[5]; /* a, b, c, d, e; */
static int one = 1;
unsigned int block[16];
SyMemcpy(buffer, (void *)block, 64);
SyMemcpy(state, qq, 5 * sizeof(unsigned int));
/* Copy context->state[] to working vars */
/*
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
*/
/* 4 rounds of 20 operations each. Loop unrolled. */
if(1 == *(unsigned char *)&one) {
Rl0(a, b, c, d, e, 0);
Rl0(e, a, b, c, d, 1);
Rl0(d, e, a, b, c, 2);
Rl0(c, d, e, a, b, 3);
Rl0(b, c, d, e, a, 4);
Rl0(a, b, c, d, e, 5);
Rl0(e, a, b, c, d, 6);
Rl0(d, e, a, b, c, 7);
Rl0(c, d, e, a, b, 8);
Rl0(b, c, d, e, a, 9);
Rl0(a, b, c, d, e, 10);
Rl0(e, a, b, c, d, 11);
Rl0(d, e, a, b, c, 12);
Rl0(c, d, e, a, b, 13);
Rl0(b, c, d, e, a, 14);
Rl0(a, b, c, d, e, 15);
} else {
Rb0(a, b, c, d, e, 0);
Rb0(e, a, b, c, d, 1);
Rb0(d, e, a, b, c, 2);
Rb0(c, d, e, a, b, 3);
Rb0(b, c, d, e, a, 4);
Rb0(a, b, c, d, e, 5);
Rb0(e, a, b, c, d, 6);
Rb0(d, e, a, b, c, 7);
Rb0(c, d, e, a, b, 8);
Rb0(b, c, d, e, a, 9);
Rb0(a, b, c, d, e, 10);
Rb0(e, a, b, c, d, 11);
Rb0(d, e, a, b, c, 12);
Rb0(c, d, e, a, b, 13);
Rb0(b, c, d, e, a, 14);
Rb0(a, b, c, d, e, 15);
}
R1(e, a, b, c, d, 16);
R1(d, e, a, b, c, 17);
R1(c, d, e, a, b, 18);
R1(b, c, d, e, a, 19);
R2(a, b, c, d, e, 20);
R2(e, a, b, c, d, 21);
R2(d, e, a, b, c, 22);
R2(c, d, e, a, b, 23);
R2(b, c, d, e, a, 24);
R2(a, b, c, d, e, 25);
R2(e, a, b, c, d, 26);
R2(d, e, a, b, c, 27);
R2(c, d, e, a, b, 28);
R2(b, c, d, e, a, 29);
R2(a, b, c, d, e, 30);
R2(e, a, b, c, d, 31);
R2(d, e, a, b, c, 32);
R2(c, d, e, a, b, 33);
R2(b, c, d, e, a, 34);
R2(a, b, c, d, e, 35);
R2(e, a, b, c, d, 36);
R2(d, e, a, b, c, 37);
R2(c, d, e, a, b, 38);
R2(b, c, d, e, a, 39);
R3(a, b, c, d, e, 40);
R3(e, a, b, c, d, 41);
R3(d, e, a, b, c, 42);
R3(c, d, e, a, b, 43);
R3(b, c, d, e, a, 44);
R3(a, b, c, d, e, 45);
R3(e, a, b, c, d, 46);
R3(d, e, a, b, c, 47);
R3(c, d, e, a, b, 48);
R3(b, c, d, e, a, 49);
R3(a, b, c, d, e, 50);
R3(e, a, b, c, d, 51);
R3(d, e, a, b, c, 52);
R3(c, d, e, a, b, 53);
R3(b, c, d, e, a, 54);
R3(a, b, c, d, e, 55);
R3(e, a, b, c, d, 56);
R3(d, e, a, b, c, 57);
R3(c, d, e, a, b, 58);
R3(b, c, d, e, a, 59);
R4(a, b, c, d, e, 60);
R4(e, a, b, c, d, 61);
R4(d, e, a, b, c, 62);
R4(c, d, e, a, b, 63);
R4(b, c, d, e, a, 64);
R4(a, b, c, d, e, 65);
R4(e, a, b, c, d, 66);
R4(d, e, a, b, c, 67);
R4(c, d, e, a, b, 68);
R4(b, c, d, e, a, 69);
R4(a, b, c, d, e, 70);
R4(e, a, b, c, d, 71);
R4(d, e, a, b, c, 72);
R4(c, d, e, a, b, 73);
R4(b, c, d, e, a, 74);
R4(a, b, c, d, e, 75);
R4(e, a, b, c, d, 76);
R4(d, e, a, b, c, 77);
R4(c, d, e, a, b, 78);
R4(b, c, d, e, a, 79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
}
#undef a
#undef b
#undef c
#undef d
#undef e
/*
* SHA1Init - Initialize new context
*/
PH7_PRIVATE void SHA1Init(SHA1Context *context) {
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/*
* Run your data through this.
*/
PH7_PRIVATE void SHA1Update(SHA1Context *context, const unsigned char *data, unsigned int len) {
unsigned int i, j;
j = context->count[0];
if((context->count[0] += len << 3) < j) {
context->count[1] += (len >> 29) + 1;
}
j = (j >> 3) & 63;
if((j + len) > 63) {
(void)SyMemcpy(data, &context->buffer[j], (i = 64 - j));
SHA1Transform(context->state, context->buffer);
for(; i + 63 < len; i += 64) {
SHA1Transform(context->state, &data[i]);
}
j = 0;
} else {
i = 0;
}
(void)SyMemcpy(&data[i], &context->buffer[j], len - i);
}
/*
* Add padding and return the message digest.
*/
PH7_PRIVATE void SHA1Final(SHA1Context *context, unsigned char digest[20]) {
unsigned int i;
unsigned char finalcount[8];
for(i = 0; i < 8; i++) {
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
>> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
}
SHA1Update(context, (const unsigned char *)"\200", 1);
while((context->count[0] & 504) != 448) {
SHA1Update(context, (const unsigned char *)"\0", 1);
}
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
if(digest) {
for(i = 0; i < 20; i++)
digest[i] = (unsigned char)
((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
}
}
#undef Rl0
#undef Rb0
#undef R1
#undef R2
#undef R3
#undef R4
PH7_PRIVATE sxi32 SySha1Compute(const void *pIn, sxu32 nLen, unsigned char zDigest[20]) {
SHA1Context sCtx;
SHA1Init(&sCtx);
SHA1Update(&sCtx, (const unsigned char *)pIn, nLen);
SHA1Final(&sCtx, zDigest);
return SXRET_OK;
}
static const sxu32 crc32_table[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
#define CRC32C(c,d) (c = ( crc32_table[(c ^ (d)) & 0xFF] ^ (c>>8) ) )
static sxu32 SyCrc32Update(sxu32 crc32, const void *pSrc, sxu32 nLen) {
register unsigned char *zIn = (unsigned char *)pSrc;
unsigned char *zEnd;
if(zIn == 0) {
return crc32;
}
zEnd = &zIn[nLen];
for(;;) {
if(zIn >= zEnd) {
break;
}
CRC32C(crc32, zIn[0]);
zIn++;
}
return crc32;
}
PH7_PRIVATE sxu32 SyCrc32(const void *pSrc, sxu32 nLen) {
return SyCrc32Update(SXU32_HIGH, pSrc, nLen);
}
PH7_PRIVATE sxi32 SyBinToHexConsumer(const void *pIn, sxu32 nLen, ProcConsumer xConsumer, void *pConsumerData) {
static const unsigned char zHexTab[] = "0123456789abcdef";
const unsigned char *zIn, *zEnd;
unsigned char zOut[3];
sxi32 rc;
if(pIn == 0 || xConsumer == 0) {
return SXERR_EMPTY;
}
zIn = (const unsigned char *)pIn;
zEnd = &zIn[nLen];
for(;;) {
if(zIn >= zEnd) {
break;
}
zOut[0] = zHexTab[zIn[0] >> 4];
zOut[1] = zHexTab[zIn[0] & 0x0F];
rc = xConsumer((const void *)zOut, sizeof(char) * 2, pConsumerData);
if(rc != SXRET_OK) {
return rc;
}
zIn++;
}
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyUriDecode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData, int bUTF8) {
static const sxu8 Utf8Trans[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00
};
const char *zIn = zSrc;
const char *zEnd;
const char *zCur;
sxu8 *zOutPtr;
sxu8 zOut[10];
sxi32 c, d;
sxi32 rc;
if(SX_EMPTY_STR(zSrc) || xConsumer == 0) {
return SXERR_EMPTY;
}
rc = SXRET_OK;
zEnd = &zSrc[nLen];
zCur = zIn;
for(;;) {
while(zCur < zEnd && zCur[0] != '%' && zCur[0] != '+') {
zCur++;
}
if(zCur != zIn) {
/* Consume input */
rc = xConsumer(zIn, (unsigned int)(zCur - zIn), pUserData);
if(rc != SXRET_OK) {
/* User consumer routine request an operation abort */
break;
}
}
if(zCur >= zEnd) {
rc = SXRET_OK;
break;
}
/* Decode unsafe HTTP characters */
zOutPtr = zOut;
if(zCur[0] == '+') {
*zOutPtr++ = ' ';
zCur++;
} else {
if(&zCur[2] >= zEnd) {
rc = SXERR_OVERFLOW;
break;
}
c = (SyAsciiToHex(zCur[1]) << 4) | SyAsciiToHex(zCur[2]);
zCur += 3;
if(c < 0x000C0) {
*zOutPtr++ = (sxu8)c;
} else {
c = Utf8Trans[c - 0xC0];
while(zCur[0] == '%') {
d = (SyAsciiToHex(zCur[1]) << 4) | SyAsciiToHex(zCur[2]);
if((d & 0xC0) != 0x80) {
break;
}
c = (c << 6) + (0x3f & d);
zCur += 3;
}
if(bUTF8 == FALSE) {
*zOutPtr++ = (sxu8)c;
} else {
SX_WRITE_UTF8(zOutPtr, c);
}
}
}
/* Consume the decoded characters */
rc = xConsumer((const void *)zOut, (unsigned int)(zOutPtr - zOut), pUserData);
if(rc != SXRET_OK) {
break;
}
/* Synchronize pointers */
zIn = zCur;
}
return rc;
}
#define SAFE_HTTP(C) (SyisAlphaNum(c) || c == '_' || c == '-' || c == '$' || c == '.' )
PH7_PRIVATE sxi32 SyUriEncode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) {
unsigned char *zIn = (unsigned char *)zSrc;
unsigned char zHex[3] = { '%', 0, 0 };
unsigned char zOut[2];
unsigned char *zCur, *zEnd;
sxi32 c;
sxi32 rc;
if(SX_EMPTY_STR(zSrc) || xConsumer == 0) {
return SXERR_EMPTY;
}
rc = SXRET_OK;
zEnd = &zIn[nLen];
zCur = zIn;
for(;;) {
if(zCur >= zEnd) {
if(zCur != zIn) {
rc = xConsumer(zIn, (sxu32)(zCur - zIn), pUserData);
}
break;
}
c = zCur[0];
if(SAFE_HTTP(c)) {
zCur++;
continue;
}
if(zCur != zIn && SXRET_OK != (rc = xConsumer(zIn, (sxu32)(zCur - zIn), pUserData))) {
break;
}
if(c == ' ') {
zOut[0] = '+';
rc = xConsumer((const void *)zOut, sizeof(unsigned char), pUserData);
} else {
zHex[1] = "0123456789ABCDEF"[(c >> 4) & 0x0F];
zHex[2] = "0123456789ABCDEF"[c & 0x0F];
rc = xConsumer(zHex, sizeof(zHex), pUserData);
}
if(SXRET_OK != rc) {
break;
}
zIn = &zCur[1];
zCur = zIn ;
}
return rc == SXRET_OK ? SXRET_OK : SXERR_ABORT;
}

4901
engine/lib/lib.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,745 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/libfmt.c
* @DESCRIPTION Modern formatting library for the PH7 Engine
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
#define SXFMT_BUFSIZ 1024 /* Conversion buffer size */
/*
** Conversion types fall into various categories as defined by the
** following enumeration.
*/
#define SXFMT_RADIX 1 /* Integer types.%d, %x, %o, and so forth */
#define SXFMT_FLOAT 2 /* Floating point.%f */
#define SXFMT_EXP 3 /* Exponentional notation.%e and %E */
#define SXFMT_GENERIC 4 /* Floating or exponential, depending on exponent.%g */
#define SXFMT_SIZE 5 /* Total number of characters processed so far.%n */
#define SXFMT_STRING 6 /* Strings.%s */
#define SXFMT_PERCENT 7 /* Percent symbol.%% */
#define SXFMT_CHARX 8 /* Characters.%c */
#define SXFMT_ERROR 9 /* Used to indicate no such conversion type */
/* Extension by Symisc Systems */
#define SXFMT_RAWSTR 13 /* %z Pointer to raw string (SyString *) */
#define SXFMT_UNUSED 15
/*
** Allowed values for SyFmtInfo.flags
*/
#define SXFLAG_SIGNED 0x01
#define SXFLAG_UNSIGNED 0x02
/* Allowed values for SyFmtConsumer.nType */
#define SXFMT_CONS_PROC 1 /* Consumer is a procedure */
#define SXFMT_CONS_STR 2 /* Consumer is a managed string */
#define SXFMT_CONS_FILE 5 /* Consumer is an open File */
#define SXFMT_CONS_BLOB 6 /* Consumer is a BLOB */
/*
** Each builtin conversion character (ex: the 'd' in "%d") is described
** by an instance of the following structure
*/
typedef struct SyFmtInfo SyFmtInfo;
struct SyFmtInfo {
char fmttype; /* The format field code letter [i.e: 'd','s','x'] */
sxu8 base; /* The base for radix conversion */
int flags; /* One or more of SXFLAG_ constants below */
sxu8 type; /* Conversion paradigm */
const char *charset; /* The character set for conversion */
const char *prefix; /* Prefix on non-zero values in alt format */
};
typedef struct SyFmtConsumer SyFmtConsumer;
struct SyFmtConsumer {
sxu32 nLen; /* Total output length */
sxi32 nType; /* Type of the consumer see below */
sxi32 rc; /* Consumer return value;Abort processing if rc != SXRET_OK */
union {
struct {
ProcConsumer xUserConsumer;
void *pUserData;
} sFunc;
SyBlob *pBlob;
} uConsumer;
};
static int getdigit(sxlongreal *val, int *cnt) {
sxlongreal d;
int digit;
if((*cnt)++ >= 16) {
return '0';
}
digit = (int) * val;
d = digit;
*val = (*val - d) * 10.0;
return digit + '0' ;
}
/*
* The following routine was taken from the SQLITE2 source tree and was
* extended by Symisc Systems to fit its need.
* Status: Public Domain
*/
static sxi32 InternFormat(ProcConsumer xConsumer, void *pUserData, const char *zFormat, va_list ap) {
/*
* The following table is searched linearly, so it is good to put the most frequently
* used conversion types first.
*/
static const SyFmtInfo aFmt[] = {
{ 'd', 10, SXFLAG_SIGNED, SXFMT_RADIX, "0123456789", 0 },
{ 's', 0, 0, SXFMT_STRING, 0, 0 },
{ 'c', 0, 0, SXFMT_CHARX, 0, 0 },
{ 'x', 16, 0, SXFMT_RADIX, "0123456789abcdef", "x0" },
{ 'X', 16, 0, SXFMT_RADIX, "0123456789ABCDEF", "X0" },
/* -- Extensions by Symisc Systems -- */
{ 'z', 0, 0, SXFMT_RAWSTR, 0, 0 }, /* Pointer to a raw string (SyString *) */
{ 'B', 2, 0, SXFMT_RADIX, "01", "b0"},
/* -- End of Extensions -- */
{ 'o', 8, 0, SXFMT_RADIX, "01234567", "0" },
{ 'u', 10, 0, SXFMT_RADIX, "0123456789", 0 },
{ 'f', 0, SXFLAG_SIGNED, SXFMT_FLOAT, 0, 0 },
{ 'e', 0, SXFLAG_SIGNED, SXFMT_EXP, "e", 0 },
{ 'E', 0, SXFLAG_SIGNED, SXFMT_EXP, "E", 0 },
{ 'g', 0, SXFLAG_SIGNED, SXFMT_GENERIC, "e", 0 },
{ 'G', 0, SXFLAG_SIGNED, SXFMT_GENERIC, "E", 0 },
{ 'i', 10, SXFLAG_SIGNED, SXFMT_RADIX, "0123456789", 0 },
{ 'n', 0, 0, SXFMT_SIZE, 0, 0 },
{ '%', 0, 0, SXFMT_PERCENT, 0, 0 },
{ 'p', 10, 0, SXFMT_RADIX, "0123456789", 0 }
};
int c; /* Next character in the format string */
char *bufpt; /* Pointer to the conversion buffer */
int precision; /* Precision of the current field */
int length; /* Length of the field */
int idx; /* A general purpose loop counter */
int width; /* Width of the current field */
sxu8 flag_leftjustify; /* True if "-" flag is present */
sxu8 flag_plussign; /* True if "+" flag is present */
sxu8 flag_blanksign; /* True if " " flag is present */
sxu8 flag_alternateform; /* True if "#" flag is present */
sxu8 flag_zeropad; /* True if field width constant starts with zero */
sxu8 flag_long; /* True if "l" flag is present */
sxi64 longvalue; /* Value for integer types */
const SyFmtInfo *infop; /* Pointer to the appropriate info structure */
char buf[SXFMT_BUFSIZ]; /* Conversion buffer */
char prefix; /* Prefix character."+" or "-" or " " or '\0'.*/
sxu8 errorflag = 0; /* True if an error is encountered */
sxu8 xtype; /* Conversion paradigm */
static char spaces[] = " ";
#define etSPACESIZE ((int)sizeof(spaces)-1)
sxlongreal realvalue; /* Value for real types */
int exp; /* exponent of real numbers */
double rounder; /* Used for rounding floating point values */
sxu8 flag_dp; /* True if decimal point should be shown */
sxu8 flag_rtz; /* True if trailing zeros should be removed */
sxu8 flag_exp; /* True to force display of the exponent */
int nsd; /* Number of significant digits returned */
int rc;
length = 0;
bufpt = 0;
for(; (c = (*zFormat)) != 0; ++zFormat) {
if(c != '%') {
unsigned int amt;
bufpt = (char *)zFormat;
amt = 1;
while((c = (*++zFormat)) != '%' && c != 0) {
amt++;
}
rc = xConsumer((const void *)bufpt, amt, pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT; /* Consumer routine request an operation abort */
}
if(c == 0) {
return errorflag > 0 ? SXERR_FORMAT : SXRET_OK;
}
}
if((c = (*++zFormat)) == 0) {
errorflag = 1;
rc = xConsumer("%", sizeof("%") - 1, pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT; /* Consumer routine request an operation abort */
}
return errorflag > 0 ? SXERR_FORMAT : SXRET_OK;
}
/* Find out what flags are present */
flag_leftjustify = flag_plussign = flag_blanksign =
flag_alternateform = flag_zeropad = 0;
do {
switch(c) {
case '-':
flag_leftjustify = 1;
c = 0;
break;
case '+':
flag_plussign = 1;
c = 0;
break;
case ' ':
flag_blanksign = 1;
c = 0;
break;
case '#':
flag_alternateform = 1;
c = 0;
break;
case '0':
flag_zeropad = 1;
c = 0;
break;
default:
break;
}
} while(c == 0 && (c = (*++zFormat)) != 0);
/* Get the field width */
width = 0;
if(c == '*') {
width = va_arg(ap, int);
if(width < 0) {
flag_leftjustify = 1;
width = -width;
}
c = *++zFormat;
} else {
while(c >= '0' && c <= '9') {
width = width * 10 + c - '0';
c = *++zFormat;
}
}
if(width > SXFMT_BUFSIZ - 10) {
width = SXFMT_BUFSIZ - 10;
}
/* Get the precision */
precision = -1;
if(c == '.') {
precision = 0;
c = *++zFormat;
if(c == '*') {
precision = va_arg(ap, int);
if(precision < 0) {
precision = -precision;
}
c = *++zFormat;
} else {
while(c >= '0' && c <= '9') {
precision = precision * 10 + c - '0';
c = *++zFormat;
}
}
}
/* Get the conversion type modifier */
flag_long = 0;
if(c == 'l' || c == 'q' /* BSD quad (expect a 64-bit integer) */) {
flag_long = (c == 'q') ? 2 : 1;
c = *++zFormat;
if(c == 'l') {
/* Standard printf emulation 'lld' (expect a 64bit integer) */
flag_long = 2;
}
}
/* Fetch the info entry for the field */
infop = 0;
xtype = SXFMT_ERROR;
for(idx = 0; idx < (int)SX_ARRAYSIZE(aFmt); idx++) {
if(c == aFmt[idx].fmttype) {
infop = &aFmt[idx];
xtype = infop->type;
break;
}
}
/*
** At this point, variables are initialized as follows:
**
** flag_alternateform TRUE if a '#' is present.
** flag_plussign TRUE if a '+' is present.
** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative.
** flag_zeropad TRUE if the width began with 0.
** flag_long TRUE if the letter 'l' (ell) or 'q'(BSD quad) prefixed
** the conversion character.
** flag_blanksign TRUE if a ' ' is present.
** width The specified field width.This is
** always non-negative.Zero is the default.
** precision The specified precision.The default
** is -1.
** xtype The class of the conversion.
** infop Pointer to the appropriate info struct.
*/
switch(xtype) {
case SXFMT_RADIX:
if(flag_long > 0) {
if(flag_long > 1) {
/* BSD quad: expect a 64-bit integer */
longvalue = va_arg(ap, sxi64);
} else {
longvalue = va_arg(ap, sxlong);
}
} else {
if(infop->flags & SXFLAG_SIGNED) {
longvalue = va_arg(ap, sxi32);
} else {
longvalue = va_arg(ap, sxu32);
}
}
/* Limit the precision to prevent overflowing buf[] during conversion */
if(precision > SXFMT_BUFSIZ - 40) {
precision = SXFMT_BUFSIZ - 40;
}
#if 1
/* For the format %#x, the value zero is printed "0" not "0x0".
** I think this is stupid.*/
if(longvalue == 0) {
flag_alternateform = 0;
}
#else
/* More sensible: turn off the prefix for octal (to prevent "00"),
** but leave the prefix for hex.*/
if(longvalue == 0 && infop->base == 8) {
flag_alternateform = 0;
}
#endif
if(infop->flags & SXFLAG_SIGNED) {
if(longvalue < 0) {
longvalue = -longvalue;
/* Ticket 1433-003 */
if(longvalue < 0) {
/* Overflow */
longvalue = SXI64_HIGH;
}
prefix = '-';
} else if(flag_plussign) {
prefix = '+';
} else if(flag_blanksign) {
prefix = ' ';
} else {
prefix = 0;
}
} else {
if(longvalue < 0) {
longvalue = -longvalue;
/* Ticket 1433-003 */
if(longvalue < 0) {
/* Overflow */
longvalue = SXI64_HIGH;
}
}
prefix = 0;
}
if(flag_zeropad && precision < width - (prefix != 0)) {
precision = width - (prefix != 0);
}
bufpt = &buf[SXFMT_BUFSIZ - 1];
{
register const char *cset; /* Use registers for speed */
register int base;
cset = infop->charset;
base = infop->base;
do { /* Convert to ascii */
*(--bufpt) = cset[longvalue % base];
longvalue = longvalue / base;
} while(longvalue > 0);
}
length = &buf[SXFMT_BUFSIZ - 1] - bufpt;
for(idx = precision - length; idx > 0; idx--) {
*(--bufpt) = '0'; /* Zero pad */
}
if(prefix) {
*(--bufpt) = prefix; /* Add sign */
}
if(flag_alternateform && infop->prefix) { /* Add "0" or "0x" */
const char *pre;
char x;
pre = infop->prefix;
if(*bufpt != pre[0]) {
for(pre = infop->prefix; (x = (*pre)) != 0; pre++) {
*(--bufpt) = x;
}
}
}
length = &buf[SXFMT_BUFSIZ - 1] - bufpt;
break;
case SXFMT_FLOAT:
case SXFMT_EXP:
case SXFMT_GENERIC:
realvalue = va_arg(ap, double);
if(precision < 0) {
precision = 6; /* Set default precision */
}
if(precision > SXFMT_BUFSIZ - 40) {
precision = SXFMT_BUFSIZ - 40;
}
if(realvalue < 0.0) {
realvalue = -realvalue;
prefix = '-';
} else {
if(flag_plussign) {
prefix = '+';
} else if(flag_blanksign) {
prefix = ' ';
} else {
prefix = 0;
}
}
if(infop->type == SXFMT_GENERIC && precision > 0) {
precision--;
}
rounder = 0.0;
/* Rounding works like BSD when the constant 0.4999 is used. Wierd!
* It makes more sense to use 0.5 instead. */
for(idx = precision, rounder = 0.5; idx > 0; idx--, rounder *= 0.1);
if(infop->type == SXFMT_FLOAT) {
realvalue += rounder;
}
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
if(realvalue > 0.0) {
while(realvalue >= 1e8 && exp <= 350) {
realvalue *= 1e-8;
exp += 8;
}
while(realvalue >= 10.0 && exp <= 350) {
realvalue *= 0.1;
exp++;
}
while(realvalue < 1e-8 && exp >= -350) {
realvalue *= 1e8;
exp -= 8;
}
while(realvalue < 1.0 && exp >= -350) {
realvalue *= 10.0;
exp--;
}
if(exp > 350 || exp < -350) {
bufpt = "NaN";
length = 3;
break;
}
}
bufpt = buf;
/*
** If the field type is etGENERIC, then convert to either etEXP
** or etFLOAT, as appropriate.
*/
flag_exp = xtype == SXFMT_EXP;
if(xtype != SXFMT_FLOAT) {
realvalue += rounder;
if(realvalue >= 10.0) {
realvalue *= 0.1;
exp++;
}
}
if(xtype == SXFMT_GENERIC) {
flag_rtz = !flag_alternateform;
if(exp < -4 || exp > precision) {
xtype = SXFMT_EXP;
} else {
precision = precision - exp;
xtype = SXFMT_FLOAT;
}
} else {
flag_rtz = 0;
}
/*
** The "exp+precision" test causes output to be of type etEXP if
** the precision is too large to fit in buf[].
*/
nsd = 0;
if(xtype == SXFMT_FLOAT && exp + precision < SXFMT_BUFSIZ - 30) {
flag_dp = (precision > 0 || flag_alternateform);
if(prefix) {
*(bufpt++) = prefix; /* Sign */
}
if(exp < 0) {
*(bufpt++) = '0'; /* Digits before "." */
} else
for(; exp >= 0; exp--) {
*(bufpt++) = (char)getdigit(&realvalue, &nsd);
}
if(flag_dp) {
*(bufpt++) = '.'; /* The decimal point */
}
for(exp++; exp < 0 && precision > 0; precision--, exp++) {
*(bufpt++) = '0';
}
while((precision--) > 0) {
*(bufpt++) = (char)getdigit(&realvalue, &nsd);
}
*(bufpt--) = 0; /* Null terminate */
if(flag_rtz && flag_dp) { /* Remove trailing zeros and "." */
while(bufpt >= buf && *bufpt == '0') {
*(bufpt--) = 0;
}
if(bufpt >= buf && *bufpt == '.') {
*(bufpt--) = 0;
}
}
bufpt++; /* point to next free slot */
} else { /* etEXP or etGENERIC */
flag_dp = (precision > 0 || flag_alternateform);
if(prefix) {
*(bufpt++) = prefix; /* Sign */
}
*(bufpt++) = (char)getdigit(&realvalue, &nsd); /* First digit */
if(flag_dp) {
*(bufpt++) = '.'; /* Decimal point */
}
while((precision--) > 0) {
*(bufpt++) = (char)getdigit(&realvalue, &nsd);
}
bufpt--; /* point to last digit */
if(flag_rtz && flag_dp) { /* Remove tail zeros */
while(bufpt >= buf && *bufpt == '0') {
*(bufpt--) = 0;
}
if(bufpt >= buf && *bufpt == '.') {
*(bufpt--) = 0;
}
}
bufpt++; /* point to next free slot */
if(exp || flag_exp) {
*(bufpt++) = infop->charset[0];
if(exp < 0) {
*(bufpt++) = '-'; /* sign of exp */
exp = -exp;
} else {
*(bufpt++) = '+';
}
if(exp >= 100) {
*(bufpt++) = (char)((exp / 100) + '0'); /* 100's digit */
exp %= 100;
}
*(bufpt++) = (char)(exp / 10 + '0'); /* 10's digit */
*(bufpt++) = (char)(exp % 10 + '0'); /* 1's digit */
}
}
/* The converted number is in buf[] and zero terminated.Output it.
** Note that the number is in the usual order, not reversed as with
** integer conversions.*/
length = bufpt - buf;
bufpt = buf;
/* Special case: Add leading zeros if the flag_zeropad flag is
** set and we are not left justified */
if(flag_zeropad && !flag_leftjustify && length < width) {
int i;
int nPad = width - length;
for(i = width; i >= nPad; i--) {
bufpt[i] = bufpt[i - nPad];
}
i = prefix != 0;
while(nPad--) {
bufpt[i++] = '0';
}
length = width;
}
break;
case SXFMT_SIZE: {
int *pSize = va_arg(ap, int *);
*pSize = ((SyFmtConsumer *)pUserData)->nLen;
length = width = 0;
}
break;
case SXFMT_PERCENT:
buf[0] = '%';
bufpt = buf;
length = 1;
break;
case SXFMT_CHARX:
c = va_arg(ap, int);
buf[0] = (char)c;
/* Limit the precision to prevent overflowing buf[] during conversion */
if(precision > SXFMT_BUFSIZ - 40) {
precision = SXFMT_BUFSIZ - 40;
}
if(precision >= 0) {
for(idx = 1; idx < precision; idx++) {
buf[idx] = (char)c;
}
length = precision;
} else {
length = 1;
}
bufpt = buf;
break;
case SXFMT_STRING:
bufpt = va_arg(ap, char *);
if(bufpt == 0) {
bufpt = " ";
length = (int)sizeof(" ") - 1;
break;
}
length = precision;
if(precision < 0) {
/* Symisc extension */
length = (int)SyStrlen(bufpt);
}
if(precision >= 0 && precision < length) {
length = precision;
}
break;
case SXFMT_RAWSTR: {
/* Symisc extension */
SyString *pStr = va_arg(ap, SyString *);
if(pStr == 0 || pStr->zString == 0) {
bufpt = " ";
length = (int)sizeof(char);
break;
}
bufpt = (char *)pStr->zString;
length = (int)pStr->nByte;
break;
}
case SXFMT_ERROR:
buf[0] = '?';
bufpt = buf;
length = (int)sizeof(char);
if(c == 0) {
zFormat--;
}
break;
}/* End switch over the format type */
/*
** The text of the conversion is pointed to by "bufpt" and is
** "length" characters long.The field width is "width".Do
** the output.
*/
if(!flag_leftjustify) {
register int nspace;
nspace = width - length;
if(nspace > 0) {
while(nspace >= etSPACESIZE) {
rc = xConsumer(spaces, etSPACESIZE, pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT; /* Consumer routine request an operation abort */
}
nspace -= etSPACESIZE;
}
if(nspace > 0) {
rc = xConsumer(spaces, (unsigned int)nspace, pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT; /* Consumer routine request an operation abort */
}
}
}
}
if(length > 0) {
rc = xConsumer(bufpt, (unsigned int)length, pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT; /* Consumer routine request an operation abort */
}
}
if(flag_leftjustify) {
register int nspace;
nspace = width - length;
if(nspace > 0) {
while(nspace >= etSPACESIZE) {
rc = xConsumer(spaces, etSPACESIZE, pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT; /* Consumer routine request an operation abort */
}
nspace -= etSPACESIZE;
}
if(nspace > 0) {
rc = xConsumer(spaces, (unsigned int)nspace, pUserData);
if(rc != SXRET_OK) {
return SXERR_ABORT; /* Consumer routine request an operation abort */
}
}
}
}
}/* End for loop over the format string */
return errorflag ? SXERR_FORMAT : SXRET_OK;
}
static sxi32 FormatConsumer(const void *pSrc, unsigned int nLen, void *pData) {
SyFmtConsumer *pConsumer = (SyFmtConsumer *)pData;
sxi32 rc = SXERR_ABORT;
switch(pConsumer->nType) {
case SXFMT_CONS_PROC:
/* User callback */
rc = pConsumer->uConsumer.sFunc.xUserConsumer(pSrc, nLen, pConsumer->uConsumer.sFunc.pUserData);
break;
case SXFMT_CONS_BLOB:
/* Blob consumer */
rc = SyBlobAppend(pConsumer->uConsumer.pBlob, pSrc, (sxu32)nLen);
break;
default:
/* Unknown consumer */
break;
}
/* Update total number of bytes consumed so far */
pConsumer->nLen += nLen;
pConsumer->rc = rc;
return rc;
}
static sxi32 FormatMount(sxi32 nType, void *pConsumer, ProcConsumer xUserCons, void *pUserData, sxu32 *pOutLen, const char *zFormat, va_list ap) {
SyFmtConsumer sCons;
sCons.nType = nType;
sCons.rc = SXRET_OK;
sCons.nLen = 0;
if(pOutLen) {
*pOutLen = 0;
}
switch(nType) {
case SXFMT_CONS_PROC:
if(xUserCons == 0) {
return SXERR_EMPTY;
}
sCons.uConsumer.sFunc.xUserConsumer = xUserCons;
sCons.uConsumer.sFunc.pUserData = pUserData;
break;
case SXFMT_CONS_BLOB:
sCons.uConsumer.pBlob = (SyBlob *)pConsumer;
break;
default:
return SXERR_UNKNOWN;
}
InternFormat(FormatConsumer, &sCons, zFormat, ap);
if(pOutLen) {
*pOutLen = sCons.nLen;
}
return sCons.rc;
}
PH7_PRIVATE sxi32 SyProcFormat(ProcConsumer xConsumer, void *pData, const char *zFormat, ...) {
va_list ap;
sxi32 rc;
if(SX_EMPTY_STR(zFormat)) {
return SXERR_EMPTY;
}
va_start(ap, zFormat);
rc = FormatMount(SXFMT_CONS_PROC, 0, xConsumer, pData, 0, zFormat, ap);
va_end(ap);
return rc;
}
PH7_PRIVATE sxu32 SyBlobFormat(SyBlob *pBlob, const char *zFormat, ...) {
va_list ap;
sxu32 n;
if(SX_EMPTY_STR(zFormat)) {
return 0;
}
va_start(ap, zFormat);
FormatMount(SXFMT_CONS_BLOB, &(*pBlob), 0, 0, &n, zFormat, ap);
va_end(ap);
return n;
}
PH7_PRIVATE sxu32 SyBlobFormatAp(SyBlob *pBlob, const char *zFormat, va_list ap) {
sxu32 n = 0; /* cc warning */
if(SX_EMPTY_STR(zFormat)) {
return 0;
}
FormatMount(SXFMT_CONS_BLOB, &(*pBlob), 0, 0, &n, zFormat, ap);
return n;
}
PH7_PRIVATE sxu32 SyBufferFormat(char *zBuf, sxu32 nLen, const char *zFormat, ...) {
SyBlob sBlob;
va_list ap;
sxu32 n;
if(SX_EMPTY_STR(zFormat)) {
return 0;
}
if(SXRET_OK != SyBlobInitFromBuf(&sBlob, zBuf, nLen - 1)) {
return 0;
}
va_start(ap, zFormat);
FormatMount(SXFMT_CONS_BLOB, &sBlob, 0, 0, 0, zFormat, ap);
va_end(ap);
n = SyBlobLength(&sBlob);
/* Append the null terminator */
sBlob.mByte++;
SyBlobAppend(&sBlob, "\0", sizeof(char));
return n;
}

View File

@ -1,514 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/libzip.c
* @DESCRIPTION ZIP archive file manipulation support for the PH7 Engine
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
sxu32 SyBinHash(const void *pSrc, sxu32 nLen);
/*
* Zip File Format:
*
* Byte order: Little-endian
*
* [Local file header + Compressed data [+ Extended local header]?]*
* [Central directory]*
* [End of central directory record]
*
* Local file header:*
* Offset Length Contents
* 0 4 bytes Local file header signature (0x04034b50)
* 4 2 bytes Version needed to extract
* 6 2 bytes General purpose bit flag
* 8 2 bytes Compression method
* 10 2 bytes Last mod file time
* 12 2 bytes Last mod file date
* 14 4 bytes CRC-32
* 18 4 bytes Compressed size (n)
* 22 4 bytes Uncompressed size
* 26 2 bytes Filename length (f)
* 28 2 bytes Extra field length (e)
* 30 (f)bytes Filename
* (e)bytes Extra field
* (n)bytes Compressed data
*
* Extended local header:*
* Offset Length Contents
* 0 4 bytes Extended Local file header signature (0x08074b50)
* 4 4 bytes CRC-32
* 8 4 bytes Compressed size
* 12 4 bytes Uncompressed size
*
* Extra field:?(if any)
* Offset Length Contents
* 0 2 bytes Header ID (0x001 until 0xfb4a) see extended appnote from Info-zip
* 2 2 bytes Data size (g)
* (g) bytes (g) bytes of extra field
*
* Central directory:*
* Offset Length Contents
* 0 4 bytes Central file header signature (0x02014b50)
* 4 2 bytes Version made by
* 6 2 bytes Version needed to extract
* 8 2 bytes General purpose bit flag
* 10 2 bytes Compression method
* 12 2 bytes Last mod file time
* 14 2 bytes Last mod file date
* 16 4 bytes CRC-32
* 20 4 bytes Compressed size
* 24 4 bytes Uncompressed size
* 28 2 bytes Filename length (f)
* 30 2 bytes Extra field length (e)
* 32 2 bytes File comment length (c)
* 34 2 bytes Disk number start
* 36 2 bytes Internal file attributes
* 38 4 bytes External file attributes
* 42 4 bytes Relative offset of local header
* 46 (f)bytes Filename
* (e)bytes Extra field
* (c)bytes File comment
*
* End of central directory record:
* Offset Length Contents
* 0 4 bytes End of central dir signature (0x06054b50)
* 4 2 bytes Number of this disk
* 6 2 bytes Number of the disk with the start of the central directory
* 8 2 bytes Total number of entries in the central dir on this disk
* 10 2 bytes Total number of entries in the central dir
* 12 4 bytes Size of the central directory
* 16 4 bytes Offset of start of central directory with respect to the starting disk number
* 20 2 bytes zipfile comment length (c)
* 22 (c)bytes zipfile comment
*
* compression method: (2 bytes)
* 0 - The file is stored (no compression)
* 1 - The file is Shrunk
* 2 - The file is Reduced with compression factor 1
* 3 - The file is Reduced with compression factor 2
* 4 - The file is Reduced with compression factor 3
* 5 - The file is Reduced with compression factor 4
* 6 - The file is Imploded
* 7 - Reserved for Tokenizing compression algorithm
* 8 - The file is Deflated
*/
#define SXMAKE_ZIP_WORKBUF (SXU16_HIGH/2) /* 32KB Initial working buffer size */
#define SXMAKE_ZIP_EXTRACT_VER 0x000a /* Version needed to extract */
#define SXMAKE_ZIP_VER 0x003 /* Version made by */
#define SXZIP_CENTRAL_MAGIC 0x02014b50
#define SXZIP_END_CENTRAL_MAGIC 0x06054b50
#define SXZIP_LOCAL_MAGIC 0x04034b50
/*#define SXZIP_CRC32_START 0xdebb20e3*/
#define SXZIP_LOCAL_HDRSZ 30 /* Local header size */
#define SXZIP_LOCAL_EXT_HDRZ 16 /* Extended local header(footer) size */
#define SXZIP_CENTRAL_HDRSZ 46 /* Central directory header size */
#define SXZIP_END_CENTRAL_HDRSZ 22 /* End of central directory header size */
#define SXARCHIVE_HASH_SIZE 64 /* Starting hash table size(MUST BE POWER OF 2)*/
static sxi32 SyLittleEndianUnpack32(sxu32 *uNB, const unsigned char *buf, sxu32 Len) {
if(Len < sizeof(sxu32)) {
return SXERR_SHORT;
}
*uNB = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
return SXRET_OK;
}
static sxi32 SyLittleEndianUnpack16(sxu16 *pOut, const unsigned char *zBuf, sxu32 nLen) {
if(nLen < sizeof(sxu16)) {
return SXERR_SHORT;
}
*pOut = zBuf[0] + (zBuf[1] << 8);
return SXRET_OK;
}
static sxi32 SyDosTimeFormat(sxu32 nDosDate, Sytm *pOut) {
sxu16 nDate;
sxu16 nTime;
nDate = nDosDate >> 16;
nTime = nDosDate & 0xFFFF;
pOut->tm_isdst = 0;
pOut->tm_year = 1980 + (nDate >> 9);
pOut->tm_mon = (nDate % (1 << 9)) >> 5;
pOut->tm_mday = (nDate % (1 << 9)) & 0x1F;
pOut->tm_hour = nTime >> 11;
pOut->tm_min = (nTime % (1 << 11)) >> 5;
pOut->tm_sec = ((nTime % (1 << 11)) & 0x1F) << 1;
return SXRET_OK;
}
/*
* Archive hashtable manager
*/
static sxi32 ArchiveHashGetEntry(SyArchive *pArch, const char *zName, sxu32 nLen, SyArchiveEntry **ppEntry) {
SyArchiveEntry *pBucketEntry;
SyString sEntry;
sxu32 nHash;
nHash = pArch->xHash(zName, nLen);
pBucketEntry = pArch->apHash[nHash & (pArch->nSize - 1)];
SyStringInitFromBuf(&sEntry, zName, nLen);
for(;;) {
if(pBucketEntry == 0) {
break;
}
if(nHash == pBucketEntry->nHash && pArch->xCmp(&sEntry, &pBucketEntry->sFileName) == 0) {
if(ppEntry) {
*ppEntry = pBucketEntry;
}
return SXRET_OK;
}
pBucketEntry = pBucketEntry->pNextHash;
}
return SXERR_NOTFOUND;
}
static void ArchiveHashBucketInstall(SyArchiveEntry **apTable, sxu32 nBucket, SyArchiveEntry *pEntry) {
pEntry->pNextHash = apTable[nBucket];
if(apTable[nBucket] != 0) {
apTable[nBucket]->pPrevHash = pEntry;
}
apTable[nBucket] = pEntry;
}
static sxi32 ArchiveHashGrowTable(SyArchive *pArch) {
sxu32 nNewSize = pArch->nSize * 2;
SyArchiveEntry **apNew;
SyArchiveEntry *pEntry;
sxu32 n;
/* Allocate a new table */
apNew = (SyArchiveEntry **)SyMemBackendAlloc(pArch->pAllocator, nNewSize * sizeof(SyArchiveEntry *));
if(apNew == 0) {
return SXRET_OK; /* Not so fatal,simply a performance hit */
}
SyZero(apNew, nNewSize * sizeof(SyArchiveEntry *));
/* Rehash old entries */
for(n = 0, pEntry = pArch->pList ; n < pArch->nLoaded ; n++, pEntry = pEntry->pNext) {
pEntry->pNextHash = pEntry->pPrevHash = 0;
ArchiveHashBucketInstall(apNew, pEntry->nHash & (nNewSize - 1), pEntry);
}
/* Release the old table */
SyMemBackendFree(pArch->pAllocator, pArch->apHash);
pArch->apHash = apNew;
pArch->nSize = nNewSize;
return SXRET_OK;
}
static sxi32 ArchiveHashInstallEntry(SyArchive *pArch, SyArchiveEntry *pEntry) {
if(pArch->nLoaded > pArch->nSize * 3) {
ArchiveHashGrowTable(&(*pArch));
}
pEntry->nHash = pArch->xHash(SyStringData(&pEntry->sFileName), SyStringLength(&pEntry->sFileName));
/* Install the entry in its bucket */
ArchiveHashBucketInstall(pArch->apHash, pEntry->nHash & (pArch->nSize - 1), pEntry);
MACRO_LD_PUSH(pArch->pList, pEntry);
pArch->nLoaded++;
return SXRET_OK;
}
/*
* Parse the End of central directory and report status
*/
static sxi32 ParseEndOfCentralDirectory(SyArchive *pArch, const unsigned char *zBuf) {
sxu32 nMagic = 0; /* cc -O6 warning */
/* Sanity check */
SyLittleEndianUnpack32(&nMagic, zBuf, sizeof(sxu32));
if(nMagic != SXZIP_END_CENTRAL_MAGIC) {
return SXERR_CORRUPT;
}
/* # of entries */
SyLittleEndianUnpack16((sxu16 *)&pArch->nEntry, &zBuf[8], sizeof(sxu16));
if(pArch->nEntry > SXI16_HIGH /* SXU16_HIGH */) {
return SXERR_CORRUPT;
}
/* Size of central directory */
SyLittleEndianUnpack32(&pArch->nCentralSize, &zBuf[12], sizeof(sxu32));
if(pArch->nCentralSize > SXI32_HIGH) {
return SXERR_CORRUPT;
}
/* Starting offset of central directory */
SyLittleEndianUnpack32(&pArch->nCentralOfft, &zBuf[16], sizeof(sxu32));
if(pArch->nCentralSize > SXI32_HIGH) {
return SXERR_CORRUPT;
}
return SXRET_OK;
}
/*
* Fill the zip entry with the appropriate information from the central directory
*/
static sxi32 GetCentralDirectoryEntry(SyArchive *pArch, SyArchiveEntry *pEntry, const unsigned char *zCentral, sxu32 *pNextOffset) {
SyString *pName = &pEntry->sFileName; /* File name */
sxu16 nDosDate, nDosTime;
sxu16 nComment = 0 ;
sxu32 nMagic = 0; /* cc -O6 warning */
sxi32 rc;
nDosDate = nDosTime = 0; /* cc -O6 warning */
SXUNUSED(pArch);
// (void)pArch;
/* Sanity check */
rc = SyLittleEndianUnpack32(&nMagic, zCentral, sizeof(sxu32));
if(/* rc != SXRET_OK || */ nMagic != SXZIP_CENTRAL_MAGIC) {
rc = SXERR_CORRUPT;
/*
* Try to recover by examing the next central directory record.
* Dont worry here,there is no risk of an infinite loop since
* the buffer size is delimited.
*/
/* pName->nByte = 0; nComment = 0; pName->nExtra = 0 */
goto update;
}
/*
* entry name length
*/
SyLittleEndianUnpack16((sxu16 *)&pName->nByte, &zCentral[28], sizeof(sxu16));
if(pName->nByte > SXI16_HIGH /* SXU16_HIGH */) {
rc = SXERR_BIG;
goto update;
}
/* Extra information */
SyLittleEndianUnpack16(&pEntry->nExtra, &zCentral[30], sizeof(sxu16));
/* Comment length */
SyLittleEndianUnpack16(&nComment, &zCentral[32], sizeof(sxu16));
/* Compression method 0 == stored / 8 == deflated */
rc = SyLittleEndianUnpack16(&pEntry->nComprMeth, &zCentral[10], sizeof(sxu16));
/* DOS Timestamp */
SyLittleEndianUnpack16(&nDosTime, &zCentral[12], sizeof(sxu16));
SyLittleEndianUnpack16(&nDosDate, &zCentral[14], sizeof(sxu16));
SyDosTimeFormat((nDosDate << 16 | nDosTime), &pEntry->sFmt);
/* Little hack to fix month index */
pEntry->sFmt.tm_mon--;
/* CRC32 */
rc = SyLittleEndianUnpack32(&pEntry->nCrc, &zCentral[16], sizeof(sxu32));
/* Content size before compression */
rc = SyLittleEndianUnpack32(&pEntry->nByte, &zCentral[24], sizeof(sxu32));
if(pEntry->nByte > SXI32_HIGH) {
rc = SXERR_BIG;
goto update;
}
/*
* Content size after compression.
* Note that if the file is stored pEntry->nByte should be equal to pEntry->nByteCompr
*/
rc = SyLittleEndianUnpack32(&pEntry->nByteCompr, &zCentral[20], sizeof(sxu32));
if(pEntry->nByteCompr > SXI32_HIGH) {
rc = SXERR_BIG;
goto update;
}
/* Finally grab the contents offset */
SyLittleEndianUnpack32(&pEntry->nOfft, &zCentral[42], sizeof(sxu32));
if(pEntry->nOfft > SXI32_HIGH) {
rc = SXERR_BIG;
goto update;
}
rc = SXRET_OK;
update:
/* Update the offset to point to the next central directory record */
*pNextOffset = SXZIP_CENTRAL_HDRSZ + pName->nByte + pEntry->nExtra + nComment;
return rc; /* Report failure or success */
}
static sxi32 ZipFixOffset(SyArchiveEntry *pEntry, void *pSrc) {
sxu16 nExtra, nNameLen;
unsigned char *zHdr;
nExtra = nNameLen = 0;
zHdr = (unsigned char *)pSrc;
zHdr = &zHdr[pEntry->nOfft];
if(SyMemcmp(zHdr, "PK\003\004", sizeof(sxu32)) != 0) {
return SXERR_CORRUPT;
}
SyLittleEndianUnpack16(&nNameLen, &zHdr[26], sizeof(sxu16));
SyLittleEndianUnpack16(&nExtra, &zHdr[28], sizeof(sxu16));
/* Fix contents offset */
pEntry->nOfft += SXZIP_LOCAL_HDRSZ + nExtra + nNameLen;
return SXRET_OK;
}
/*
* Extract all valid entries from the central directory
*/
static sxi32 ZipExtract(SyArchive *pArch, const unsigned char *zCentral, sxu32 nLen, void *pSrc) {
SyArchiveEntry *pEntry, *pDup;
const unsigned char *zEnd ; /* End of central directory */
sxu32 nIncr, nOfft; /* Central Offset */
SyString *pName; /* Entry name */
char *zName;
sxi32 rc;
nOfft = nIncr = 0;
zEnd = &zCentral[nLen];
for(;;) {
if(&zCentral[nOfft] >= zEnd) {
break;
}
/* Add a new entry */
pEntry = (SyArchiveEntry *)SyMemBackendPoolAlloc(pArch->pAllocator, sizeof(SyArchiveEntry));
if(pEntry == 0) {
break;
}
SyZero(pEntry, sizeof(SyArchiveEntry));
pEntry->nMagic = SXARCH_MAGIC;
nIncr = 0;
rc = GetCentralDirectoryEntry(&(*pArch), pEntry, &zCentral[nOfft], &nIncr);
if(rc == SXRET_OK) {
/* Fix the starting record offset so we can access entry contents correctly */
rc = ZipFixOffset(pEntry, pSrc);
}
if(rc != SXRET_OK) {
sxu32 nJmp = 0;
SyMemBackendPoolFree(pArch->pAllocator, pEntry);
/* Try to recover by brute-forcing for a valid central directory record */
if(SXRET_OK == SyBlobSearch((const void *)&zCentral[nOfft + nIncr], (sxu32)(zEnd - &zCentral[nOfft + nIncr]),
(const void *)"PK\001\002", sizeof(sxu32), &nJmp)) {
nOfft += nIncr + nJmp; /* Check next entry */
continue;
}
break; /* Giving up,archive is hopelessly corrupted */
}
pName = &pEntry->sFileName;
pName->zString = (const char *)&zCentral[nOfft + SXZIP_CENTRAL_HDRSZ];
if(pName->nByte <= 0 || (pEntry->nByte <= 0 && pName->zString[pName->nByte - 1] != '/')) {
/* Ignore zero length records (except folders) and records without names */
SyMemBackendPoolFree(pArch->pAllocator, pEntry);
nOfft += nIncr; /* Check next entry */
continue;
}
zName = SyMemBackendStrDup(pArch->pAllocator, pName->zString, pName->nByte);
if(zName == 0) {
SyMemBackendPoolFree(pArch->pAllocator, pEntry);
nOfft += nIncr; /* Check next entry */
continue;
}
pName->zString = (const char *)zName;
/* Check for duplicates */
rc = ArchiveHashGetEntry(&(*pArch), pName->zString, pName->nByte, &pDup);
if(rc == SXRET_OK) {
/* Another entry with the same name exists ; link them together */
pEntry->pNextName = pDup->pNextName;
pDup->pNextName = pEntry;
pDup->nDup++;
} else {
/* Insert in hashtable */
ArchiveHashInstallEntry(pArch, pEntry);
}
nOfft += nIncr; /* Check next record */
}
pArch->pCursor = pArch->pList;
return pArch->nLoaded > 0 ? SXRET_OK : SXERR_EMPTY;
}
PH7_PRIVATE sxi32 SyZipExtractFromBuf(SyArchive *pArch, const char *zBuf, sxu32 nLen) {
const unsigned char *zCentral, *zEnd;
sxi32 rc;
if(SXARCH_INVALID(pArch) || zBuf == 0) {
return SXERR_INVALID;
}
/* The miminal size of a zip archive:
* LOCAL_HDR_SZ + CENTRAL_HDR_SZ + END_OF_CENTRAL_HDR_SZ
* 30 46 22
*/
if(nLen < SXZIP_LOCAL_HDRSZ + SXZIP_CENTRAL_HDRSZ + SXZIP_END_CENTRAL_HDRSZ) {
return SXERR_CORRUPT; /* Don't bother processing return immediately */
}
zEnd = (unsigned char *)&zBuf[nLen - SXZIP_END_CENTRAL_HDRSZ];
/* Find the end of central directory */
while(((sxu32)((unsigned char *)&zBuf[nLen] - zEnd) < (SXZIP_END_CENTRAL_HDRSZ + SXI16_HIGH)) &&
zEnd > (unsigned char *)zBuf && SyMemcmp(zEnd, "PK\005\006", sizeof(sxu32)) != 0) {
zEnd--;
}
/* Parse the end of central directory */
rc = ParseEndOfCentralDirectory(&(*pArch), zEnd);
if(rc != SXRET_OK) {
return rc;
}
/* Find the starting offset of the central directory */
zCentral = &zEnd[-(sxi32)pArch->nCentralSize];
if(zCentral <= (unsigned char *)zBuf || SyMemcmp(zCentral, "PK\001\002", sizeof(sxu32)) != 0) {
if(pArch->nCentralOfft >= nLen) {
/* Corrupted central directory offset */
return SXERR_CORRUPT;
}
zCentral = (unsigned char *)&zBuf[pArch->nCentralOfft];
if(SyMemcmp(zCentral, "PK\001\002", sizeof(sxu32)) != 0) {
/* Corrupted zip archive */
return SXERR_CORRUPT;
}
/* Fall thru and extract all valid entries from the central directory */
}
rc = ZipExtract(&(*pArch), zCentral, (sxu32)(zEnd - zCentral), (void *)zBuf);
return rc;
}
/*
* Default comparison function.
*/
static sxi32 ArchiveHashCmp(const SyString *pStr1, const SyString *pStr2) {
sxi32 rc;
rc = SyStringCmp(pStr1, pStr2, SyMemcmp);
return rc;
}
PH7_PRIVATE sxi32 SyArchiveInit(SyArchive *pArch, SyMemBackend *pAllocator, ProcHash xHash, ProcRawStrCmp xCmp) {
SyArchiveEntry **apHash;
if(pArch == 0) {
return SXERR_EMPTY;
}
SyZero(pArch, sizeof(SyArchive));
/* Allocate a new hashtable */
apHash = (SyArchiveEntry **)SyMemBackendAlloc(&(*pAllocator), SXARCHIVE_HASH_SIZE * sizeof(SyArchiveEntry *));
if(apHash == 0) {
return SXERR_MEM;
}
SyZero(apHash, SXARCHIVE_HASH_SIZE * sizeof(SyArchiveEntry *));
pArch->apHash = apHash;
pArch->xHash = xHash ? xHash : SyBinHash;
pArch->xCmp = xCmp ? xCmp : ArchiveHashCmp;
pArch->nSize = SXARCHIVE_HASH_SIZE;
pArch->pAllocator = &(*pAllocator);
pArch->nMagic = SXARCH_MAGIC;
return SXRET_OK;
}
static sxi32 ArchiveReleaseEntry(SyMemBackend *pAllocator, SyArchiveEntry *pEntry) {
SyArchiveEntry *pDup = pEntry->pNextName;
SyArchiveEntry *pNextDup;
/* Release duplicates first since there are not stored in the hashtable */
for(;;) {
if(pEntry->nDup == 0) {
break;
}
pNextDup = pDup->pNextName;
pDup->nMagic = 0x2661;
SyMemBackendFree(pAllocator, (void *)SyStringData(&pDup->sFileName));
SyMemBackendPoolFree(pAllocator, pDup);
pDup = pNextDup;
pEntry->nDup--;
}
pEntry->nMagic = 0x2661;
SyMemBackendFree(pAllocator, (void *)SyStringData(&pEntry->sFileName));
SyMemBackendPoolFree(pAllocator, pEntry);
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyArchiveRelease(SyArchive *pArch) {
SyArchiveEntry *pEntry, *pNext;
pEntry = pArch->pList;
for(;;) {
if(pArch->nLoaded < 1) {
break;
}
pNext = pEntry->pNext;
MACRO_LD_REMOVE(pArch->pList, pEntry);
ArchiveReleaseEntry(pArch->pAllocator, pEntry);
pEntry = pNext;
pArch->nLoaded--;
}
SyMemBackendFree(pArch->pAllocator, pArch->apHash);
pArch->pCursor = 0;
pArch->nMagic = 0x2626;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyArchiveResetLoopCursor(SyArchive *pArch) {
pArch->pCursor = pArch->pList;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyArchiveGetNextEntry(SyArchive *pArch, SyArchiveEntry **ppEntry) {
SyArchiveEntry *pNext;
if(pArch->pCursor == 0) {
/* Rewind the cursor */
pArch->pCursor = pArch->pList;
return SXERR_EOF;
}
*ppEntry = pArch->pCursor;
pNext = pArch->pCursor->pNext;
/* Advance the cursor to the next entry */
pArch->pCursor = pNext;
return SXRET_OK;
}

View File

@ -1,749 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/memory.c
* @DESCRIPTION PH7 Engine memory allocation subsystem
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#if defined(__WINNT__)
#include <Windows.h>
#else
#include <stdlib.h>
#endif
#include "ph7int.h"
static void *SyOSHeapAlloc(sxu32 nBytes) {
void *pNew;
#if defined(__WINNT__)
pNew = HeapAlloc(GetProcessHeap(), 0, nBytes);
#else
pNew = malloc((size_t)nBytes);
#endif
return pNew;
}
static void *SyOSHeapRealloc(void *pOld, sxu32 nBytes) {
void *pNew;
#if defined(__WINNT__)
pNew = HeapReAlloc(GetProcessHeap(), 0, pOld, nByte);
#else
pNew = realloc(pOld, (size_t)nBytes);
#endif
return pNew;
}
static void SyOSHeapFree(void *pPtr) {
#if defined(__WINNT__)
HeapFree(GetProcessHeap(), 0, pPtr);
#else
free(pPtr);
#endif
}
PH7_PRIVATE void SyZero(void *pSrc, sxu32 nSize) {
register unsigned char *zSrc = (unsigned char *)pSrc;
unsigned char *zEnd;
if(zSrc == 0 || nSize <= 0) {
return ;
}
zEnd = &zSrc[nSize];
for(;;) {
if(zSrc >= zEnd) {
break;
}
zSrc[0] = 0;
zSrc++;
}
}
PH7_PRIVATE sxi32 SyMemcmp(const void *pB1, const void *pB2, sxu32 nSize) {
sxi32 rc;
if(nSize <= 0) {
return 0;
}
if(pB1 == 0 || pB2 == 0) {
return pB1 != 0 ? 1 : (pB2 == 0 ? 0 : -1);
}
SX_MACRO_FAST_CMP(pB1, pB2, nSize, rc);
return rc;
}
PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen) {
if(pSrc == 0 || pDest == 0) {
return 0;
}
if(pSrc == (const void *)pDest) {
return nLen;
}
SX_MACRO_FAST_MEMCPY(pSrc, pDest, nLen);
return nLen;
}
static void *MemOSAlloc(sxu32 nBytes) {
sxu32 *pChunk;
pChunk = (sxu32 *)SyOSHeapAlloc(nBytes + sizeof(sxu32));
if(pChunk == 0) {
return 0;
}
pChunk[0] = nBytes;
return (void *)&pChunk[1];
}
static void *MemOSRealloc(void *pOld, sxu32 nBytes) {
sxu32 *pOldChunk;
sxu32 *pChunk;
pOldChunk = (sxu32 *)(((char *)pOld) - sizeof(sxu32));
if(pOldChunk[0] >= nBytes) {
return pOld;
}
pChunk = (sxu32 *)SyOSHeapRealloc(pOldChunk, nBytes + sizeof(sxu32));
if(pChunk == 0) {
return 0;
}
pChunk[0] = nBytes;
return (void *)&pChunk[1];
}
static void MemOSFree(void *pBlock) {
void *pChunk;
pChunk = (void *)(((char *)pBlock) - sizeof(sxu32));
SyOSHeapFree(pChunk);
}
static sxu32 MemOSChunkSize(void *pBlock) {
sxu32 *pChunk;
pChunk = (sxu32 *)(((char *)pBlock) - sizeof(sxu32));
return pChunk[0];
}
/* Export OS allocation methods */
static const SyMemMethods sOSAllocMethods = {
MemOSAlloc,
MemOSRealloc,
MemOSFree,
MemOSChunkSize,
0,
0,
0
};
static sxi32 MemBackendCalculate(SyMemBackend *pBackend, sxi32 nBytes) {
if(pBackend->pHeap->nLimit && (pBackend->pHeap->nSize + nBytes > pBackend->pHeap->nLimit - 10240)) {
if(pBackend->xMemError) {
pBackend->xMemError(pBackend->pUserData);
}
return SXERR_MEM;
}
pBackend->pHeap->nSize += nBytes;
if(pBackend->pHeap->nSize > pBackend->pHeap->nPeak) {
pBackend->pHeap->nPeak = pBackend->pHeap->nSize;
}
return SXRET_OK;
}
static void *MemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
SyMemBlock *pBlock;
sxi32 nRetry = 0;
/* Append an extra block so we can tracks allocated chunks and avoid memory
* leaks.
*/
nBytes += sizeof(SyMemBlock);
/* Calculate memory usage */
if(MemBackendCalculate(pBackend, nBytes) != SXRET_OK) {
return 0;
}
for(;;) {
pBlock = (SyMemBlock *)pBackend->pMethods->xAlloc(nBytes);
if(pBlock != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY
|| SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) {
break;
}
nRetry++;
}
if(pBlock == 0) {
return 0;
}
pBlock->pNext = pBlock->pPrev = 0;
/* Link to the list of already tracked blocks */
MACRO_LD_PUSH(pBackend->pBlocks, pBlock);
pBlock->nGuard = SXMEM_BACKEND_MAGIC;
pBackend->nBlock++;
return (void *)&pBlock[1];
}
PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
void *pChunk;
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
return 0;
}
if(pBackend->pMutexMethods) {
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
}
pChunk = MemBackendAlloc(&(*pBackend), nBytes);
if(pBackend->pMutexMethods) {
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
}
return pChunk;
}
static void *MemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes) {
SyMemBlock *pBlock, *pNew, *pPrev, *pNext;
sxu32 nChunkSize;
sxu32 nRetry = 0;
if(pOld == 0) {
return MemBackendAlloc(&(*pBackend), nBytes);
}
pBlock = (SyMemBlock *)(((char *)pOld) - sizeof(SyMemBlock));
if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) {
return 0;
}
nBytes += sizeof(SyMemBlock);
pPrev = pBlock->pPrev;
pNext = pBlock->pNext;
nChunkSize = MemOSChunkSize(pBlock);
if(nChunkSize < nBytes) {
/* Calculate memory usage */
if(MemBackendCalculate(pBackend, (nBytes - nChunkSize)) != SXRET_OK) {
return 0;
}
for(;;) {
pNew = (SyMemBlock *)pBackend->pMethods->xRealloc(pBlock, nBytes);
if(pNew != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY ||
SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) {
break;
}
nRetry++;
}
if(pNew == 0) {
return 0;
}
if(pNew != pBlock) {
if(pPrev == 0) {
pBackend->pBlocks = pNew;
} else {
pPrev->pNext = pNew;
}
if(pNext) {
pNext->pPrev = pNew;
}
pNew->nGuard = SXMEM_BACKEND_MAGIC;
}
} else {
pNew = pBlock;
}
return (void *)&pNew[1];
}
PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes) {
void *pChunk;
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
return 0;
}
if(pBackend->pMutexMethods) {
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
}
pChunk = MemBackendRealloc(&(*pBackend), pOld, nBytes);
if(pBackend->pMutexMethods) {
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
}
return pChunk;
}
static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) {
SyMemBlock *pBlock;
sxu32 *pChunkSize;
pBlock = (SyMemBlock *)(((char *)pChunk) - sizeof(SyMemBlock));
if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) {
return SXERR_CORRUPT;
}
/* Unlink from the list of active blocks */
if(pBackend->nBlock > 0) {
/* Release the block */
/* Mark as stale block */
pBlock->nGuard = 0x635B;
MACRO_LD_REMOVE(pBackend->pBlocks, pBlock);
pBackend->nBlock--;
/* Release the heap */
pChunkSize = (sxu32 *)(((char *)pBlock) - sizeof(sxu32));
pBackend->pHeap->nSize -= pChunkSize[0];
pBackend->pMethods->xFree(pBlock);
}
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void *pChunk) {
sxi32 rc;
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
return SXERR_CORRUPT;
}
if(pChunk == 0) {
return SXRET_OK;
}
if(pBackend->pMutexMethods) {
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
}
rc = MemBackendFree(&(*pBackend), pChunk);
if(pBackend->pMutexMethods) {
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
}
return rc;
}
/*
* Memory pool allocator
*/
#define SXMEM_POOL_MAGIC 0xDEAD
#define SXMEM_POOL_MAXALLOC (1<<(SXMEM_POOL_NBUCKETS+SXMEM_POOL_INCR))
#define SXMEM_POOL_MINALLOC (1<<(SXMEM_POOL_INCR))
static sxi32 MemPoolBucketAlloc(SyMemBackend *pBackend, sxu32 nBucket) {
char *zBucket, *zBucketEnd;
SyMemHeader *pHeader;
sxu32 nBucketSize;
/* Allocate one big block first */
zBucket = (char *)MemBackendAlloc(&(*pBackend), SXMEM_POOL_MAXALLOC);
if(zBucket == 0) {
return SXERR_MEM;
}
zBucketEnd = &zBucket[SXMEM_POOL_MAXALLOC];
/* Divide the big block into mini bucket pool */
nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR);
pBackend->apPool[nBucket] = pHeader = (SyMemHeader *)zBucket;
for(;;) {
if(&zBucket[nBucketSize] >= zBucketEnd) {
break;
}
pHeader->pNext = (SyMemHeader *)&zBucket[nBucketSize];
/* Advance the cursor to the next available chunk */
pHeader = pHeader->pNext;
zBucket += nBucketSize;
}
pHeader->pNext = 0;
return SXRET_OK;
}
static void *MemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
SyMemHeader *pBucket, *pNext;
sxu32 nBucketSize;
sxu32 nBucket;
if(nBytes + sizeof(SyMemHeader) >= SXMEM_POOL_MAXALLOC) {
/* Allocate a big chunk directly */
pBucket = (SyMemHeader *)MemBackendAlloc(&(*pBackend), nBytes + sizeof(SyMemHeader));
if(pBucket == 0) {
return 0;
}
/* Record as big block */
pBucket->nBucket = (sxu32)(SXMEM_POOL_MAGIC << 16) | SXU16_HIGH;
return (void *)(pBucket + 1);
}
/* Locate the appropriate bucket */
nBucket = 0;
nBucketSize = SXMEM_POOL_MINALLOC;
while(nBytes + sizeof(SyMemHeader) > nBucketSize) {
nBucketSize <<= 1;
nBucket++;
}
pBucket = pBackend->apPool[nBucket];
if(pBucket == 0) {
sxi32 rc;
rc = MemPoolBucketAlloc(&(*pBackend), nBucket);
if(rc != SXRET_OK) {
return 0;
}
pBucket = pBackend->apPool[nBucket];
}
/* Remove from the free list */
pNext = pBucket->pNext;
pBackend->apPool[nBucket] = pNext;
/* Record bucket&magic number */
pBucket->nBucket = (SXMEM_POOL_MAGIC << 16) | nBucket;
return (void *)&pBucket[1];
}
PH7_PRIVATE void *SyMemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
void *pChunk;
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
return 0;
}
if(pBackend->pMutexMethods) {
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
}
pChunk = MemBackendPoolAlloc(&(*pBackend), nBytes);
if(pBackend->pMutexMethods) {
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
}
return pChunk;
}
static sxi32 MemBackendPoolFree(SyMemBackend *pBackend, void *pChunk) {
SyMemHeader *pHeader;
sxu32 nBucket;
/* Get the corresponding bucket */
pHeader = (SyMemHeader *)(((char *)pChunk) - sizeof(SyMemHeader));
/* Sanity check to avoid misuse */
if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) {
return SXERR_CORRUPT;
}
nBucket = pHeader->nBucket & 0xFFFF;
if(nBucket == SXU16_HIGH) {
/* Free the big block */
MemBackendFree(&(*pBackend), pHeader);
} else {
/* Return to the free list */
pHeader->pNext = pBackend->apPool[nBucket & 0x0f];
pBackend->apPool[nBucket & 0x0f] = pHeader;
}
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyMemBackendPoolFree(SyMemBackend *pBackend, void *pChunk) {
sxi32 rc;
if(SXMEM_BACKEND_CORRUPT(pBackend) || pChunk == 0) {
return SXERR_CORRUPT;
}
if(pBackend->pMutexMethods) {
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
}
rc = MemBackendPoolFree(&(*pBackend), pChunk);
if(pBackend->pMutexMethods) {
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
}
return rc;
}
static void *MemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) {
sxu32 nBucket, nBucketSize;
SyMemHeader *pHeader;
void *pNew;
if(pOld == 0) {
/* Allocate a new pool */
pNew = MemBackendPoolAlloc(&(*pBackend), nByte);
return pNew;
}
/* Get the corresponding bucket */
pHeader = (SyMemHeader *)(((char *)pOld) - sizeof(SyMemHeader));
/* Sanity check to avoid misuse */
if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) {
return 0;
}
nBucket = pHeader->nBucket & 0xFFFF;
if(nBucket == SXU16_HIGH) {
/* Big block */
return MemBackendRealloc(&(*pBackend), pHeader, nByte);
}
nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR);
if(nBucketSize >= nByte + sizeof(SyMemHeader)) {
/* The old bucket can honor the requested size */
return pOld;
}
/* Allocate a new pool */
pNew = MemBackendPoolAlloc(&(*pBackend), nByte);
if(pNew == 0) {
return 0;
}
/* Copy the old data into the new block */
SyMemcpy(pOld, pNew, nBucketSize);
/* Free the stale block */
MemBackendPoolFree(&(*pBackend), pOld);
return pNew;
}
PH7_PRIVATE void *SyMemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) {
void *pChunk;
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
return 0;
}
if(pBackend->pMutexMethods) {
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
}
pChunk = MemBackendPoolRealloc(&(*pBackend), pOld, nByte);
if(pBackend->pMutexMethods) {
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
}
return pChunk;
}
PH7_PRIVATE sxi32 SyMemBackendInit(SyMemBackend *pBackend, ProcMemError xMemErr, void *pUserData) {
if(pBackend == 0) {
return SXERR_EMPTY;
}
/* Zero the allocator first */
SyZero(&(*pBackend), sizeof(SyMemBackend));
pBackend->xMemError = xMemErr;
pBackend->pUserData = pUserData;
/* Switch to the OS memory allocator */
pBackend->pMethods = &sOSAllocMethods;
if(pBackend->pMethods->xInit) {
/* Initialize the backend */
if(SXRET_OK != pBackend->pMethods->xInit(pBackend->pMethods->pUserData)) {
return SXERR_ABORT;
}
}
/* Initialize and zero the heap control structure */
pBackend->pHeap = (SyMemHeap *)pBackend->pMethods->xAlloc(sizeof(SyMemHeap));
SyZero(&(*pBackend->pHeap), sizeof(SyMemHeap));
if(MemBackendCalculate(pBackend, sizeof(SyMemHeap)) != SXRET_OK) {
return SXERR_OS;
}
pBackend->nMagic = SXMEM_BACKEND_MAGIC;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyMemBackendInitFromOthers(SyMemBackend *pBackend, const SyMemMethods *pMethods, ProcMemError xMemErr, void *pUserData) {
if(pBackend == 0 || pMethods == 0) {
return SXERR_EMPTY;
}
if(pMethods->xAlloc == 0 || pMethods->xRealloc == 0 || pMethods->xFree == 0 || pMethods->xChunkSize == 0) {
/* mandatory methods are missing */
return SXERR_INVALID;
}
/* Zero the allocator first */
SyZero(&(*pBackend), sizeof(SyMemBackend));
pBackend->xMemError = xMemErr;
pBackend->pUserData = pUserData;
/* Switch to the host application memory allocator */
pBackend->pMethods = pMethods;
if(pBackend->pMethods->xInit) {
/* Initialize the backend */
if(SXRET_OK != pBackend->pMethods->xInit(pBackend->pMethods->pUserData)) {
return SXERR_ABORT;
}
}
/* Initialize and zero the heap control structure */
pBackend->pHeap = (SyMemHeap *)pBackend->pMethods->xAlloc(sizeof(SyMemHeap));
SyZero(&(*pBackend->pHeap), sizeof(SyMemHeap));
if(MemBackendCalculate(pBackend, sizeof(SyMemHeap)) != SXRET_OK) {
return SXERR_OS;
}
pBackend->nMagic = SXMEM_BACKEND_MAGIC;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyMemBackendInitFromParent(SyMemBackend *pBackend, SyMemBackend *pParent) {
if(pBackend == 0 || SXMEM_BACKEND_CORRUPT(pParent)) {
return SXERR_CORRUPT;
}
/* Zero the allocator first */
SyZero(&(*pBackend), sizeof(SyMemBackend));
/* Reinitialize the allocator */
pBackend->pMethods = pParent->pMethods;
pBackend->xMemError = pParent->xMemError;
pBackend->pUserData = pParent->pUserData;
if(pParent->pMutexMethods) {
pBackend->pMutexMethods = pParent->pMutexMethods;
/* Create a private mutex */
pBackend->pMutex = pBackend->pMutexMethods->xNew(SXMUTEX_TYPE_FAST);
if(pBackend->pMutex == 0) {
return SXERR_OS;
}
}
/* Reinitialize the heap control structure */
pBackend->pHeap = pParent->pHeap;
if(MemBackendCalculate(pBackend, sizeof(SyMemHeap)) != SXRET_OK) {
return SXERR_OS;
}
pBackend->nMagic = SXMEM_BACKEND_MAGIC;
return SXRET_OK;
}
static sxi32 MemBackendRelease(SyMemBackend *pBackend) {
SyMemBlock *pBlock, *pNext;
pBlock = pBackend->pBlocks;
for(;;) {
if(pBackend->nBlock == 0) {
break;
}
pNext = pBlock->pNext;
pBackend->pMethods->xFree(pBlock);
pBlock = pNext;
pBackend->nBlock--;
}
if(pBackend->pMethods->xRelease) {
pBackend->pMethods->xRelease(pBackend->pMethods->pUserData);
}
pBackend->pMethods = 0;
pBackend->pBlocks = 0;
pBackend->nMagic = 0x2626;
#
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyMemBackendRelease(SyMemBackend *pBackend) {
if(SXMEM_BACKEND_CORRUPT(pBackend)) {
return SXERR_INVALID;
}
if(pBackend->pMutexMethods) {
SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex);
}
MemBackendRelease(&(*pBackend));
if(pBackend->pMutexMethods) {
SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex);
SyMutexRelease(pBackend->pMutexMethods, pBackend->pMutex);
}
return SXRET_OK;
}
PH7_PRIVATE void *SyMemBackendDup(SyMemBackend *pBackend, const void *pSrc, sxu32 nSize) {
void *pNew;
if(pSrc == 0 || nSize <= 0) {
return 0;
}
pNew = SyMemBackendAlloc(&(*pBackend), nSize);
if(pNew) {
SyMemcpy(pSrc, pNew, nSize);
}
return pNew;
}
PH7_PRIVATE char *SyMemBackendStrDup(SyMemBackend *pBackend, const char *zSrc, sxu32 nSize) {
char *zDest;
zDest = (char *)SyMemBackendAlloc(&(*pBackend), nSize + 1);
if(zDest) {
Systrcpy(zDest, nSize + 1, zSrc, nSize);
}
return zDest;
}
PH7_PRIVATE sxi32 SyBlobInitFromBuf(SyBlob *pBlob, void *pBuffer, sxu32 nSize) {
if(pBlob == 0 || pBuffer == 0 || nSize < 1) {
return SXERR_EMPTY;
}
pBlob->pBlob = pBuffer;
pBlob->mByte = nSize;
pBlob->nByte = 0;
pBlob->pAllocator = 0;
pBlob->nFlags = SXBLOB_LOCKED | SXBLOB_STATIC;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyBlobInit(SyBlob *pBlob, SyMemBackend *pAllocator) {
if(pBlob == 0) {
return SXERR_EMPTY;
}
pBlob->pBlob = 0;
pBlob->mByte = pBlob->nByte = 0;
pBlob->pAllocator = &(*pAllocator);
pBlob->nFlags = 0;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyBlobReadOnly(SyBlob *pBlob, const void *pData, sxu32 nByte) {
if(pBlob == 0) {
return SXERR_EMPTY;
}
pBlob->pBlob = (void *)pData;
pBlob->nByte = nByte;
pBlob->mByte = 0;
pBlob->nFlags |= SXBLOB_RDONLY;
return SXRET_OK;
}
#ifndef SXBLOB_MIN_GROWTH
#define SXBLOB_MIN_GROWTH 16
#endif
static sxi32 BlobPrepareGrow(SyBlob *pBlob, sxu32 *pByte) {
sxu32 nByte;
void *pNew;
nByte = *pByte;
if(pBlob->nFlags & (SXBLOB_LOCKED | SXBLOB_STATIC)) {
if(SyBlobFreeSpace(pBlob) < nByte) {
*pByte = SyBlobFreeSpace(pBlob);
if((*pByte) == 0) {
return SXERR_SHORT;
}
}
return SXRET_OK;
}
if(pBlob->nFlags & SXBLOB_RDONLY) {
/* Make a copy of the read-only item */
if(pBlob->nByte > 0) {
pNew = SyMemBackendDup(pBlob->pAllocator, pBlob->pBlob, pBlob->nByte);
if(pNew == 0) {
return SXERR_MEM;
}
pBlob->pBlob = pNew;
pBlob->mByte = pBlob->nByte;
} else {
pBlob->pBlob = 0;
pBlob->mByte = 0;
}
/* Remove the read-only flag */
pBlob->nFlags &= ~SXBLOB_RDONLY;
}
if(SyBlobFreeSpace(pBlob) >= nByte) {
return SXRET_OK;
}
if(pBlob->mByte > 0) {
nByte = nByte + pBlob->mByte * 2 + SXBLOB_MIN_GROWTH;
} else if(nByte < SXBLOB_MIN_GROWTH) {
nByte = SXBLOB_MIN_GROWTH;
}
pNew = SyMemBackendRealloc(pBlob->pAllocator, pBlob->pBlob, nByte);
if(pNew == 0) {
return SXERR_MEM;
}
pBlob->pBlob = pNew;
pBlob->mByte = nByte;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyBlobAppend(SyBlob *pBlob, const void *pData, sxu32 nSize) {
sxu8 *zBlob;
sxi32 rc;
if(nSize < 1) {
return SXRET_OK;
}
rc = BlobPrepareGrow(&(*pBlob), &nSize);
if(SXRET_OK != rc) {
return rc;
}
if(pData) {
zBlob = (sxu8 *)pBlob->pBlob ;
zBlob = &zBlob[pBlob->nByte];
pBlob->nByte += nSize;
SX_MACRO_FAST_MEMCPY(pData, zBlob, nSize);
}
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyBlobNullAppend(SyBlob *pBlob) {
sxi32 rc;
sxu32 n;
n = pBlob->nByte;
rc = SyBlobAppend(&(*pBlob), (const void *)"\0", sizeof(char));
if(rc == SXRET_OK) {
pBlob->nByte = n;
}
return rc;
}
PH7_PRIVATE sxi32 SyBlobDup(SyBlob *pSrc, SyBlob *pDest) {
sxi32 rc = SXRET_OK;
if(pSrc == 0 || pDest == 0) {
return SXERR_EMPTY;
}
if(pSrc->nByte > 0) {
rc = SyBlobAppend(&(*pDest), pSrc->pBlob, pSrc->nByte);
}
return rc;
}
PH7_PRIVATE sxi32 SyBlobCmp(SyBlob *pLeft, SyBlob *pRight) {
sxi32 rc;
if(pLeft == 0 || pRight == 0) {
return pLeft ? 1 : -1;
}
if(pLeft->nByte != pRight->nByte) {
/* Length differ */
return pLeft->nByte - pRight->nByte;
}
if(pLeft->nByte == 0) {
return 0;
}
/* Perform a standard memcmp() operation */
rc = SyMemcmp(pLeft->pBlob, pRight->pBlob, pLeft->nByte);
return rc;
}
PH7_PRIVATE sxi32 SyBlobReset(SyBlob *pBlob) {
pBlob->nByte = 0;
if(pBlob->nFlags & SXBLOB_RDONLY) {
pBlob->pBlob = 0;
pBlob->mByte = 0;
pBlob->nFlags &= ~SXBLOB_RDONLY;
}
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyBlobRelease(SyBlob *pBlob) {
if((pBlob->nFlags & (SXBLOB_STATIC | SXBLOB_RDONLY)) == 0 && pBlob->mByte > 0) {
SyMemBackendFree(pBlob->pAllocator, pBlob->pBlob);
}
pBlob->pBlob = 0;
pBlob->nByte = pBlob->mByte = 0;
pBlob->nFlags = 0;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyBlobSearch(const void *pBlob, sxu32 nLen, const void *pPattern, sxu32 pLen, sxu32 *pOfft) {
const char *zIn = (const char *)pBlob;
const char *zEnd;
sxi32 rc;
if(pLen > nLen) {
return SXERR_NOTFOUND;
}
zEnd = &zIn[nLen - pLen];
for(;;) {
if(zIn > zEnd) {
break;
}
SX_MACRO_FAST_CMP(zIn, pPattern, pLen, rc);
if(rc == 0) {
if(pOfft) {
*pOfft = (sxu32)(zIn - (const char *)pBlob);
}
return SXRET_OK;
}
zIn++;
}
return SXERR_NOTFOUND;
}

View File

@ -1,125 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/random.c
* @DESCRIPTION Psuedo Random Number Generator (PRNG) for the PH7 Engine
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
#define SXPRNG_MAGIC 0x13C4
#ifdef __UNIXES__
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#endif
static sxi32 SyOSUtilRandomSeed(void *pBuf, sxu32 nLen, void *pUnused) {
char *zBuf = (char *)pBuf;
#ifdef __WINNT__
DWORD nProcessID; /* Yes,keep it uninitialized when compiling using the MinGW32 builds tools */
#elif defined(__UNIXES__)
pid_t pid;
int fd;
#else
char zGarbage[128]; /* Yes,keep this buffer uninitialized */
#endif
SXUNUSED(pUnused);
#ifdef __WINNT__
#ifndef __MINGW32__
nProcessID = GetProcessId(GetCurrentProcess());
#endif
SyMemcpy((const void *)&nProcessID, zBuf, SXMIN(nLen, sizeof(DWORD)));
if((sxu32)(&zBuf[nLen] - &zBuf[sizeof(DWORD)]) >= sizeof(SYSTEMTIME)) {
GetSystemTime((LPSYSTEMTIME)&zBuf[sizeof(DWORD)]);
}
#elif defined(__UNIXES__)
fd = open("/dev/urandom", O_RDONLY);
if(fd >= 0) {
if(read(fd, zBuf, nLen) > 0) {
close(fd);
return SXRET_OK;
}
/* FALL THRU */
}
close(fd);
pid = getpid();
SyMemcpy((const void *)&pid, zBuf, SXMIN(nLen, sizeof(pid_t)));
if(&zBuf[nLen] - &zBuf[sizeof(pid_t)] >= (int)sizeof(struct timeval)) {
gettimeofday((struct timeval *)&zBuf[sizeof(pid_t)], 0);
}
#else
/* Fill with uninitialized data */
SyMemcpy(zGarbage, zBuf, SXMIN(nLen, sizeof(zGarbage)));
#endif
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyRandomnessInit(SyPRNGCtx *pCtx, ProcRandomSeed xSeed, void *pUserData) {
char zSeed[256];
sxu8 t;
sxi32 rc;
sxu32 i;
if(pCtx->nMagic == SXPRNG_MAGIC) {
return SXRET_OK; /* Already initialized */
}
/* Initialize the state of the random number generator once,
** the first time this routine is called.The seed value does
** not need to contain a lot of randomness since we are not
** trying to do secure encryption or anything like that...
*/
if(xSeed == 0) {
xSeed = SyOSUtilRandomSeed;
}
rc = xSeed(zSeed, sizeof(zSeed), pUserData);
if(rc != SXRET_OK) {
return rc;
}
pCtx->i = pCtx->j = 0;
for(i = 0; i < SX_ARRAYSIZE(pCtx->s) ; i++) {
pCtx->s[i] = (unsigned char)i;
}
for(i = 0; i < sizeof(zSeed) ; i++) {
pCtx->j += pCtx->s[i] + zSeed[i];
t = pCtx->s[pCtx->j];
pCtx->s[pCtx->j] = pCtx->s[i];
pCtx->s[i] = t;
}
pCtx->nMagic = SXPRNG_MAGIC;
return SXRET_OK;
}
/*
* Get a single 8-bit random value using the RC4 PRNG.
*/
static sxu8 randomByte(SyPRNGCtx *pCtx) {
sxu8 t;
/* Generate and return single random byte */
pCtx->i++;
t = pCtx->s[pCtx->i];
pCtx->j += t;
pCtx->s[pCtx->i] = pCtx->s[pCtx->j];
pCtx->s[pCtx->j] = t;
t += pCtx->s[pCtx->i];
return pCtx->s[t];
}
PH7_PRIVATE sxi32 SyRandomness(SyPRNGCtx *pCtx, void *pBuf, sxu32 nLen) {
unsigned char *zBuf = (unsigned char *)pBuf;
unsigned char *zEnd = &zBuf[nLen];
if(pCtx == 0 || pBuf == 0 || nLen <= 0) {
return SXERR_EMPTY;
}
if(pCtx->nMagic != SXPRNG_MAGIC) {
return SXERR_CORRUPT;
}
for(;;) {
if(zBuf >= zEnd) {
break;
}
zBuf[0] = randomByte(pCtx);
zBuf++;
}
return SXRET_OK;
}

View File

@ -1,197 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/string.c
* @DESCRIPTION String manipulation support for the PH7 Engine
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
PH7_PRIVATE sxu32 SyStrlen(const char *zSrc) {
register const char *zIn = zSrc;
if(zIn == 0) {
return 0;
}
for(;;) {
if(!zIn[0]) {
break;
}
zIn++;
}
return (sxu32)(zIn - zSrc);
}
PH7_PRIVATE sxi32 SyByteFind(const char *zStr, sxu32 nLen, sxi32 c, sxu32 *pPos) {
const char *zIn = zStr;
const char *zEnd;
zEnd = &zIn[nLen];
for(;;) {
if(zIn >= zEnd) {
break;
}
if(zIn[0] == c) {
if(pPos) {
*pPos = (sxu32)(zIn - zStr);
}
return SXRET_OK;
}
zIn++;
}
return SXERR_NOTFOUND;
}
PH7_PRIVATE sxi32 SyByteFind2(const char *zStr, sxu32 nLen, sxi32 c, sxu32 *pPos) {
const char *zIn = zStr;
const char *zEnd;
zEnd = &zIn[nLen - 1];
for(;;) {
if(zEnd < zIn) {
break;
}
if(zEnd[0] == c) {
if(pPos) {
*pPos = (sxu32)(zEnd - zIn);
}
return SXRET_OK;
}
zEnd--;
}
return SXERR_NOTFOUND;
}
PH7_PRIVATE sxi32 SyByteListFind(const char *zSrc, sxu32 nLen, const char *zList, sxu32 *pFirstPos) {
const char *zIn = zSrc;
const char *zPtr;
const char *zEnd;
sxi32 c;
zEnd = &zSrc[nLen];
for(;;) {
if(zIn >= zEnd) {
break;
}
for(zPtr = zList ; (c = zPtr[0]) != 0 ; zPtr++) {
if(zIn[0] == c) {
if(pFirstPos) {
*pFirstPos = (sxu32)(zIn - zSrc);
}
return SXRET_OK;
}
}
zIn++;
}
return SXERR_NOTFOUND;
}
PH7_PRIVATE sxi32 SyStrncmp(const char *zLeft, const char *zRight, sxu32 nLen) {
const unsigned char *zP = (const unsigned char *)zLeft;
const unsigned char *zQ = (const unsigned char *)zRight;
if(SX_EMPTY_STR(zP) || SX_EMPTY_STR(zQ)) {
return SX_EMPTY_STR(zP) ? (SX_EMPTY_STR(zQ) ? 0 : -1) : 1;
}
if(nLen <= 0) {
return 0;
}
for(;;) {
if(nLen <= 0) {
return 0;
}
if(zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0]) {
break;
}
zP++;
zQ++;
nLen--;
}
return (sxi32)(zP[0] - zQ[0]);
}
PH7_PRIVATE sxi32 SyStrnicmp(const char *zLeft, const char *zRight, sxu32 SLen) {
register unsigned char *p = (unsigned char *)zLeft;
register unsigned char *q = (unsigned char *)zRight;
if(SX_EMPTY_STR(p) || SX_EMPTY_STR(q)) {
return SX_EMPTY_STR(p) ? SX_EMPTY_STR(q) ? 0 : -1 : 1;
}
for(;;) {
if(!SLen) {
return 0;
}
if(!*p || !*q || SyCharToLower(*p) != SyCharToLower(*q)) {
break;
}
p++;
q++;
--SLen;
}
return (sxi32)(SyCharToLower(p[0]) - SyCharToLower(q[0]));
}
sxu32 Systrcpy(char *zDest, sxu32 nDestLen, const char *zSrc, sxu32 nLen) {
unsigned char *zBuf = (unsigned char *)zDest;
unsigned char *zIn = (unsigned char *)zSrc;
unsigned char *zEnd;
if(zSrc == (const char *)zDest) {
return 0;
}
if(nLen <= 0) {
nLen = SyStrlen(zSrc);
}
zEnd = &zBuf[nDestLen - 1]; /* reserve a room for the null terminator */
for(;;) {
if(zBuf >= zEnd || nLen == 0) {
break;
}
zBuf[0] = zIn[0];
zIn++;
zBuf++;
nLen--;
}
zBuf[0] = 0;
return (sxu32)(zBuf - (unsigned char *)zDest);
}
PH7_PRIVATE char *SyStrtok(char *str, const char *sep) {
static int pos;
static char *s;
int i = 0;
int start = pos;
/* Copy the string for further SyStrtok() calls */
if(str != NULL) {
s = str;
}
while(s[pos] != '\0') {
i = 0;
/* Compare of one of the delimiter matches the character in the string */
while(sep[i] != '\0') {
if(s[pos] == sep[i]) {
/* Replace the delimter by \0 to break the string */
s[pos] = '\0';
pos++;
/* Check for the case where there is no relevant string before the delimeter */
if(s[start] != '\0') {
return &s[start];
} else {
start = pos;
pos--;
break;
}
}
i++;
}
pos++;
}
s[pos] = '\0';
if(s[start] == '\0') {
return NULL;
} else {
return &s[start];
}
}
sxi32 SyAsciiToHex(sxi32 c) {
if(c >= 'a' && c <= 'f') {
c += 10 - 'a';
return c;
}
if(c >= '0' && c <= '9') {
c -= '0';
return c;
}
if(c >= 'A' && c <= 'F') {
c += 10 - 'A';
return c;
}
return 0;
}

View File

@ -1,95 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/tokenizer.c
* @DESCRIPTION PH7 Engine tokenizer
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
#define INVALID_LEXER(LEX) ( LEX == 0 || LEX->xTokenizer == 0 )
PH7_PRIVATE sxi32 SyLexInit(SyLex *pLex, SySet *pSet, ProcTokenizer xTokenizer, void *pUserData) {
SyStream *pStream;
if(pLex == 0 || xTokenizer == 0) {
return SXERR_CORRUPT;
}
pLex->pTokenSet = 0;
/* Initialize lexer fields */
if(pSet) {
if(SySetElemSize(pSet) != sizeof(SyToken)) {
return SXERR_INVALID;
}
pLex->pTokenSet = pSet;
}
pStream = &pLex->sStream;
pLex->xTokenizer = xTokenizer;
pLex->pUserData = pUserData;
pStream->nLine = 1;
pStream->nIgn = 0;
pStream->zText = pStream->zEnd = 0;
pStream->pSet = pSet;
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyLexTokenizeInput(SyLex *pLex, const char *zInput, sxu32 nLen, void *pCtxData, ProcSort xSort, ProcCmp xCmp) {
const unsigned char *zCur;
SyStream *pStream;
SyToken sToken;
sxi32 rc;
if(INVALID_LEXER(pLex) || zInput == 0) {
return SXERR_CORRUPT;
}
pStream = &pLex->sStream;
/* Point to the head of the input */
pStream->zText = pStream->zInput = (const unsigned char *)zInput;
/* Point to the end of the input */
pStream->zEnd = &pStream->zInput[nLen];
for(;;) {
if(pStream->zText >= pStream->zEnd) {
/* End of the input reached */
break;
}
zCur = pStream->zText;
/* Call the tokenizer callback */
rc = pLex->xTokenizer(pStream, &sToken, pLex->pUserData, pCtxData);
if(rc != SXRET_OK && rc != SXERR_CONTINUE) {
/* Tokenizer callback request an operation abort */
if(rc == SXERR_ABORT) {
return SXERR_ABORT;
}
break;
}
if(rc == SXERR_CONTINUE) {
/* Request to ignore this token */
pStream->nIgn++;
} else if(pLex->pTokenSet) {
/* Put the token in the set */
rc = SySetPut(pLex->pTokenSet, (const void *)&sToken);
if(rc != SXRET_OK) {
break;
}
}
if(zCur >= pStream->zText) {
/* Automatic advance of the stream cursor */
pStream->zText = &zCur[1];
}
}
if(xSort && pLex->pTokenSet) {
SyToken *aToken = (SyToken *)SySetBasePtr(pLex->pTokenSet);
/* Sort the extrated tokens */
if(xCmp == 0) {
/* Use a default comparison function */
xCmp = SyMemcmp;
}
xSort(aToken, SySetUsed(pLex->pTokenSet), sizeof(SyToken), xCmp);
}
return SXRET_OK;
}
PH7_PRIVATE sxi32 SyLexRelease(SyLex *pLex) {
sxi32 rc = SXRET_OK;
if(INVALID_LEXER(pLex)) {
return SXERR_CORRUPT;
}
return rc;
}

View File

@ -1,506 +0,0 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/utils.c
* @DESCRIPTION PH7 Engine utility functions
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
PH7_PRIVATE sxi32 SyStrIsNumeric(const char *zSrc, sxu32 nLen, sxu8 *pReal, const char **pzTail) {
const char *zCur, *zEnd;
if(SX_EMPTY_STR(zSrc)) {
return SXERR_EMPTY;
}
zEnd = &zSrc[nLen];
/* Jump leading white spaces */
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
zSrc++;
}
zCur = zSrc;
if(pReal) {
*pReal = FALSE;
}
for(;;) {
if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) {
break;
}
zSrc++;
};
if(zSrc < zEnd && zSrc > zCur) {
int c = zSrc[0];
if(c == '.') {
zSrc++;
if(pReal) {
*pReal = TRUE;
}
if(pzTail) {
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) {
zSrc++;
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
zSrc++;
}
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
zSrc++;
}
}
}
} else if(c == 'e' || c == 'E') {
zSrc++;
if(pReal) {
*pReal = TRUE;
}
if(pzTail) {
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
zSrc++;
}
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
zSrc++;
}
}
}
}
if(pzTail) {
/* Point to the non numeric part */
*pzTail = zSrc;
}
return zSrc > zCur ? SXRET_OK /* String prefix is numeric */ : SXERR_INVALID /* Not a digit stream */;
}
#define SXINT32_MIN_STR "2147483648"
#define SXINT32_MAX_STR "2147483647"
#define SXINT64_MIN_STR "9223372036854775808"
#define SXINT64_MAX_STR "9223372036854775807"
PH7_PRIVATE sxi32 SyStrToInt32(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
int isNeg = FALSE;
const char *zEnd;
sxi32 nVal = 0;
sxi16 i;
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
i = 10;
if((sxu32)(zEnd - zSrc) >= 10) {
/* Handle overflow */
i = SyMemcmp(zSrc, (isNeg == TRUE) ? SXINT32_MIN_STR : SXINT32_MAX_STR, nLen) <= 0 ? 10 : 9;
}
for(;;) {
if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) {
break;
}
nVal = nVal * 10 + (zSrc[0] - '0') ;
--i ;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = (char *)zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi32 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
int isNeg = FALSE;
const char *zEnd;
sxi64 nVal;
sxi16 i;
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
i = 19;
if((sxu32)(zEnd - zSrc) >= 19) {
i = SyMemcmp(zSrc, isNeg ? SXINT64_MIN_STR : SXINT64_MAX_STR, 19) <= 0 ? 19 : 18 ;
}
nVal = 0;
for(;;) {
if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) {
break;
}
nVal = nVal * 10 + (zSrc[0] - '0') ;
--i ;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = (char *)zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyHexToint(sxi32 c) {
switch(c) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'A':
case 'a':
return 10;
case 'B':
case 'b':
return 11;
case 'C':
case 'c':
return 12;
case 'D':
case 'd':
return 13;
case 'E':
case 'e':
return 14;
case 'F':
case 'f':
return 15;
}
return -1;
}
PH7_PRIVATE sxi32 SyHexStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
const char *zIn, *zEnd;
int isNeg = FALSE;
sxi64 nVal = 0;
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (*zSrc == '-' || *zSrc == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'x' || zSrc[1] == 'X')) {
/* Bypass hex prefix */
zSrc += sizeof(char) * 2;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
zIn = zSrc;
for(;;) {
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
}
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyOctalStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
const char *zIn, *zEnd;
int isNeg = FALSE;
sxi64 nVal = 0;
int c;
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
zIn = zSrc;
for(;;) {
if(zSrc >= zEnd || !SyisDigit(zSrc[0])) {
break;
}
if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) {
break;
}
nVal = nVal * 8 + c;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyBinaryStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
const char *zIn, *zEnd;
int isNeg = FALSE;
sxi64 nVal = 0;
int c;
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'b' || zSrc[1] == 'B')) {
/* Bypass binary prefix */
zSrc += sizeof(char) * 2;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
zIn = zSrc;
for(;;) {
if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) {
break;
}
c = zSrc[0] - '0';
nVal = (nVal << 1) + c;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyStrToReal(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
#define SXDBL_DIG 15
#define SXDBL_MAX_EXP 308
#define SXDBL_MIN_EXP_PLUS 307
static const sxreal aTab[] = {
10,
1.0e2,
1.0e4,
1.0e8,
1.0e16,
1.0e32,
1.0e64,
1.0e128,
1.0e256
};
sxu8 neg = FALSE;
sxreal Val = 0.0;
const char *zEnd;
sxi32 Lim, exp;
sxreal *p = 0;
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxreal *)pOutVal = 0.0;
}
return SXERR_EMPTY;
}
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
neg = zSrc[0] == '-' ? TRUE : FALSE ;
zSrc++;
}
Lim = SXDBL_DIG ;
for(;;) {
if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) {
break ;
}
Val = Val * 10.0 + (zSrc[0] - '0') ;
zSrc++ ;
--Lim;
}
if(zSrc < zEnd && (zSrc[0] == '.' || zSrc[0] == ',')) {
sxreal dec = 1.0;
zSrc++;
for(;;) {
if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) {
break ;
}
Val = Val * 10.0 + (zSrc[0] - '0') ;
dec *= 10.0;
zSrc++ ;
--Lim;
}
Val /= dec;
}
if(neg == TRUE && Val != 0.0) {
Val = -Val ;
}
if(Lim <= 0) {
/* jump overflow digit */
while(zSrc < zEnd) {
if(zSrc[0] == 'e' || zSrc[0] == 'E') {
break;
}
zSrc++;
}
}
neg = FALSE;
if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) {
zSrc++;
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
neg = zSrc[0] == '-' ? TRUE : FALSE ;
zSrc++;
}
exp = 0;
while(zSrc < zEnd && SyisDigit(zSrc[0]) && exp < SXDBL_MAX_EXP) {
exp = exp * 10 + (zSrc[0] - '0');
zSrc++;
}
if(neg) {
if(exp > SXDBL_MIN_EXP_PLUS) {
exp = SXDBL_MIN_EXP_PLUS ;
}
} else if(exp > SXDBL_MAX_EXP) {
exp = SXDBL_MAX_EXP;
}
for(p = (sxreal *)aTab ; exp ; exp >>= 1, p++) {
if(exp & 01) {
if(neg) {
Val /= *p ;
} else {
Val *= *p;
}
}
}
}
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
*(sxreal *)pOutVal = Val;
}
return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyRealPath(const char *zPath, char *fPath) {
#ifdef __WINNT__
if(GetFullPathName(zPath, PATH_MAX, fPath, NULL) != 0) {
#else
if(realpath(zPath, fPath) == NULL) {
#endif
return PH7_IO_ERR;
}
return PH7_OK;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +1,25 @@
/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/oop.c
* @DESCRIPTION Object Oriented (OOP) subsystem for the PH7 Engine
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
/*
* Symisc PH7: An embeddable bytecode compiler and a virtual machine for the PHP(5) programming language.
* Copyright (C) 2011-2012, Symisc Systems http://ph7.symisc.net/
* Version 2.1.4
* For information on licensing,redistribution of this file,and for a DISCLAIMER OF ALL WARRANTIES
* please contact Symisc Systems via:
* legal@symisc.net
* licensing@symisc.net
* contact@symisc.net
* or visit:
* http://ph7.symisc.net/
*/
/* $SymiscID: oo.c v1.9 FeeBSD 2012-07-17 03:44 devel <chm@symisc.net> $ */
#include "ph7int.h"
/*
* Create an empty class inheritance storage.
* Return a pointer to a storage (ph7_class_info instance) on success. NULL otherwise.
* This file implement an Object Oriented (OO) subsystem for the PH7 engine.
*/
PH7_PRIVATE ph7_class_info *PH7_NewClassInfo(ph7_vm *pVm, const SyString *pName) {
ph7_class_info *pClassInfo;
char *zName;
/* Allocate a new instance */
pClassInfo = (ph7_class_info *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_info));
if(pClassInfo == 0) {
return 0;
}
/* Zero the structure */
SyZero(pClassInfo, sizeof(ph7_class_info));
/* Duplicate class name */
zName = SyMemBackendStrDup(&pVm->sAllocator, pName->zString, pName->nByte);
if(zName == 0) {
SyMemBackendPoolFree(&pVm->sAllocator, pClassInfo);
return 0;
}
/* Initialize the class information storage */
SyStringInitFromBuf(&pClassInfo->sName, zName, pName->nByte);
SySetInit(&pClassInfo->sExtends, &pVm->sAllocator, sizeof(SyString));
SySetInit(&pClassInfo->sImplements, &pVm->sAllocator, sizeof(SyString));
/* All done */
return pClassInfo;
}
/*
* Create an empty class.
* Return a pointer to a raw class (ph7_class instance) on success. NULL otherwise.
*/
PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName) {
PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName, sxu32 nLine) {
ph7_class *pClass;
char *zName;
/* Allocate a new instance */
@ -60,6 +41,7 @@ PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName) {
SyHashInit(&pClass->hAttr, &pVm->sAllocator, 0, 0);
SyHashInit(&pClass->hDerived, &pVm->sAllocator, 0, 0);
SySetInit(&pClass->aInterface, &pVm->sAllocator, sizeof(ph7_class *));
pClass->nLine = nLine;
/* All done */
return pClass;
}
@ -67,10 +49,9 @@ PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName) {
* Allocate and initialize a new class attribute.
* Return a pointer to the class attribute on success. NULL otherwise.
*/
PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, ph7_class *pClass, const SyString *pName, sxu32 nLine, sxi32 iProtection, sxi32 iFlags, sxu32 nType) {
PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, const SyString *pName, sxu32 nLine, sxi32 iProtection, sxi32 iFlags) {
ph7_class_attr *pAttr;
char *zName;
SXUNUSED(pClass);
pAttr = (ph7_class_attr *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_attr));
if(pAttr == 0) {
return 0;
@ -83,13 +64,12 @@ PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, ph7_class *pClass, con
SyMemBackendPoolFree(&pVm->sAllocator, pAttr);
return 0;
}
SyStringInitFromBuf(&pAttr->sName, zName, pName->nByte);
/* Initialize fields */
SySetInit(&pAttr->aByteCode, &pVm->sAllocator, sizeof(VmInstr));
SyStringInitFromBuf(&pAttr->sName, zName, pName->nByte);
pAttr->iProtection = iProtection;
pAttr->nIdx = SXU32_HIGH;
pAttr->iFlags = iFlags;
pAttr->nType = nType;
pAttr->nLine = nLine;
return pAttr;
}
@ -166,18 +146,14 @@ PH7_PRIVATE ph7_class_method *PH7_ClassExtractMethod(ph7_class *pClass, const ch
*/
PH7_PRIVATE ph7_class_attr *PH7_ClassExtractAttribute(ph7_class *pClass, const char *zName, sxu32 nByte) {
SyHashEntry *pEntry;
ph7_class_attr *pAttr;
/* Perform a hash lookup */
SyHashResetLoopCursor(&pClass->hAttr);
while((pEntry = SyHashGetNextEntry(&pClass->hAttr)) != 0) {
/* Point to the desired method */
pAttr = (ph7_class_attr *)pEntry->pUserData;
if(pAttr->pClass == pClass && SyStrncmp(pAttr->sName.zString, zName, nByte) == 0) {
return pAttr;
}
pEntry = SyHashGet(&pClass->hAttr, (const void *)zName, nByte);
if(pEntry == 0) {
/* No such entry */
return 0;
}
/* No such entry */
return 0;
/* Point to the desierd method */
return (ph7_class_attr *)pEntry->pUserData;
}
/*
* Install a class attribute in the corresponding container.
@ -186,7 +162,6 @@ PH7_PRIVATE ph7_class_attr *PH7_ClassExtractAttribute(ph7_class *pClass, const c
PH7_PRIVATE sxi32 PH7_ClassInstallAttr(ph7_class *pClass, ph7_class_attr *pAttr) {
SyString *pName = &pAttr->sName;
sxi32 rc;
pAttr->pClass = pClass;
rc = SyHashInsert(&pClass->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
return rc;
}
@ -197,7 +172,6 @@ PH7_PRIVATE sxi32 PH7_ClassInstallAttr(ph7_class *pClass, ph7_class_attr *pAttr)
PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass, ph7_class_method *pMeth) {
SyString *pName = &pMeth->sFunc.sName;
sxi32 rc;
pMeth->sFunc.pClass = pClass;
rc = SyHashInsert(&pClass->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
return rc;
}
@ -242,60 +216,76 @@ PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass, ph7_class_method *pM
* Any other return value indicates failure and the upper layer must generate an appropriate
* error message.
*/
PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_vm *pVm, ph7_class *pSub, ph7_class *pBase) {
PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_gen_state *pGen, ph7_class *pSub, ph7_class *pBase) {
ph7_class_method *pMeth;
ph7_class_attr *pAttr;
SyHashEntry *pEntry;
SyString *pName;
sxi32 rc;
/* Install in the derived hashtable */
rc = SyHashInsert(&pSub->hDerived, (const void *)SyStringData(&pBase->sName), SyStringLength(&pBase->sName), pBase);
rc = SyHashInsert(&pBase->hDerived, (const void *)SyStringData(&pSub->sName), SyStringLength(&pSub->sName), pSub);
if(rc != SXRET_OK) {
return rc;
}
/* Copy all attributes from the base class */
/* Copy public/protected attributes from the base class */
SyHashResetLoopCursor(&pBase->hAttr);
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0) {
/* Check if attributes are not being redeclared in the subclass and emit WARNING */
/* Make sure the private attributes are not redeclared in the subclass */
pAttr = (ph7_class_attr *)pEntry->pUserData;
pName = &pAttr->sName;
if((pEntry = SyHashGet(&pSub->hAttr, (const void *)pName->zString, pName->nByte)) != 0) {
ph7_class_attr *pSubAttr = (ph7_class_attr *)pEntry->pUserData;
PH7_VmThrowError(pVm, PH7_CTX_WARNING, "Attribute '%z::$%z' hides inherited member '%z::$%z'", &pSubAttr->pClass->sName, pName, &pBase->sName, pName);
if(pAttr->iProtection == PH7_CLASS_PROT_PRIVATE &&
((ph7_class_attr *)pEntry->pUserData)->iProtection != PH7_CLASS_PROT_PUBLIC) {
/* Cannot redeclare private attribute */
PH7_GenCompileError(&(*pGen), E_WARNING, ((ph7_class_attr *)pEntry->pUserData)->nLine,
"Private attribute '%z::%z' redeclared inside child class '%z'",
&pBase->sName, pName, &pSub->sName);
}
continue;
}
/* Install the attribute */
rc = SyHashInsert(&pSub->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
if(rc != SXRET_OK) {
return rc;
if(pAttr->iProtection != PH7_CLASS_PROT_PRIVATE) {
rc = SyHashInsert(&pSub->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
if(rc != SXRET_OK) {
return rc;
}
}
}
SyHashResetLoopCursor(&pBase->hMethod);
while((pEntry = SyHashGetNextEntry(&pBase->hMethod)) != 0) {
/* Make sure the final methods are not redeclared in the subclass */
/* Make sure the private/final methods are not redeclared in the subclass */
pMeth = (ph7_class_method *)pEntry->pUserData;
pName = &pMeth->sFunc.sName;
if((pEntry = SyHashGet(&pSub->hMethod, (const void *)pName->zString, pName->nByte)) != 0) {
if(pMeth->iFlags & PH7_CLASS_ATTR_FINAL) {
/* Cannot Overwrite final method */
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Cannot overwrite final method '%z:%z()' inside child class '%z'", &pBase->sName, pName, &pSub->sName);
rc = PH7_GenCompileError(&(*pGen), E_ERROR, ((ph7_class_method *)pEntry->pUserData)->nLine,
"Cannot Overwrite final method '%z:%z' inside child class '%z'",
&pBase->sName, pName, &pSub->sName);
if(rc == SXERR_ABORT) {
return SXERR_ABORT;
}
}
continue;
} else {
if(pMeth->iFlags & PH7_CLASS_ATTR_VIRTUAL) {
/* Virtual method must be defined in the child class */
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Virtual method '%z::%z()' must be defined inside child class '%z'", &pBase->sName, pName, &pSub->sName);
if(pMeth->iFlags & PH7_CLASS_ATTR_ABSTRACT) {
/* Abstract method must be defined in the child class */
PH7_GenCompileError(&(*pGen), E_WARNING, pMeth->nLine,
"Abstract method '%z:%z' must be defined inside child class '%z'",
&pBase->sName, pName, &pSub->sName);
continue;
}
}
/* Install the method */
rc = SyHashInsert(&pSub->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
if(rc != SXRET_OK) {
return rc;
if(pMeth->iProtection != PH7_CLASS_PROT_PRIVATE) {
rc = SyHashInsert(&pSub->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
if(rc != SXRET_OK) {
return rc;
}
}
}
/* Mark first inherited class as direct subclass */
if(!pSub->pBase) {
pSub->pBase = pBase;
}
/* Mark as subclass */
pSub->pBase = pBase;
/* All done */
return SXRET_OK;
}
@ -319,7 +309,7 @@ PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub, ph7_class *pBase) {
SyString *pName;
sxi32 rc;
/* Install in the derived hashtable */
SyHashInsert(&pSub->hDerived, (const void *)SyStringData(&pBase->sName), SyStringLength(&pBase->sName), pBase);
SyHashInsert(&pBase->hDerived, (const void *)SyStringData(&pSub->sName), SyStringLength(&pSub->sName), pSub);
SyHashResetLoopCursor(&pBase->hAttr);
/* Copy constants */
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0) {
@ -366,8 +356,7 @@ PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub, ph7_class *pBase) {
* Any other return value indicates failure and the upper layer must generate an appropriate
* error message.
*/
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_vm *pVm, ph7_class *pMain, ph7_class *pInterface) {
ph7_class_method *pMeth;
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain, ph7_class *pInterface) {
ph7_class_attr *pAttr;
SyHashEntry *pEntry;
SyString *pName;
@ -387,18 +376,12 @@ PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_vm *pVm, ph7_class *pMain, ph7_class *p
}
}
}
SyHashResetLoopCursor(&pInterface->hMethod);
while((pEntry = SyHashGetNextEntry(&pInterface->hMethod)) != 0) {
pMeth = (ph7_class_method *)pEntry->pUserData;
pName = &pMeth->sFunc.sName;
if((pEntry = SyHashGet(&pMain->hMethod, (const void *)pName->zString, pName->nByte)) != 0) {
continue;
} else {
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Method '%z:%z()' must be defined inside class '%z'", &pInterface->sName, pName, &pMain->sName);
}
}
/* Install in the interface container */
SySetPut(&pMain->aInterface, (const void *)&pInterface);
/* TICKET 1433-49/1: Symisc eXtension
* A class may not implemnt all declared interface methods,so there
* is no need for a method installer loop here.
*/
return SXRET_OK;
}
/*
@ -652,7 +635,7 @@ PH7_PRIVATE ph7_class_instance *PH7_CloneClassInstance(ph7_class_instance *pSrc)
PH7_VmCallClassMethod(pVm, pClone, pMethod, 0, 0, 0);
} else {
/* Nesting limit reached */
PH7_VmThrowError(pVm, PH7_CTX_ERR, "Object clone limit reached");
PH7_VmThrowError(pVm, 0, PH7_CTX_ERR, "Object clone limit reached,no more call to __clone()");
}
/* Reset the cursor */
pMethod->iCloneDepth = 0;
@ -673,7 +656,7 @@ static void PH7_ClassInstanceRelease(ph7_class_instance *pThis) {
ph7_vm *pVm;
if(pThis->iFlags & CLASS_INSTANCE_DESTROYED) {
/*
* Already destroyed, return immediately.
* Already destroyed,return immediately.
* This could happend if someone perform unset($this) in the destructor body.
*/
return;
@ -707,12 +690,10 @@ static void PH7_ClassInstanceRelease(ph7_class_instance *pThis) {
* If the reference count reaches zero,release the whole instance.
*/
PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis) {
if(pThis) {
pThis->iRef--;
if(pThis->iRef < 1) {
/* No more reference to this instance */
PH7_ClassInstanceRelease(&(*pThis));
}
pThis->iRef--;
if(pThis->iRef < 1) {
/* No more reference to this instance */
PH7_ClassInstanceRelease(&(*pThis));
}
}
/*
@ -798,7 +779,8 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft, ph7_class_inst
sxi32 rc;
if(iNest > 31) {
/* Nesting limit reached */
PH7_VmThrowError(pLeft->pVm, PH7_CTX_ERR, "Nesting limit reached, probably infinite recursion");
PH7_VmThrowError(pLeft->pVm, 0, PH7_CTX_ERR, "Nesting limit reached: Infinite recursion?");
return 1;
}
/* Comparison is performed only if the objects are instance of the same class */
if(pLeft->pClass != pRight->pClass) {
@ -811,7 +793,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft, ph7_class_inst
* are identical if and only if they refer to the same instance
* of the same class.
*/
return pLeft != pRight;
return !(pLeft == pRight);
}
/*
* Attribute comparison.
@ -881,45 +863,41 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut, ph7_class_instance *pThis,
if(!ShowType) {
SyBlobAppend(&(*pOut), "Object(", sizeof("Object(") - 1);
}
if(pThis) {
/* Append class name */
SyBlobFormat(&(*pOut), "%z) {", &pThis->pClass->sName);
/* Append class name */
SyBlobFormat(&(*pOut), "%z) {", &pThis->pClass->sName);
#ifdef __WINNT__
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
#else
SyBlobAppend(&(*pOut), "\n", sizeof(char));
SyBlobAppend(&(*pOut), "\n", sizeof(char));
#endif
/* Dump object attributes */
SyHashResetLoopCursor(&pThis->hAttr);
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0) {
VmClassAttr *pVmAttr = (VmClassAttr *)pEntry->pUserData;
if((pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) == 0) {
/* Dump non-static/constant attribute only */
for(i = 0 ; i < nTab ; i++) {
SyBlobAppend(&(*pOut), " ", sizeof(char));
}
pValue = ExtractClassAttrValue(pThis->pVm, pVmAttr);
if(pValue) {
SyBlobFormat(&(*pOut), "['%z'] =>", &pVmAttr->pAttr->sName);
/* Dump object attributes */
SyHashResetLoopCursor(&pThis->hAttr);
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0) {
VmClassAttr *pVmAttr = (VmClassAttr *)pEntry->pUserData;
if((pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) == 0) {
/* Dump non-static/constant attribute only */
for(i = 0 ; i < nTab ; i++) {
SyBlobAppend(&(*pOut), " ", sizeof(char));
}
pValue = ExtractClassAttrValue(pThis->pVm, pVmAttr);
if(pValue) {
SyBlobFormat(&(*pOut), "['%z'] =>", &pVmAttr->pAttr->sName);
#ifdef __WINNT__
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
#else
SyBlobAppend(&(*pOut), "\n", sizeof(char));
SyBlobAppend(&(*pOut), "\n", sizeof(char));
#endif
rc = PH7_MemObjDump(&(*pOut), pValue, ShowType, nTab + 1, nDepth);
if(rc == SXERR_LIMIT) {
break;
}
rc = PH7_MemObjDump(&(*pOut), pValue, ShowType, nTab + 1, nDepth, 0);
if(rc == SXERR_LIMIT) {
break;
}
}
}
for(i = 0 ; i < nTab ; i++) {
SyBlobAppend(&(*pOut), " ", sizeof(char));
}
SyBlobAppend(&(*pOut), "}", sizeof(char));
} else {
SyBlobAppend(&(*pOut), ")", sizeof(char));
}
for(i = 0 ; i < nTab ; i++) {
SyBlobAppend(&(*pOut), " ", sizeof(char));
}
SyBlobAppend(&(*pOut), "}", sizeof(char));
return rc;
}
/*
@ -958,7 +936,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut, ph7_class_instance *pThis,
* The above example will output:
* Hello
*
* Note that PH7 does not support all the magical method and introduces __toFloat(),__toInt()
* Note that PH7 does not support all the magical method and introudces __toFloat(),__toInt()
* which have the same behaviour as __toString() but for float and integer types
* respectively.
* Refer to the official documentation for more information.
@ -979,7 +957,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCallMagicMethod(
/* Make sure the magic method is available */
pMeth = PH7_ClassExtractMethod(&(*pClass), zMethod, nByte);
if(pMeth == 0) {
/* No such method, return immediately */
/* No such method,return immediately */
return SXERR_NOTFOUND;
}
nArg = 0;
@ -1033,7 +1011,7 @@ PH7_PRIVATE ph7_value *PH7_ClassInstanceExtractAttrValue(ph7_class_instance *pTh
* int(991)
* }
* You have noticed that PH7 allow class attributes [i.e: $a,$c,$d in the example above]
* have any complex expression (even function calls/anonymous functions) as their default
* have any complex expression (even function calls/Annonymous functions) as their default
* value unlike the standard PHP engine.
* This is a very powerful feature that you have to look at.
*/
@ -1107,7 +1085,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceWalk(
return SXRET_OK;
}
/*
* Extract a class attribute value.
* Extract a class atrribute value.
* Return a pointer to the attribute value on success. Otherwise NULL.
* Note:
* Access to static and constant attribute is not allowed. That is,the function
@ -1123,7 +1101,7 @@ PH7_PRIVATE ph7_value *PH7_ClassInstanceFetchAttr(ph7_class_instance *pThis, con
/* No such attribute */
return 0;
}
/* Point to the class attribute */
/* Point to the class atrribute */
pAttr = (VmClassAttr *)pEntry->pUserData;
/* Check if we are dealing with a static/constant attribute */
if(pAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,171 +0,0 @@
#ifndef _COMPILER_H_
#define _COMPILER_H_
#include "ph7int.h"
/* Forward declaration */
typedef struct LangConstruct LangConstruct;
typedef struct JumpFixup JumpFixup;
typedef struct Label Label;
/* Block [i.e: set of statements] control flags */
#define GEN_BLOCK_LOOP 0x001 /* Loop block [i.e: for,while,...] */
#define GEN_BLOCK_PROTECTED 0x002 /* Protected block */
#define GEN_BLOCK_COND 0x004 /* Conditional block [i.e: if(condition){} ]*/
#define GEN_BLOCK_FUNC 0x008 /* Function body */
#define GEN_BLOCK_GLOBAL 0x010 /* Global block (always set)*/
#define GEN_BLOCK_NESTED_FUNC 0x020 /* Nested function body */
#define GEN_BLOCK_EXPR 0x040 /* Expression */
#define GEN_BLOCK_STD 0x080 /* Standard block */
#define GEN_BLOCK_EXCEPTION 0x100 /* Exception block [i.e: try{ } }*/
#define GEN_BLOCK_SWITCH 0x200 /* Switch statement */
#define GEN_BLOCK_CLASS 0x400 /* Class definition */
#define GEN_BLOCK_NAMESPACE 0x800 /* Namespace body */
/*
* Each label seen in the input is recorded in an instance
* of the following structure.
* A label is a target point [i.e: a jump destination] that is specified
* by an identifier followed by a colon.
*/
struct Label {
ph7_vm_func *pFunc; /* Compiled function where the label was declared.NULL otherwise */
sxu32 nJumpDest; /* Jump destination */
SyString sName; /* Label name */
sxu32 nLine; /* Line number this label occurs */
sxu8 bRef; /* True if the label was referenced */
};
/*
* Compilation of some Aer constructs such as if, for, while, the logical or
* (||) and logical and (&&) operators in expressions requires the
* generation of forward jumps.
* Since the destination PC target of these jumps isn't known when the jumps
* are emitted, we record each forward jump in an instance of the following
* structure. Those jumps are fixed later when the jump destination is resolved.
*/
struct JumpFixup {
sxi32 nJumpType; /* Jump type. Either TRUE jump, FALSE jump or Unconditional jump */
sxu32 nInstrIdx; /* Instruction index to fix later when the jump destination is resolved. */
SyString sLabel; /* Label name */
ph7_vm_func *pFunc; /* Compiled function inside which the goto was emitted. NULL otherwise */
sxu32 nLine; /* Track line number */
};
/*
* Each language construct is represented by an instance
* of the following structure.
*/
struct LangConstruct {
sxu32 nID; /* Language construct ID [i.e: PH7_KEYWORD_WHILE,PH7_KEYWORD_FOR,PH7_KEYWORD_IF...] */
ProcLangConstruct xConstruct; /* C function implementing the language construct */
};
/* Compilation flags */
#define PH7_COMPILE_STATEMENT 0x001 /* Compile a single statement */
/* Token stream synchronization macros */
#define SWAP_TOKEN_STREAM(GEN,START,END)\
pTmp = GEN->pEnd;\
pGen->pIn = START;\
pGen->pEnd = END
#define UPDATE_TOKEN_STREAM(GEN)\
if( GEN->pIn < pTmp ){\
GEN->pIn++;\
}\
GEN->pEnd = pTmp
#define SWAP_DELIMITER(GEN,START,END)\
pTmpIn = GEN->pIn;\
pTmpEnd = GEN->pEnd;\
GEN->pIn = START;\
GEN->pEnd = END
#define RE_SWAP_DELIMITER(GEN)\
GEN->pIn = pTmpIn;\
GEN->pEnd = pTmpEnd
/* Flags related to expression compilation */
#define EXPR_FLAG_LOAD_IDX_STORE 0x001 /* Set the iP2 flag when dealing with the LOAD_IDX instruction */
#define EXPR_FLAG_RDONLY_LOAD 0x002 /* Read-only load, refer to the 'PH7_OP_LOAD' VM instruction for more information */
#define EXPR_FLAG_COMMA_STATEMENT 0x004 /* Treat comma expression as a single statement (used by class attributes) */
/* Forward declaration */
static sxi32 PH7_CompileExpr(ph7_gen_state *pGen, sxi32 iFlags, sxi32(*xTreeValidator)(ph7_gen_state *, ph7_expr_node *));
static GenBlock *PH7_GenStateFetchBlock(GenBlock *pCurrent, sxi32 iBlockType, sxi32 iCount);
static void PH7_GenStateInitBlock(ph7_gen_state *pGen, GenBlock *pBlock, sxi32 iType, sxu32 nFirstInstr, void *pUserData);
static sxi32 PH7_GenStateEnterBlock(ph7_gen_state *pGen, sxi32 iType, sxu32 nFirstInstr, void *pUserData, GenBlock **ppBlock);
static void PH7_GenStateReleaseBlock(GenBlock *pBlock);
static void PH7_GenStateFreeBlock(GenBlock *pBlock);
static sxi32 PH7_GenStateLeaveBlock(ph7_gen_state *pGen, GenBlock **ppBlock);
static sxi32 PH7_GenStateNewJumpFixup(GenBlock *pBlock, sxi32 nJumpType, sxu32 nInstrIdx);
static sxu32 PH7_GenStateFixJumps(GenBlock *pBlock, sxi32 nJumpType, sxu32 nJumpDest);
static sxi32 PH7_GenStateFindLiteral(ph7_gen_state *pGen, const SyString *pValue, sxu32 *pIdx);
static sxi32 PH7_GenStateInstallLiteral(ph7_gen_state *pGen, ph7_value *pObj, sxu32 nIdx);
static ph7_value *PH7_GenStateInstallNumLiteral(ph7_gen_state *pGen, sxu32 *pIdx);
static sxi32 PH7_CompileNumLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag);
PH7_PRIVATE sxi32 PH7_CompileSimpleString(ph7_gen_state *pGen, sxi32 iCompileFlag);
static sxi32 PH7_GenStateProcessStringExpression(ph7_gen_state *pGen, sxu32 nLine, const char *zIn, const char *zEnd);
static ph7_value *PH7_GenStateNewStrObj(ph7_gen_state *pGen, sxi32 *pCount);
static sxi32 PH7_GenStateCompileString(ph7_gen_state *pGen);
PH7_PRIVATE sxi32 PH7_CompileString(ph7_gen_state *pGen, sxi32 iCompileFlag);
static sxi32 PH7_GenStateCompileArrayEntry(ph7_gen_state *pGen, SyToken *pIn, SyToken *pEnd, sxi32 iFlags, sxi32(*xValidator)(ph7_gen_state *, ph7_expr_node *));
PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag);
static sxi32 PH7_GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32 iFlags, int bHandleClosure, ph7_vm_func **ppFunc);
static sxi32 GenStateDefineNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
PH7_PRIVATE sxi32 PH7_CompileDefine(ph7_gen_state *pGen);
PH7_PRIVATE sxi32 PH7_CompileVariable(ph7_gen_state *pGen, sxi32 iCompileFlag);
static sxi32 PH7_GenStateLoadLiteral(ph7_gen_state *pGen);
static sxi32 PH7_GenStateResolveNamespaceLiteral(ph7_gen_state *pGen);
PH7_PRIVATE sxi32 PH7_CompileLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag);
static int PH7_GenStateIsReservedConstant(SyString *pName);
static sxi32 PH7_CompileConstant(ph7_gen_state *pGen);
static sxi32 PH7_CompileContinue(ph7_gen_state *pGen);
static sxi32 PH7_CompileBreak(ph7_gen_state *pGen);
static sxi32 PH7_GenStateNextChunk(ph7_gen_state *pGen);
static sxi32 PH7_CompileBlock(ph7_gen_state *pGen);
static sxi32 PH7_CompileWhile(ph7_gen_state *pGen);
static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen);
static sxi32 PH7_CompileFor(ph7_gen_state *pGen);
static sxi32 GenStateForEachNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
static sxi32 PH7_CompileForeach(ph7_gen_state *pGen);
static sxi32 PH7_CompileIf(ph7_gen_state *pGen);
static sxi32 PH7_CompileReturn(ph7_gen_state *pGen);
static sxi32 PH7_CompileHalt(ph7_gen_state *pGen);
static sxi32 PH7_CompileVar(ph7_gen_state *pGen);
static sxi32 PH7_CompileNamespace(ph7_gen_state *pGen);
static sxi32 PH7_CompileUsing(ph7_gen_state *pGen);
static sxi32 PH7_CompileImport(ph7_gen_state *pGen);
static sxi32 PH7_CompileInclude(ph7_gen_state *pGen);
static sxi32 PH7_GenStateProcessArgValue(ph7_gen_state *pGen, ph7_vm_func_arg *pArg, SyToken *pIn, SyToken *pEnd);
static sxi32 PH7_GenStateCollectFuncArgs(ph7_vm_func *pFunc, ph7_gen_state *pGen, SyToken *pEnd);
static sxi32 PH7_GenStateCompileFuncBody(ph7_gen_state *pGen, ph7_vm_func *pFunc);
static sxi32 PH7_GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32 iFlags, int bHandleClosure, ph7_vm_func **ppFunc);
static sxi32 PH7_GetProtectionLevel(sxi32 nKeyword);
static sxi32 PH7_GenStateCompileClassConstant(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, ph7_class *pClass);
static sxi32 PH7_GenStateCompileClassAttr(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, sxu32 nType, ph7_class *pClass);
static sxi32 PH7_GenStateCompileClassMethod(ph7_gen_state *pGen, sxu32 nType, sxi32 iProtection, sxi32 iFlags, int doBody, ph7_class *pClass);
static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen);
static sxi32 PH7_GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags);
static sxi32 PH7_CompileClass(ph7_gen_state *pGen);
static sxi32 PH7_GenStateThrowNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot);
static sxi32 PH7_CompileThrow(ph7_gen_state *pGen);
static sxi32 PH7_CompileCatch(ph7_gen_state *pGen, ph7_exception *pException);
static sxi32 PH7_CompileTry(ph7_gen_state *pGen);
static sxi32 PH7_GenStateCompileSwitchBlock(ph7_gen_state *pGen, sxu32 *pBlockStart);
static sxi32 PH7_GenStateCompileCaseExpr(ph7_gen_state *pGen, ph7_case_expr *pExpr);
static sxi32 PH7_CompileSwitch(ph7_gen_state *pGen);
static sxi32 PH7_GenStateEmitExprCode(ph7_gen_state *pGen, ph7_expr_node *pNode, sxi32 iFlags);
static sxi32 PH7_CompileExpr(ph7_gen_state *pGen, sxi32 iFlags, sxi32(*xTreeValidator)(ph7_gen_state *, ph7_expr_node *));
PH7_PRIVATE ProcNodeConstruct PH7_GetNodeHandler(sxu32 nNodeType);
static ProcLangConstruct PH7_GenStateGetStatementHandler(sxu32 nKeywordID, SyToken *pLookahead);
static int PH7_IsLangConstruct(sxu32 nKeywordID);
static sxi32 PH7_GenStateCompileChunk(ph7_gen_state *pGen, sxi32 iFlags);
static sxi32 PH7_GenStateCompileGlobalScope(ph7_gen_state *pGen);
static sxi32 PH7_CompileScript(ph7_gen_state *pGen, SySet *pTokenSet, sxi32 iFlags);
PH7_PRIVATE sxi32 PH7_InitCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData);
PH7_PRIVATE sxi32 PH7_ResetCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData);
PH7_PRIVATE sxi32 PH7_GenCompileError(ph7_gen_state *pGen, sxi32 nErrType, sxu32 nLine, const char *zFormat, ...);
#endif /* _COMPILER_H_ */

View File

@ -3,7 +3,7 @@
#define _PH7_H_
/*
* Symisc PH7: An embeddable bytecode compiler and a virtual machine for the PHP(5) programming language.
* Copyright (C) 2011-2012, Symisc Systems https://ph7.symisc.net/
* Copyright (C) 2011-2012, Symisc Systems http://ph7.symisc.net/
* Version 2.1.4
* For information on licensing,redistribution of this file,and for a DISCLAIMER OF ALL WARRANTIES
* please contact Symisc Systems via:
@ -11,7 +11,7 @@
* licensing@symisc.net
* contact@symisc.net
* or visit:
* https://ph7.symisc.net/
* http://ph7.symisc.net/
*/
/*
* Copyright (C) 2011, 2012 Symisc Systems. All rights reserved.
@ -50,11 +50,14 @@
/* $SymiscID: ph7.h v2.1 UNIX|WIN32/64 2012-09-15 09:43 stable <chm@symisc.net> $ */
#include <stdarg.h> /* needed for the definition of va_list */
#include <stdio.h> /* needed for the definition of snprintf */
#include <limits.h> /* needed for MAX_PATH */
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif
/*
* Compile time engine version, signature, identification in the symisc source tree
* and copyright notice.
* Each macro have an equivalent C interface associated with it that provide the same
* information but are associated with the library instead of the header file.
* Refer to [ph7_lib_version()], [ph7_lib_signature()], [ph7_lib_ident()] and
* [ph7_lib_copyright()] for more information.
*/
/*
* The PH7_VERSION C preprocessor macroevaluates to a string literal
* that is the ph7 version in the format "X.Y.Z" where X is the major
@ -62,6 +65,12 @@
* number.
*/
#define PH7_VERSION "2.1.4"
/*
* The PH7_VERSION_NUMBER C preprocessor macro resolves to an integer
* with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
* numbers used in [PH7_VERSION].
*/
#define PH7_VERSION_NUMBER 2001004
/*
* The PH7_SIG C preprocessor macro evaluates to a string
* literal which is the public signature of the ph7 engine.
@ -70,16 +79,23 @@
* Server: YourWebServer/x.x PH7/x.x.x \r\n
*/
#define PH7_SIG "PH7/2.1.4"
/*
* PH7 identification in the Symisc source tree:
* Each particular check-in of a particular software released
* by symisc systems have an unique identifier associated with it.
* This macro hold the one associated with ph7.
*/
#define PH7_IDENT "ph7:c193f4d8a6b90ee60f9afad11840f1010054fdf9"
/*
* Copyright notice.
* If you have any questions about the licensing situation,please
* visit https://ph7.symisc.net/licensing.html
* visit http://ph7.symisc.net/licensing.html
* or contact Symisc Systems via:
* legal@symisc.net
* licensing@symisc.net
* contact@symisc.net
*/
#define PH7_COPYRIGHT "Copyright (C) Symisc Systems 2011-2012, https://ph7.symisc.net/"
#define PH7_COPYRIGHT "Copyright (C) Symisc Systems 2011-2012, http://ph7.symisc.net/"
/* Forward declaration to public objects */
typedef struct ph7_io_stream ph7_io_stream;
typedef struct ph7_context ph7_context;
@ -87,34 +103,96 @@ typedef struct ph7_value ph7_value;
typedef struct ph7_vfs ph7_vfs;
typedef struct ph7_vm ph7_vm;
typedef struct ph7 ph7;
/*
* ------------------------------
* Compile time directives
* ------------------------------
* For most purposes, PH7 can be built just fine using the default compilation options.
* However, if required, the compile-time options documented below can be used to omit
* PH7 features (resulting in a smaller compiled library size) or to change the default
* values of some parameters.
* Every effort has been made to ensure that the various combinations of compilation
* options work harmoniously and produce a working library.
*
* PH7_ENABLE_THREADS
* This option controls whether or not code is included in PH7 to enable it to operate
* safely in a multithreaded environment. The default is not. That is,all mutexing code
* is omitted and it is unsafe to use PH7 in a multithreaded program. When compiled
* with the PH7_ENABLE_THREADS directive enabled, PH7 can be used in a multithreaded
* program and it's safe to share the same virtual machine and engine instance between
* two or more threads.
* The value of PH7_ENABLE_THREADS can be determined at run-time using the
* ph7_lib_is_threadsafe() interface.When PH7 has been compiled with PH7_ENABLE_THREAD
* then the threading mode can be altered at run-time using the ph7_lib_config()
* interface together with one of these verbs:
* PH7_LIB_CONFIG_THREAD_LEVEL_SINGLE
* PH7_LIB_CONFIG_THREAD_LEVEL_MULTI
* Also note,platforms others than Windows and UNIX systems must install their own
* mutex subsystem via ph7_lib_config() with a configuration verb set to
* PH7_LIB_CONFIG_USER_MUTEX. Otherwise the library is not threadsafe.
* Note that you must link PH7 with the POSIX threads library under UNIX-like systems
* (i.e: -lpthread).Otherwise you will get a link time error.
* Options To Omit/Enable Features:
* The following options can be used to reduce the size of the compiled library
* by omitting optional features. This is probably only useful in embedded systems
* where space is especially tight, as even with all features included the PH7 library
* is relatively small. Don't forget to tell your compiler to optimize for binary
* size! (the -Os option if using GCC).
* Telling your compiler to optimize for size usually has a much larger impact
* on library footprint than employing any of these compile-time options.
* PH7_DISABLE_BUILTIN_FUNC
* PH7 come with more than 460 built-in functions suitable for most purposes ranging
* from string/XML/INI processing to ZIP extracting, Base64 encoding/decoding and so on.
* If this directive is enabled, all the built-in functions are omitted from the build.
* Note that language construct functions such as is_int(), is_string(), func_get_arg(),
* define(), etc. are not omitted from the build and are not affected by this directive.
* PH7_ENABLE_MATH_FUNC
* If this directive is enabled, built-in math functions such as sqrt(),abs(),
* log(), ceil(), etc. are included in the build. Note that you may need to link
* PH7 with the math library in same linux/BSD flavor (i.e: -lm).Otherwise you
* will get a link time error.
* PH7_DISABLE_DISK_IO
* If this directive is enabled, built-in Virtual File System functions such as
* chdir(), mkdir(), chroot(), unlink(), delete(), etc. are omitted from the build.
* PH7_DISABLE_HASH_IO
* If this directive is enabled, built-in hash functions such as md5(), sha1(),
* md5_file(), crc32(), etc. are omitted from the build.
* PH7_OMIT_FLOATING_POINT
* This option is used to omit floating-point number support from the PH7 library
* if compiling for a processor that lacks floating point support. When specified
* the library will substitute 64-bit integer arithmetic for floating-point which
* mean that 25.e-3 and 25 are equals and are of type integer.
*/
/* Symisc public definitions */
#if !defined(SYMISC_STANDARD_DEFS)
#define SYMISC_STANDARD_DEFS
#if defined (_WIN32) || defined (WIN32) || defined(__MINGW32__) || defined (_MSC_VER) || defined (_WIN32_WCE)
/* Windows Systems */
#if !defined(__WINNT__)
#define __WINNT__
#endif
/* Windows Systems */
#if !defined(__WINNT__)
#define __WINNT__
#endif
#else
/*
* By default we will assume that we are compiling on a UNIX systems.
* Otherwise the OS_OTHER directive must be defined.
*/
#if !defined(OS_OTHER)
#if !defined(__UNIXES__)
#define __UNIXES__
#endif /* __UNIXES__ */
#else
#endif /* OS_OTHER */
/*
* By default we will assume that we are compiling on a UNIX systems.
* Otherwise the OS_OTHER directive must be defined.
*/
#if !defined(OS_OTHER)
#if !defined(__UNIXES__)
#define __UNIXES__
#endif /* __UNIXES__ */
#else
#endif /* OS_OTHER */
#endif /* __WINNT__/__UNIXES__ */
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef signed __int64 sxi64; /* 64 bits(8 bytes) signed int64 */
typedef unsigned __int64 sxu64; /* 64 bits(8 bytes) unsigned int64 */
typedef signed __int64 sxi64; /* 64 bits(8 bytes) signed int64 */
typedef unsigned __int64 sxu64; /* 64 bits(8 bytes) unsigned int64 */
#else
typedef signed long long int sxi64; /* 64 bits(8 bytes) signed int64 */
typedef unsigned long long int sxu64; /* 64 bits(8 bytes) unsigned int64 */
typedef signed long long int sxi64; /* 64 bits(8 bytes) signed int64 */
typedef unsigned long long int sxu64; /* 64 bits(8 bytes) unsigned int64 */
#endif /* _MSC_VER */
/* Solaris additions */
#ifndef MAP_FILE
#define MAP_FILE 0
#define MAP_FILE 0
#endif
/* Signature of the consumer routine */
typedef int (*ProcConsumer)(const void *, unsigned int, void *);
@ -187,7 +265,7 @@ struct SyMemMethods {
void *(*xAlloc)(unsigned int); /* [Required:] Allocate a memory chunk */
void *(*xRealloc)(void *, unsigned int); /* [Required:] Re-allocate a memory chunk */
void (*xFree)(void *); /* [Required:] Release a memory chunk */
unsigned int (*xChunkSize)(void *); /* [Required:] Return chunk size */
unsigned int (*xChunkSize)(void *); /* [Optional:] Return chunk size */
int (*xInit)(void *); /* [Optional:] Initialization callback */
void (*xRelease)(void *); /* [Optional:] Release callback */
void *pUserData; /* [Optional:] First argument to xInit() and xRelease() */
@ -205,11 +283,11 @@ struct SyMutexMethods {
void (*xLeave)(SyMutex *); /* [Required:] Leave a locked mutex */
};
#if defined (_MSC_VER) || defined (__MINGW32__) || defined (__GNUC__) && defined (__declspec)
#define SX_APIIMPORT __declspec(dllimport)
#define SX_APIEXPORT __declspec(dllexport)
#define SX_APIIMPORT __declspec(dllimport)
#define SX_APIEXPORT __declspec(dllexport)
#else
#define SX_APIIMPORT
#define SX_APIEXPORT
#define SX_APIIMPORT
#define SX_APIEXPORT
#endif
/* Standard return values from Symisc public interfaces */
#define SXRET_OK 0 /* Not an error */
@ -247,6 +325,7 @@ struct SyMutexMethods {
#define SXERR_BIG (-32) /* Too big for processing */
#define SXERR_RETRY (-33) /* Retry your call */
#define SXERR_IGNORE (-63) /* Ignore */
#endif /* SYMISC_PUBLIC_DEFS */
/* Standard PH7 return values */
#define PH7_OK SXRET_OK /* Successful result */
/* beginning-of-error-codes */
@ -262,11 +341,13 @@ struct SyMutexMethods {
* If compiling for a processor that lacks floating point
* support, substitute integer for floating-point.
*/
#ifdef PH7_OMIT_FLOATING_POINT
typedef sxi64 ph7_real;
#else
typedef double ph7_real;
#endif
typedef sxi64 ph7_int64;
#define PH7_APIEXPORT SX_APIEXPORT
#define PH7_APIIMPORT SX_APIIMPORT
/*
* Engine Configuration Commands.
*
@ -279,12 +360,11 @@ typedef sxi64 ph7_int64;
* return value indicates failure.
* For a full discussion on the configuration verbs and their expected
* parameters, please refer to this page:
* https://ph7.symisc.net/c_api_func.html#ph7_config
* http://ph7.symisc.net/c_api_func.html#ph7_config
*/
#define PH7_CONFIG_ERR_OUTPUT 1 /* TWO ARGUMENTS: int (*xConsumer)(const void *pOut,unsigned int nLen,void *pUserData),void *pUserData */
#define PH7_CONFIG_ERR_ABORT 2 /* RESERVED FOR FUTURE USE */
#define PH7_CONFIG_ERR_LOG 3 /* TWO ARGUMENTS: const char **pzBuf,int *pLen */
#define PH7_CONFIG_MEM_LIMIT 4 /* ONE ARGUMENT: char *nMemLimit */
/*
* Virtual Machine Configuration Commands.
*
@ -300,24 +380,28 @@ typedef sxi64 ph7_int64;
* a HTTP request and PH7_VM_CONFIG_ARGV_ENTRY which populate the $argv array.
* For a full discussion on the configuration verbs and their expected parameters, please
* refer to this page:
* https://ph7.symisc.net/c_api_func.html#ph7_vm_config
* http://ph7.symisc.net/c_api_func.html#ph7_vm_config
*/
#define PH7_VM_CONFIG_OUTPUT 1 /* TWO ARGUMENTS: int (*xConsumer)(const void *pOut,unsigned int nLen,void *pUserData),void *pUserData */
#define PH7_VM_CONFIG_IMPORT_PATH 3 /* ONE ARGUMENT: const char *zIncludePath */
#define PH7_VM_CONFIG_ERR_REPORT 4 /* NO ARGUMENTS: Report all run-time errors in the VM output */
#define PH7_VM_CONFIG_CREATE_SUPER 5 /* TWO ARGUMENTS: const char *zName,ph7_value *pValue */
#define PH7_VM_CONFIG_CREATE_VAR 6 /* TWO ARGUMENTS: const char *zName,ph7_value *pValue */
#define PH7_VM_CONFIG_HTTP_REQUEST 7 /* TWO ARGUMENTS: const char *zRawRequest,int nRequestLength */
#define PH7_VM_CONFIG_SERVER_ATTR 8 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_ENV_ATTR 9 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_SESSION_ATTR 10 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_POST_ATTR 11 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_GET_ATTR 12 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_COOKIE_ATTR 13 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_HEADER_ATTR 14 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_IO_STREAM 15 /* ONE ARGUMENT: const ph7_io_stream *pStream */
#define PH7_VM_CONFIG_ARGV_ENTRY 16 /* ONE ARGUMENT: const char *zValue */
#define PH7_VM_CONFIG_EXTRACT_OUTPUT 17 /* TWO ARGUMENTS: const void **ppOut,unsigned int *pOutputLen */
#define PH7_VM_CONFIG_RECURSION_DEPTH 5 /* ONE ARGUMENT: int nMaxDepth */
#define PH7_VM_OUTPUT_LENGTH 6 /* ONE ARGUMENT: unsigned int *pLength */
#define PH7_VM_CONFIG_CREATE_SUPER 7 /* TWO ARGUMENTS: const char *zName,ph7_value *pValue */
#define PH7_VM_CONFIG_CREATE_VAR 8 /* TWO ARGUMENTS: const char *zName,ph7_value *pValue */
#define PH7_VM_CONFIG_HTTP_REQUEST 9 /* TWO ARGUMENTS: const char *zRawRequest,int nRequestLength */
#define PH7_VM_CONFIG_SERVER_ATTR 10 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_ENV_ATTR 11 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_SESSION_ATTR 12 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_POST_ATTR 13 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_GET_ATTR 14 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_COOKIE_ATTR 15 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_HEADER_ATTR 16 /* THREE ARGUMENTS: const char *zKey,const char *zValue,int nLen */
#define PH7_VM_CONFIG_EXEC_VALUE 17 /* ONE ARGUMENT: ph7_value **ppValue */
#define PH7_VM_CONFIG_IO_STREAM 18 /* ONE ARGUMENT: const ph7_io_stream *pStream */
#define PH7_VM_CONFIG_ARGV_ENTRY 19 /* ONE ARGUMENT: const char *zValue */
#define PH7_VM_CONFIG_EXTRACT_OUTPUT 20 /* TWO ARGUMENTS: const void **ppOut,unsigned int *pOutputLen */
#define PH7_VM_CONFIG_ERR_LOG_HANDLER 21 /* ONE ARGUMENT: void (*xErrLog)(const char *,int,const char *,const char *) */
/*
* Global Library Configuration Commands.
*
@ -342,7 +426,7 @@ typedef sxi64 ph7_int64;
* and their expected parameters.
* For a full discussion on the configuration verbs and their expected parameters,please
* refer to this page:
* https://ph7.symisc.net/c_api_func.html#Global_Library_Management_Interfaces
* http://ph7.symisc.net/c_api_func.html#Global_Library_Management_Interfaces
*/
#define PH7_LIB_CONFIG_USER_MALLOC 1 /* ONE ARGUMENT: const SyMemMethods *pMemMethods */
#define PH7_LIB_CONFIG_MEM_ERR_CALLBACK 2 /* TWO ARGUMENTS: int (*xMemError)(void *),void *pUserData */
@ -352,26 +436,29 @@ typedef sxi64 ph7_int64;
#define PH7_LIB_CONFIG_VFS 6 /* ONE ARGUMENT: const ph7_vfs *pVfs */
/*
* Compile-time flags.
*
* VmEvalChunk and PH7_CompileAerScript takes iFlags argument
* which controls the behavior of the PH7 Engine while
* The new compile interfaces [ph7_compile_v2()] and [ph7_compile_file()] takes
* as their last argument zero or more combination of compile time flags.
* These flags are used to control the behavior of the PH7 compiler while
* processing the input.
* Refer to the official documentation for additional information.
*/
#define PH7_AERSCRIPT_CODE 0x01 /* AerScript Code */
#define PH7_AERSCRIPT_CHNK 0x02 /* AerScript Chunk of Code */
#define PH7_AERSCRIPT_EXPR 0x04 /* AerScript Expression */
#define PH7_AERSCRIPT_FILE 0x08 /* AerScript File Inclusion */
#define PH7_PHP_ONLY 0x01 /* If this flag is set then the code to compile is assumed
* to be plain PHP only. That is, there is no need to delimit
* the PHP code using the standard tags such as <?php ?> or <? ?>.
* Everything will pass through the PH7 compiler.
*/
#define PH7_PHP_EXPR 0x02 /* This flag is reserved for future use. */
/*
* Call Context Error Message Severity Level.
*
* The following constans are the allowed severity level that can
* passed as the second argument to the PH7_VmThrowError().
* passed as the second argument to the [ph7_context_throw_error()] or
* [ph7_context_throw_error_format()] interfaces.
* Refer to the official documentation for additional information.
*/
#define PH7_CTX_ERR 1 /* Call context Error such as unexpected number of arguments,invalid types and so on. */
#define PH7_CTX_WARNING 2 /* Call context Warning */
#define PH7_CTX_NOTICE 3 /* Call context Notice */
#define PH7_CTX_DEPRECATED 4 /* Call context Deprecated notice */
#define PH7_CTX_ERR 1 /* Call context error such as unexpected number of arguments,invalid types and so on. */
#define PH7_CTX_WARNING 2 /* Call context Warning */
#define PH7_CTX_NOTICE 3 /* Call context Notice */
/* Current VFS structure version*/
#define PH7_VFS_VERSION 2
/*
@ -422,13 +509,10 @@ struct ph7_vfs {
ph7_int64(*xFileAtime)(const char *); /* Gets last access time of file */
ph7_int64(*xFileMtime)(const char *); /* Gets file modification time */
ph7_int64(*xFileCtime)(const char *); /* Gets inode change time of file */
ph7_int64(*xFileGroup)(const char *); /* Gets file group */
ph7_int64(*xFileInode)(const char *); /* Gets file inode */
ph7_int64(*xFileOwner)(const char *); /* Gets file owner */
int (*xStat)(const char *, ph7_value *, ph7_value *); /* Gives information about a file */
int (*xlStat)(const char *, ph7_value *, ph7_value *); /* Gives information about a file */
int (*xIsFile)(const char *); /* Tells whether the filename is a regular file */
int (*xIsLink)(const char *); /* Tells whether the filename is a symbolic link */
int (*xIsfile)(const char *); /* Tells whether the filename is a regular file */
int (*xIslink)(const char *); /* Tells whether the filename is a symbolic link */
int (*xReadable)(const char *); /* Tells whether a file exists and is readable */
int (*xWritable)(const char *); /* Tells whether the filename is writable */
int (*xExecutable)(const char *); /* Tells whether the filename is executable */
@ -445,13 +529,14 @@ struct ph7_vfs {
int (*xUid)(void); /* user ID of the process */
int (*xGid)(void); /* group ID of the process */
void (*xUsername)(ph7_context *); /* Running username */
int (*xExec)(const char *, ph7_context *); /* Execute an external program */
};
/* Current PH7 IO stream structure version. */
#define PH7_IO_STREAM_VERSION 1
/*
* Possible open mode flags that can be passed to the xOpen() routine
* of the underlying IO stream device .
* Refer to the PH7 IO Stream C/C++ specification manual (https://ph7.symisc.net/io_stream_spec.html)
* Refer to the PH7 IO Stream C/C++ specification manual (http://ph7.symisc.net/io_stream_spec.html)
* for additional information.
*/
#define PH7_IO_OPEN_RDONLY 0x001 /* Read-only open */
@ -491,7 +576,7 @@ struct ph7_vfs {
* Currently the PH7 development team is working on the implementation of the http:// and ftp://
* IO stream protocols. These devices will be available in the next major release of the PH7 engine.
* Developers wishing to implement their own IO stream devices must understand and follow
* The PH7 IO Stream C/C++ specification manual (https://ph7.symisc.net/io_stream_spec.html).
* The PH7 IO Stream C/C++ specification manual (http://ph7.symisc.net/io_stream_spec.html).
*/
struct ph7_io_stream {
const char *zName; /* Underlying stream name [i.e: file/http/zip/php,..] */
@ -519,16 +604,16 @@ struct ph7_io_stream {
PH7_APIEXPORT int ph7_init(ph7 **ppEngine);
PH7_APIEXPORT int ph7_config(ph7 *pEngine, int nConfigOp, ...);
PH7_APIEXPORT int ph7_release(ph7 *pEngine);
PH7_APIEXPORT int ph7_vm_init(ph7 *pEngine, ph7_vm **ppOutVm, int bDebug);
/* Compile Interfaces */
PH7_APIEXPORT int ph7_compile_code(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm);
PH7_APIEXPORT int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm);
PH7_APIEXPORT int ph7_compile(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm);
PH7_APIEXPORT int ph7_compile_v2(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm, int iFlags);
PH7_APIEXPORT int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm, int iFlags);
/* Virtual Machine Handling Interfaces */
PH7_APIEXPORT int ph7_vm_config(ph7_vm *pVm, int iConfigOp, ...);
PH7_APIEXPORT int ph7_vm_exec(ph7_vm *pVm, int *pExitStatus);
PH7_APIEXPORT int ph7_vm_reset(ph7_vm *pVm);
PH7_APIEXPORT int ph7_vm_release(ph7_vm *pVm);
PH7_APIEXPORT int ph7_vm_dump(ph7_vm *pVm, int (*xConsumer)(const void *, unsigned int, void *), void *pUserData);
PH7_APIEXPORT int ph7_vm_dump_v2(ph7_vm *pVm, int (*xConsumer)(const void *, unsigned int, void *), void *pUserData);
/* In-process Extending Interfaces */
PH7_APIEXPORT int ph7_create_function(ph7_vm *pVm, const char *zName, int (*xFunc)(ph7_context *, int, ph7_value **), void *pUserData);
PH7_APIEXPORT int ph7_delete_function(ph7_vm *pVm, const char *zName);
@ -555,6 +640,8 @@ PH7_APIEXPORT int ph7_result_resource(ph7_context *pCtx, void *pUserData);
/* Call Context Handling Interfaces */
PH7_APIEXPORT int ph7_context_output(ph7_context *pCtx, const char *zString, int nLen);
PH7_APIEXPORT int ph7_context_output_format(ph7_context *pCtx, const char *zFormat, ...);
PH7_APIEXPORT int ph7_context_throw_error(ph7_context *pCtx, int iErr, const char *zErr);
PH7_APIEXPORT int ph7_context_throw_error_format(ph7_context *pCtx, int iErr, const char *zFormat, ...);
PH7_APIEXPORT unsigned int ph7_context_random_num(ph7_context *pCtx);
PH7_APIEXPORT int ph7_context_random_string(ph7_context *pCtx, char *zBuf, int nBuflen);
PH7_APIEXPORT void *ph7_context_user_data(ph7_context *pCtx);
@ -578,13 +665,13 @@ PH7_APIEXPORT void ph7_context_release_value(ph7_context *pCtx, ph7_value *pValu
PH7_APIEXPORT int ph7_value_int(ph7_value *pVal, int iValue);
PH7_APIEXPORT int ph7_value_int64(ph7_value *pVal, ph7_int64 iValue);
PH7_APIEXPORT int ph7_value_bool(ph7_value *pVal, int iBool);
PH7_APIEXPORT int ph7_value_null(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_double(ph7_value *pVal, double Value);
PH7_APIEXPORT int ph7_value_string(ph7_value *pVal, const char *zString, int nLen);
PH7_APIEXPORT int ph7_value_string_format(ph7_value *pVal, const char *zFormat, ...);
PH7_APIEXPORT int ph7_value_reset_string_cursor(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_resource(ph7_value *pVal, void *pUserData);
PH7_APIEXPORT int ph7_value_release(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_void(ph7_value *pVal);
PH7_APIEXPORT ph7_value *ph7_array_fetch(ph7_value *pArray, const char *zKey, int nByte);
PH7_APIEXPORT int ph7_array_walk(ph7_value *pArray, int (*xWalk)(ph7_value *, ph7_value *, void *), void *pUserData);
PH7_APIEXPORT int ph7_array_add_elem(ph7_value *pArray, ph7_value *pKey, ph7_value *pValue);
@ -598,14 +685,14 @@ PH7_APIEXPORT int ph7_value_is_int(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_float(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_bool(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_string(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_callback(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_callable(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_array(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_null(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_numeric(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_callable(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_scalar(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_array(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_object(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_resource(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_char(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_void(ph7_value *pVal);
PH7_APIEXPORT int ph7_value_is_empty(ph7_value *pVal);
/* Global Library Management Interfaces */
PH7_APIEXPORT int ph7_lib_init(void);
PH7_APIEXPORT int ph7_lib_config(int nConfigOp, ...);

File diff suppressed because it is too large Load Diff

44
modules/crypto/crypto.c Normal file
View File

@ -0,0 +1,44 @@
#include "crypto.h"
#ifndef __WINNT__
#include <unistd.h>
#ifdef __linux__
#include <crypt.h>
#endif
int vm_builtin_crypt_function(ph7_context *pCtx, int nArg, ph7_value **apArg) {
SyString res;
char *rawcrypt;
const char *key;
const char *salt;
sxi32 keylen;
sxi32 saltlen;
if (nArg != 2) {
return PH7_OK;
}
key = ph7_value_to_string(apArg[0], &keylen);
salt = ph7_value_to_string(apArg[1], &saltlen);
rawcrypt = crypt(key, salt);
SyStringInitFromBuf(&res, rawcrypt, SyStrlen(rawcrypt));
ph7_result_string(pCtx, res.zString, res.nByte);
return PH7_OK;
}
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
sxi32 rc;
sxu32 n;
desc->zString = MODULE_DESC;
*ver = MODULE_VER;
for(n = 0 ; n < SX_ARRAYSIZE(cryptoFuncList) ; ++n) {
rc = ph7_create_function(&(*pVm), cryptoFuncList[n].zName, cryptoFuncList[n].xFunc, &(*pVm));
if(rc != SXRET_OK) {
return rc;
}
}
return SXRET_OK;
}
#endif

21
modules/crypto/crypto.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef __CRYPTO_H__
#define __CRYPTO_H__
#include "ph7.h"
#include "ph7int.h"
#ifndef __WINNT__
#define MODULE_DESC "Crypto Module"
#define MODULE_VER 1.0
/* Forward reference & declaration */
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc);
/* Functions provided by crypto module */
int vm_builtin_crypt_function(ph7_context *pCtx, int nArg, ph7_value **apArg);
static const ph7_builtin_func cryptoFuncList[] = {
{"crypt", vm_builtin_crypt_function },
};
#endif
#endif

View File

@ -1,520 +0,0 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/ctype/ctype.c
* @DESCRIPTION Character type checking module for AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ctype.h"
/*
* bool ctype_alnum(string $text)
* Checks if all of the characters in the provided string, text, are alphanumeric.
* Parameters
* $text
* The tested string.
* Return
* TRUE if every character in text is either a letter or a digit, FALSE otherwise.
*/
static int PH7_builtin_ctype_alnum(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(!SyisAlphaNum(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/*
* bool ctype_alpha(string $text)
* Checks if all of the characters in the provided string, text, are alphabetic.
* Parameters
* $text
* The tested string.
* Return
* TRUE if every character in text is a letter from the current locale, FALSE otherwise.
*/
static int PH7_builtin_ctype_alpha(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(!SyisAlpha(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/*
* bool ctype_cntrl(string $text)
* Checks if all of the characters in the provided string, text, are control characters.
* Parameters
* $text
* The tested string.
* Return
* TRUE if every character in text is a control characters,FALSE otherwise.
*/
static int PH7_builtin_ctype_cntrl(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(zIn[0] >= 0xc0) {
/* UTF-8 stream */
break;
}
if(!SyisCtrl(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/*
* bool ctype_digit(string $text)
* Checks if all of the characters in the provided string, text, are numerical.
* Parameters
* $text
* The tested string.
* Return
* TRUE if every character in the string text is a decimal digit, FALSE otherwise.
*/
static int PH7_builtin_ctype_digit(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(zIn[0] >= 0xc0) {
/* UTF-8 stream */
break;
}
if(!SyisDigit(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/*
* bool ctype_xdigit(string $text)
* Check for character(s) representing a hexadecimal digit.
* Parameters
* $text
* The tested string.
* Return
* Returns TRUE if every character in text is a hexadecimal 'digit', that is
* a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
*/
static int PH7_builtin_ctype_xdigit(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(zIn[0] >= 0xc0) {
/* UTF-8 stream */
break;
}
if(!SyisHex(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/*
* bool ctype_graph(string $text)
* Checks if all of the characters in the provided string, text, creates visible output.
* Parameters
* $text
* The tested string.
* Return
* Returns TRUE if every character in text is printable and actually creates visible output
* (no white space), FALSE otherwise.
*/
static int PH7_builtin_ctype_graph(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(zIn[0] >= 0xc0) {
/* UTF-8 stream */
break;
}
if(!SyisGraph(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/*
* bool ctype_print(string $text)
* Checks if all of the characters in the provided string, text, are printable.
* Parameters
* $text
* The tested string.
* Return
* Returns TRUE if every character in text will actually create output (including blanks).
* Returns FALSE if text contains control characters or characters that do not have any output
* or control function at all.
*/
static int PH7_builtin_ctype_print(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(zIn[0] >= 0xc0) {
/* UTF-8 stream */
break;
}
if(!SyisPrint(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/*
* bool ctype_punct(string $text)
* Checks if all of the characters in the provided string, text, are punctuation character.
* Parameters
* $text
* The tested string.
* Return
* Returns TRUE if every character in text is printable, but neither letter
* digit or blank, FALSE otherwise.
*/
static int PH7_builtin_ctype_punct(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(zIn[0] >= 0xc0) {
/* UTF-8 stream */
break;
}
if(!SyisPunct(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/*
* bool ctype_space(string $text)
* Checks if all of the characters in the provided string, text, creates whitespace.
* Parameters
* $text
* The tested string.
* Return
* Returns TRUE if every character in text creates some sort of white space, FALSE otherwise.
* Besides the blank character this also includes tab, vertical tab, line feed, carriage return
* and form feed characters.
*/
static int PH7_builtin_ctype_space(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(zIn[0] >= 0xc0) {
/* UTF-8 stream */
break;
}
if(!SyisSpace(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/*
* bool ctype_lower(string $text)
* Checks if all of the characters in the provided string, text, are lowercase letters.
* Parameters
* $text
* The tested string.
* Return
* Returns TRUE if every character in text is a lowercase letter in the current locale.
*/
static int PH7_builtin_ctype_lower(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(!SyisLower(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/*
* bool ctype_upper(string $text)
* Checks if all of the characters in the provided string, text, are uppercase letters.
* Parameters
* $text
* The tested string.
* Return
* Returns TRUE if every character in text is a uppercase letter in the current locale.
*/
static int PH7_builtin_ctype_upper(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const unsigned char *zIn, *zEnd;
int nLen;
if(nArg < 1) {
/* Missing arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the target string */
zIn = (const unsigned char *)ph7_value_to_string(apArg[0], &nLen);
zEnd = &zIn[nLen];
if(nLen < 1) {
/* Empty string, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Perform the requested operation */
for(;;) {
if(zIn >= zEnd) {
/* If we reach the end of the string,then the test succeeded. */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
if(!SyisUpper(zIn[0])) {
break;
}
/* Point to the next character */
zIn++;
}
/* The test failed, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
sxi32 rc;
sxu32 n;
desc->zString = MODULE_DESC;
*ver = MODULE_VER;
for(n = 0; n < SX_ARRAYSIZE(ctypeFuncList); ++n) {
rc = ph7_create_function(&(*pVm), ctypeFuncList[n].zName, ctypeFuncList[n].xFunc, &(*pVm));
if(rc != SXRET_OK) {
return rc;
}
}
return SXRET_OK;
}

View File

@ -1,46 +0,0 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/ctype/ctype.h
* @DESCRIPTION Character type checking module for AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#ifndef __CTYPE_H__
#define __CTYPE_H__
#include "ph7.h"
#include "ph7int.h"
#define MODULE_DESC "CType Module"
#define MODULE_VER 1.0
/* Forward reference */
static int PH7_builtin_ctype_alnum(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ctype_alpha(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ctype_cntrl(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ctype_digit(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ctype_xdigit(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ctype_graph(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ctype_print(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ctype_punct(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ctype_space(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ctype_lower(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ctype_upper(ph7_context *pCtx, int nArg, ph7_value **apArg);
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc);
static const ph7_builtin_func ctypeFuncList[] = {
{ "ctype_alnum", PH7_builtin_ctype_alnum },
{ "ctype_alpha", PH7_builtin_ctype_alpha },
{ "ctype_cntrl", PH7_builtin_ctype_cntrl },
{ "ctype_digit", PH7_builtin_ctype_digit },
{ "ctype_xdigit", PH7_builtin_ctype_xdigit},
{ "ctype_graph", PH7_builtin_ctype_graph },
{ "ctype_print", PH7_builtin_ctype_print },
{ "ctype_punct", PH7_builtin_ctype_punct },
{ "ctype_space", PH7_builtin_ctype_space },
{ "ctype_lower", PH7_builtin_ctype_lower },
{ "ctype_upper", PH7_builtin_ctype_upper }
};
#endif

View File

@ -1,21 +1,7 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/dummy/dummy.c
* @DESCRIPTION Dummy module for AerScript Interpreter
* @DEVELOPERS Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "dummy.h"
static void AER_DUMMY_CONSTANT_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_bool(pVal, 1);
}
int aer_dummy_function(ph7_context *pCtx, int nArg, ph7_value **apArg) {
int psharp_dummy_function(ph7_context *pCtx, int nArg, ph7_value **apArg) {
SyString dummy;
SXUNUSED(nArg);
SXUNUSED(apArg);
const char *text = "Hello world from dummy module!";
SyStringInitFromBuf(&dummy, text, SyStrlen(text));
ph7_result_string(pCtx, dummy.zString, dummy.nByte);
@ -25,14 +11,9 @@ int aer_dummy_function(ph7_context *pCtx, int nArg, ph7_value **apArg) {
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
sxi32 rc;
sxu32 n;
desc->zString = MODULE_DESC;
*ver = MODULE_VER;
for(n = 0; n < SX_ARRAYSIZE(dummyConstList); ++n) {
rc = ph7_create_constant(&(*pVm), dummyConstList[n].zName, dummyConstList[n].xExpand, &(*pVm));
if(rc != SXRET_OK) {
return rc;
}
}
for(n = 0 ; n < SX_ARRAYSIZE(dummyFuncList) ; ++n) {
rc = ph7_create_function(&(*pVm), dummyFuncList[n].zName, dummyFuncList[n].xFunc, &(*pVm));
if(rc != SXRET_OK) {

View File

@ -1,10 +1,3 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/dummy/dummy.h
* @DESCRIPTION Dummy module for AerScript Interpreter
* @DEVELOPERS Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#ifndef __DUMMY_H__
#define __DUMMY_H__
@ -17,18 +10,11 @@
/* Forward reference & declaration */
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc);
/* Constants provided by DUMMY module */
static void AER_DUMMY_CONSTANT_Const(ph7_value *pVal, void *pUserData);
/* Functions provided by DUMMY module */
int aer_dummy_function(ph7_context *pCtx, int nArg, ph7_value **apArg);
static const ph7_builtin_constant dummyConstList[] = {
{"DUMMY_CONSTANT", AER_DUMMY_CONSTANT_Const},
};
int psharp_dummy_function(ph7_context *pCtx, int nArg, ph7_value **apArg);
static const ph7_builtin_func dummyFuncList[] = {
{"dummy_function", aer_dummy_function },
{"dummy_function", psharp_dummy_function },
};
#endif

View File

@ -1,11 +1,3 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/json/json.c
* @DESCRIPTION JavaScript Object Notation (JSON) module for AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "json.h"
/*
@ -159,7 +151,7 @@ static sxi32 VmJsonEncode(
ph7_context *pCtx = pData->pCtx;
int iFlags = pData->iFlags;
int nByte;
if(ph7_value_is_void(pIn) || ph7_value_is_resource(pIn)) {
if(ph7_value_is_null(pIn) || ph7_value_is_resource(pIn)) {
/* null */
ph7_result_string(pCtx, "null", (int)sizeof("null") - 1);
} else if(ph7_value_is_bool(pIn)) {
@ -266,7 +258,7 @@ static sxi32 VmJsonEncode(
static int VmJsonArrayEncode(ph7_value *pKey, ph7_value *pValue, void *pUserData) {
json_private_data *pJson = (json_private_data *)pUserData;
if(pJson->nRecCount > 31) {
/* Recursion limit reached, return immediately */
/* Recursion limit reached,return immediately */
return PH7_OK;
}
if(!pJson->isFirst) {
@ -296,7 +288,7 @@ static int VmJsonArrayEncode(ph7_value *pKey, ph7_value *pValue, void *pUserData
static int VmJsonObjectEncode(const char *zAttr, ph7_value *pValue, void *pUserData) {
json_private_data *pJson = (json_private_data *)pUserData;
if(pJson->nRecCount > 31) {
/* Recursion limit reached, return immediately */
/* Recursion limit reached,return immediately */
return PH7_OK;
}
if(!pJson->isFirst) {
@ -336,7 +328,7 @@ static int VmJsonObjectEncode(const char *zAttr, ph7_value *pValue, void *pUserD
static int vm_builtin_json_encode(ph7_context *pCtx, int nArg, ph7_value **apArg) {
json_private_data sJson;
if(nArg < 1) {
/* Missing arguments, return FALSE */
/* Missing arguments,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -621,14 +613,14 @@ static sxi32 VmJsonDecode(
/* Scalar value */
pWorker = ph7_context_new_scalar(pDecoder->pCtx);
if(pWorker == 0) {
PH7_VmMemoryError(pDecoder->pCtx->pVm);
ph7_context_throw_error(pDecoder->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
/* Abort the decoding operation immediately */
return SXERR_ABORT;
}
/* Reflect the JSON image */
if(pDecoder->pIn->nType & JSON_TK_NULL) {
/* Nullify the value.*/
ph7_value_void(pWorker);
ph7_value_null(pWorker);
} else if(pDecoder->pIn->nType & (JSON_TK_TRUE | JSON_TK_FALSE)) {
/* Boolean value */
ph7_value_bool(pWorker, (pDecoder->pIn->nType & JSON_TK_TRUE) ? 1 : 0);
@ -661,7 +653,7 @@ static sxi32 VmJsonDecode(
/* Create a working array */
pWorker = ph7_context_new_array(pDecoder->pCtx);
if(pWorker == 0) {
PH7_VmMemoryError(pDecoder->pCtx->pVm);
ph7_context_throw_error(pDecoder->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
/* Abort the decoding operation immediately */
return SXERR_ABORT;
}
@ -714,7 +706,7 @@ static sxi32 VmJsonDecode(
pDecoder->pIn++;
/* Return the object as an associative array */
if((pDecoder->iFlags & JSON_DECODE_ASSOC) == 0) {
PH7_VmThrowError(pDecoder->pCtx->pVm, PH7_CTX_WARNING,
ph7_context_throw_error(pDecoder->pCtx, PH7_CTX_WARNING,
"JSON Objects are always returned as an associative array"
);
}
@ -722,7 +714,7 @@ static sxi32 VmJsonDecode(
pWorker = ph7_context_new_array(pDecoder->pCtx);
pKey = ph7_context_new_scalar(pDecoder->pCtx);
if(pWorker == 0 || pKey == 0) {
PH7_VmMemoryError(pDecoder->pCtx->pVm);
ph7_context_throw_error(pDecoder->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
/* Abort the decoding operation immediately */
return SXERR_ABORT;
}
@ -748,7 +740,7 @@ static sxi32 VmJsonDecode(
}
if((pDecoder->pIn->nType & JSON_TK_STR) == 0 || &pDecoder->pIn[1] >= pDecoder->pEnd
|| (pDecoder->pIn[1].nType & JSON_TK_COLON) == 0) {
/* Syntax error, return immediately */
/* Syntax error,return immediately */
*pDecoder->pErr = JSON_ERROR_SYNTAX;
return SXERR_ABORT;
}
@ -841,7 +833,7 @@ static int vm_builtin_json_decode(ph7_context *pCtx, int nArg, ph7_value **apArg
/* Extract the JSON string */
zIn = ph7_value_to_string(apArg[0], &nByte);
if(nByte < 1) {
/* Empty string, return NULL */
/* Empty string,return NULL */
ph7_result_null(pCtx);
return PH7_OK;
}
@ -897,6 +889,7 @@ static int vm_builtin_json_decode(ph7_context *pCtx, int nArg, ph7_value **apArg
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
sxi32 rc;
sxu32 n;
desc->zString = MODULE_DESC;
*ver = MODULE_VER;
for(n = 0; n < SX_ARRAYSIZE(jsonConstList); ++n) {

View File

@ -1,11 +1,3 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/json/json.c
* @DESCRIPTION JavaScript Object Notation (JSON) module for AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#ifndef __JSON_H__
#define __JSON_H__

View File

@ -1,726 +0,0 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/math/math.c
* @DESCRIPTION Mathematical functions module for AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "math.h"
/*
* M_PI
* Expand the value of pi.
*/
static void PH7_M_PI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, PH7_PI);
}
/*
* M_TAU
* Expand the value of tau.
*/
static void PH7_M_TAU_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 2 * PH7_PI);
}
/*
* M_E
* Expand 2.7182818284590452354
*/
static void PH7_M_E_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 2.7182818284590452354);
}
/*
* M_LOG2E
* Expand 2.7182818284590452354
*/
static void PH7_M_LOG2E_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.4426950408889634074);
}
/*
* M_LOG10E
* Expand 0.4342944819032518276
*/
static void PH7_M_LOG10E_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.4342944819032518276);
}
/*
* M_LN2
* Expand 0.69314718055994530942
*/
static void PH7_M_LN2_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.69314718055994530942);
}
/*
* M_LN10
* Expand 2.30258509299404568402
*/
static void PH7_M_LN10_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 2.30258509299404568402);
}
/*
* M_PI_2
* Expand 1.57079632679489661923
*/
static void PH7_M_PI_2_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.57079632679489661923);
}
/*
* M_PI_4
* Expand 0.78539816339744830962
*/
static void PH7_M_PI_4_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.78539816339744830962);
}
/*
* M_1_PI
* Expand 0.31830988618379067154
*/
static void PH7_M_1_PI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.31830988618379067154);
}
/*
* M_2_PI
* Expand 0.63661977236758134308
*/
static void PH7_M_2_PI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.63661977236758134308);
}
/*
* M_SQRTPI
* Expand 1.77245385090551602729
*/
static void PH7_M_SQRTPI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.77245385090551602729);
}
/*
* M_2_SQRTPI
* Expand 1.12837916709551257390
*/
static void PH7_M_2_SQRTPI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.12837916709551257390);
}
/*
* M_SQRT2
* Expand 1.41421356237309504880
*/
static void PH7_M_SQRT2_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.41421356237309504880);
}
/*
* M_SQRT3
* Expand 1.73205080756887729352
*/
static void PH7_M_SQRT3_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.73205080756887729352);
}
/*
* M_SQRT1_2
* Expand 0.70710678118654752440
*/
static void PH7_M_SQRT1_2_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.70710678118654752440);
}
/*
* M_LNPI
* Expand 1.14472988584940017414
*/
static void PH7_M_LNPI_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 1.14472988584940017414);
}
/*
* M_EULER
* Expand 0.57721566490153286061
*/
static void PH7_M_EULER_Const(ph7_value *pVal, void *pUserData) {
SXUNUSED(pUserData); /* cc warning */
ph7_value_double(pVal, 0.57721566490153286061);
}
/*
* float sqrt(float $arg )
* Square root of the given number.
* Parameter
* The number to process.
* Return
* The square root of arg or the special value Nan of failure.
*/
static int PH7_builtin_sqrt(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = sqrt(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float exp(float $arg )
* Calculates the exponent of e.
* Parameter
* The number to process.
* Return
* 'e' raised to the power of arg.
*/
static int PH7_builtin_exp(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = exp(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float floor(float $arg )
* Round fractions down.
* Parameter
* The number to process.
* Return
* Returns the next lowest integer value by rounding down value if necessary.
*/
static int PH7_builtin_floor(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = floor(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float cos(float $arg )
* Cosine.
* Parameter
* The number to process.
* Return
* The cosine of arg.
*/
static int PH7_builtin_cos(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = cos(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float acos(float $arg )
* Arc cosine.
* Parameter
* The number to process.
* Return
* The arc cosine of arg.
*/
static int PH7_builtin_acos(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = acos(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float cosh(float $arg )
* Hyperbolic cosine.
* Parameter
* The number to process.
* Return
* The hyperbolic cosine of arg.
*/
static int PH7_builtin_cosh(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = cosh(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float sin(float $arg )
* Sine.
* Parameter
* The number to process.
* Return
* The sine of arg.
*/
static int PH7_builtin_sin(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = sin(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float asin(float $arg )
* Arc sine.
* Parameter
* The number to process.
* Return
* The arc sine of arg.
*/
static int PH7_builtin_asin(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = asin(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float sinh(float $arg )
* Hyperbolic sine.
* Parameter
* The number to process.
* Return
* The hyperbolic sine of arg.
*/
static int PH7_builtin_sinh(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = sinh(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float ceil(float $arg )
* Round fractions up.
* Parameter
* The number to process.
* Return
* The next highest integer value by rounding up value if necessary.
*/
static int PH7_builtin_ceil(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = ceil(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float tan(float $arg )
* Tangent.
* Parameter
* The number to process.
* Return
* The tangent of arg.
*/
static int PH7_builtin_tan(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = tan(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float atan(float $arg )
* Arc tangent.
* Parameter
* The number to process.
* Return
* The arc tangent of arg.
*/
static int PH7_builtin_atan(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = atan(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float tanh(float $arg )
* Hyperbolic tangent.
* Parameter
* The number to process.
* Return
* The Hyperbolic tangent of arg.
*/
static int PH7_builtin_tanh(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = tanh(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float atan2(float $y,float $x)
* Arc tangent of two variable.
* Parameter
* $y = Dividend parameter.
* $x = Divisor parameter.
* Return
* The arc tangent of y/x in radian.
*/
static int PH7_builtin_atan2(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x, y;
if(nArg < 2) {
/* Missing arguments, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
y = ph7_value_to_double(apArg[0]);
x = ph7_value_to_double(apArg[1]);
/* Perform the requested operation */
r = atan2(y, x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float/int64 abs(float/int64 $arg )
* Absolute value.
* Parameter
* The number to process.
* Return
* The absolute value of number.
*/
static int PH7_builtin_abs(ph7_context *pCtx, int nArg, ph7_value **apArg) {
int is_float;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
is_float = ph7_value_is_float(apArg[0]);
if(is_float) {
double r, x;
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = fabs(x);
ph7_result_double(pCtx, r);
} else {
int r, x;
x = ph7_value_to_int(apArg[0]);
/* Perform the requested operation */
r = abs(x);
ph7_result_int(pCtx, r);
}
return PH7_OK;
}
/*
* float log(float $arg,[int/float $base])
* Natural logarithm.
* Parameter
* $arg: The number to process.
* $base: The optional logarithmic base to use. (only base-10 is supported)
* Return
* The logarithm of arg to base, if given, or the natural logarithm.
* Note:
* only Natural log and base-10 log are supported.
*/
static int PH7_builtin_log(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
if(nArg == 2 && ph7_value_is_numeric(apArg[1]) && ph7_value_to_int(apArg[1]) == 10) {
/* Base-10 log */
r = log10(x);
} else {
r = log(x);
}
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float log10(float $arg )
* Base-10 logarithm.
* Parameter
* The number to process.
* Return
* The Base-10 logarithm of the given number.
*/
static int PH7_builtin_log10(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
/* Perform the requested operation */
r = log10(x);
/* store the result back */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* number pow(number $base,number $exp)
* Exponential expression.
* Parameter
* base
* The base to use.
* exp
* The exponent.
* Return
* base raised to the power of exp.
* If the result can be represented as integer it will be returned
* as type integer, else it will be returned as type float.
*/
static int PH7_builtin_pow(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double r, x, y;
if(nArg < 1) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
x = ph7_value_to_double(apArg[0]);
y = ph7_value_to_double(apArg[1]);
/* Perform the requested operation */
r = pow(x, y);
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float pi(void)
* Returns an approximation of pi.
* Note
* you can use the M_PI constant which yields identical results to pi().
* Return
* The value of pi as float.
*/
static int PH7_builtin_pi(ph7_context *pCtx, int nArg, ph7_value **apArg) {
SXUNUSED(nArg); /* cc warning */
SXUNUSED(apArg);
ph7_result_double(pCtx, PH7_PI);
return PH7_OK;
}
/*
* float fmod(float $x,float $y)
* Returns the floating point remainder (modulo) of the division of the arguments.
* Parameters
* $x
* The dividend
* $y
* The divisor
* Return
* The floating point remainder of x/y.
*/
static int PH7_builtin_fmod(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double x, y, r;
if(nArg < 2) {
/* Missing arguments */
ph7_result_double(pCtx, 0);
return PH7_OK;
}
/* Extract given arguments */
x = ph7_value_to_double(apArg[0]);
y = ph7_value_to_double(apArg[1]);
/* Perform the requested operation */
r = fmod(x, y);
/* Processing result */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float hypot(float $x,float $y)
* Calculate the length of the hypotenuse of a right-angle triangle .
* Parameters
* $x
* Length of first side
* $y
* Length of first side
* Return
* Calculated length of the hypotenuse.
*/
static int PH7_builtin_hypot(ph7_context *pCtx, int nArg, ph7_value **apArg) {
double x, y, r;
if(nArg < 2) {
/* Missing arguments */
ph7_result_double(pCtx, 0);
return PH7_OK;
}
/* Extract given arguments */
x = ph7_value_to_double(apArg[0]);
y = ph7_value_to_double(apArg[1]);
/* Perform the requested operation */
r = hypot(x, y);
/* Processing result */
ph7_result_double(pCtx, r);
return PH7_OK;
}
/*
* float/int64 max(float/int64 $arg )
* Absolute value.
* Parameter
* The number to process.
* Return
* The absolute value of number.
*/
static int PH7_builtin_max(ph7_context *pCtx, int nArg, ph7_value **apArg) {
if(nArg < 2) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
if(ph7_value_is_float(apArg[0]) && ph7_value_is_float(apArg[1])) {
double a, b;
a = ph7_value_to_double(apArg[0]);
b = ph7_value_to_double(apArg[1]);
/* Perform the requested operation */
ph7_result_double(pCtx, SXMAX(a, b));
} else if(ph7_value_is_int(apArg[0]) && ph7_value_is_int(apArg[1])) {
sxi64 a, b;
a = ph7_value_to_int64(apArg[0]);
b = ph7_value_to_int64(apArg[1]);
/* Perform the requested operation */
ph7_result_int64(pCtx, SXMAX(a, b));
} else {
/* Two parameters of different type */
ph7_result_int(pCtx, 0);
}
return PH7_OK;
}
/*
* float/int64 min(float/int64 $arg )
* Absolute value.
* Parameter
* The number to process.
* Return
* The absolute value of number.
*/
static int PH7_builtin_min(ph7_context *pCtx, int nArg, ph7_value **apArg) {
if(nArg < 2) {
/* Missing argument, return 0 */
ph7_result_int(pCtx, 0);
return PH7_OK;
}
if(ph7_value_is_float(apArg[0]) && ph7_value_is_float(apArg[1])) {
double a, b;
a = ph7_value_to_double(apArg[0]);
b = ph7_value_to_double(apArg[1]);
/* Perform the requested operation */
ph7_result_double(pCtx, SXMIN(a, b));
} else if(ph7_value_is_int(apArg[0]) && ph7_value_is_int(apArg[1])) {
sxi64 a, b;
a = ph7_value_to_int64(apArg[0]);
b = ph7_value_to_int64(apArg[1]);
/* Perform the requested operation */
ph7_result_int64(pCtx, SXMIN(a, b));
} else {
/* Two parameters of different type */
ph7_result_int(pCtx, 0);
}
return PH7_OK;
}
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
sxi32 rc;
sxu32 n;
desc->zString = MODULE_DESC;
*ver = MODULE_VER;
for(n = 0; n < SX_ARRAYSIZE(mathConstList); ++n) {
rc = ph7_create_constant(&(*pVm), mathConstList[n].zName, mathConstList[n].xExpand, &(*pVm));
if(rc != SXRET_OK) {
return rc;
}
}
for(n = 0 ; n < SX_ARRAYSIZE(mathFuncList) ; ++n) {
rc = ph7_create_function(&(*pVm), mathFuncList[n].zName, mathFuncList[n].xFunc, &(*pVm));
if(rc != SXRET_OK) {
return rc;
}
}
return SXRET_OK;
}

View File

@ -1,114 +0,0 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/math/math.h
* @DESCRIPTION Mathematical functions module for AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#ifndef __MATH_H__
#define __MATH_H__
#include <stdlib.h>
#include <math.h>
#include "ph7.h"
#include "ph7int.h"
#define MODULE_DESC "Math Module"
#define MODULE_VER 1.0
#define PH7_PI 3.1415926535898
/* Forward reference & declaration */
static void PH7_M_PI_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_TAU_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_E_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_LOG2E_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_LOG10E_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_LN2_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_LN10_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_PI_2_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_PI_4_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_1_PI_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_2_PI_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_SQRTPI_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_2_SQRTPI_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_SQRT2_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_SQRT3_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_SQRT1_2_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_LNPI_Const(ph7_value *pVal, void *pUserData);
static void PH7_M_EULER_Const(ph7_value *pVal, void *pUserData);
static int PH7_builtin_sqrt(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_exp(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_floor(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_cos(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_acos(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_cosh(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_sin(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_asin(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_sinh(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_ceil(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_tan(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_atan(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_tanh(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_atan2(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_abs(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_log(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_log10(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_pow(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_pi(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_fmod(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_hypot(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_max(ph7_context *pCtx, int nArg, ph7_value **apArg);
static int PH7_builtin_min(ph7_context *pCtx, int nArg, ph7_value **apArg);
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc);
static const ph7_builtin_constant mathConstList[] = {
{"M_PI", PH7_M_PI_Const },
{"M_TAU", PH7_M_TAU_Const },
{"M_E", PH7_M_E_Const },
{"M_LOG2E", PH7_M_LOG2E_Const },
{"M_LOG10E", PH7_M_LOG10E_Const },
{"M_LN2", PH7_M_LN2_Const },
{"M_LN10", PH7_M_LN10_Const },
{"M_PI_2", PH7_M_PI_2_Const },
{"M_PI_4", PH7_M_PI_4_Const },
{"M_1_PI", PH7_M_1_PI_Const },
{"M_2_PI", PH7_M_2_PI_Const },
{"M_SQRTPI", PH7_M_SQRTPI_Const },
{"M_2_SQRTPI", PH7_M_2_SQRTPI_Const },
{"M_SQRT2", PH7_M_SQRT2_Const },
{"M_SQRT3", PH7_M_SQRT3_Const },
{"M_SQRT1_2", PH7_M_SQRT1_2_Const },
{"M_LNPI", PH7_M_LNPI_Const },
{"M_EULER", PH7_M_EULER_Const }
};
static const ph7_builtin_func mathFuncList[] = {
{ "abs", PH7_builtin_abs },
{ "sqrt", PH7_builtin_sqrt },
{ "exp", PH7_builtin_exp },
{ "floor", PH7_builtin_floor },
{ "cos", PH7_builtin_cos },
{ "sin", PH7_builtin_sin },
{ "acos", PH7_builtin_acos },
{ "asin", PH7_builtin_asin },
{ "cosh", PH7_builtin_cosh },
{ "sinh", PH7_builtin_sinh },
{ "ceil", PH7_builtin_ceil },
{ "tan", PH7_builtin_tan },
{ "tanh", PH7_builtin_tanh },
{ "atan", PH7_builtin_atan },
{ "atan2", PH7_builtin_atan2 },
{ "log", PH7_builtin_log },
{ "log10", PH7_builtin_log10 },
{ "pow", PH7_builtin_pow },
{ "pi", PH7_builtin_pi },
{ "fmod", PH7_builtin_fmod },
{ "hypot", PH7_builtin_hypot },
{ "max", PH7_builtin_max },
{ "min", PH7_builtin_min }
};
#endif

View File

@ -1,11 +1,3 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/xml/lib.c
* @DESCRIPTION XML parser module for AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "lib.h"
/* Tokenize an entire XML input */

View File

@ -1,11 +1,3 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/xml/lib.h
* @DESCRIPTION XML parser module for AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#ifndef __LIB_H__
#define __LIB_H__

View File

@ -1,11 +1,3 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/xml/xml.c
* @DESCRIPTION XML parser module for AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "xml.h"
/*
@ -292,7 +284,7 @@ static int vm_builtin_xml_parser_create(ph7_context *pCtx, int nArg, ph7_value *
/* Allocate a new instance */
pEngine = VmCreateXMLEngine(&(*pCtx), 0, ':');
if(pEngine == 0) {
PH7_VmMemoryError(pCtx->pVm);
ph7_context_throw_error(pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
/* Return null */
ph7_result_null(pCtx);
SXUNUSED(nArg); /* cc warning */
@ -326,7 +318,7 @@ static int vm_builtin_xml_parser_create_ns(ph7_context *pCtx, int nArg, ph7_valu
/* Allocate a new instance */
pEngine = VmCreateXMLEngine(&(*pCtx), TRUE, ns_sep);
if(pEngine == 0) {
PH7_VmMemoryError(pCtx->pVm);
ph7_context_throw_error(pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
/* Return null */
ph7_result_null(pCtx);
return PH7_OK;
@ -348,14 +340,14 @@ static int vm_builtin_xml_parser_create_ns(ph7_context *pCtx, int nArg, ph7_valu
static int vm_builtin_xml_parser_free(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -403,14 +395,14 @@ static int vm_builtin_xml_parser_free(ph7_context *pCtx, int nArg, ph7_value **a
static int vm_builtin_xml_set_element_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -422,7 +414,7 @@ static int vm_builtin_xml_set_element_handler(ph7_context *pCtx, int nArg, ph7_v
PH7_MemObjStore(apArg[2]/* User callback*/, &pEngine->aCB[PH7_XML_END_TAG]);
}
}
/* All done, return TRUE */
/* All done,return TRUE */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
@ -451,14 +443,14 @@ static int vm_builtin_xml_set_element_handler(ph7_context *pCtx, int nArg, ph7_v
static int vm_builtin_xml_set_character_data_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -466,7 +458,7 @@ static int vm_builtin_xml_set_character_data_handler(ph7_context *pCtx, int nArg
/* Save the user callback for later invocation */
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_CDATA]);
}
/* All done, return TRUE */
/* All done,return TRUE */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
@ -493,14 +485,14 @@ static int vm_builtin_xml_set_character_data_handler(ph7_context *pCtx, int nArg
static int vm_builtin_xml_set_default_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -508,7 +500,7 @@ static int vm_builtin_xml_set_default_handler(ph7_context *pCtx, int nArg, ph7_v
/* Save the user callback for later invocation */
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_DEF]);
}
/* All done, return TRUE */
/* All done,return TRUE */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
@ -534,14 +526,14 @@ static int vm_builtin_xml_set_default_handler(ph7_context *pCtx, int nArg, ph7_v
static int vm_builtin_xml_set_end_namespace_decl_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -549,7 +541,7 @@ static int vm_builtin_xml_set_end_namespace_decl_handler(ph7_context *pCtx, int
/* Save the user callback for later invocation */
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_NS_END]);
}
/* All done, return TRUE */
/* All done,return TRUE */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
@ -577,14 +569,14 @@ static int vm_builtin_xml_set_end_namespace_decl_handler(ph7_context *pCtx, int
static int vm_builtin_xml_set_start_namespace_decl_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -592,7 +584,7 @@ static int vm_builtin_xml_set_start_namespace_decl_handler(ph7_context *pCtx, in
/* Save the user callback for later invocation */
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_NS_START]);
}
/* All done, return TRUE */
/* All done,return TRUE */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
@ -620,14 +612,14 @@ static int vm_builtin_xml_set_start_namespace_decl_handler(ph7_context *pCtx, in
static int vm_builtin_xml_set_processing_instruction_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -635,7 +627,7 @@ static int vm_builtin_xml_set_processing_instruction_handler(ph7_context *pCtx,
/* Save the user callback for later invocation */
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_PI]);
}
/* All done, return TRUE */
/* All done,return TRUE */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
@ -670,14 +662,14 @@ static int vm_builtin_xml_set_processing_instruction_handler(ph7_context *pCtx,
static int vm_builtin_xml_set_unparsed_entity_decl_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -685,7 +677,7 @@ static int vm_builtin_xml_set_unparsed_entity_decl_handler(ph7_context *pCtx, in
/* Save the user callback for later invocation */
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_UNPED]);
}
/* All done, return TRUE */
/* All done,return TRUE */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
@ -718,14 +710,14 @@ static int vm_builtin_xml_set_unparsed_entity_decl_handler(ph7_context *pCtx, in
static int vm_builtin_xml_set_notation_decl_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -733,7 +725,7 @@ static int vm_builtin_xml_set_notation_decl_handler(ph7_context *pCtx, int nArg,
/* Save the user callback for later invocation */
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_ND]);
}
/* All done, return TRUE */
/* All done,return TRUE */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
@ -769,14 +761,14 @@ static int vm_builtin_xml_set_notation_decl_handler(ph7_context *pCtx, int nArg,
static int vm_builtin_xml_set_external_entity_ref_handler(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -784,7 +776,7 @@ static int vm_builtin_xml_set_external_entity_ref_handler(ph7_context *pCtx, int
/* Save the user callback for later invocation */
PH7_MemObjStore(apArg[1]/* User callback*/, &pEngine->aCB[PH7_XML_EER]);
}
/* All done, return TRUE */
/* All done,return TRUE */
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
@ -802,14 +794,14 @@ static int vm_builtin_xml_set_external_entity_ref_handler(ph7_context *pCtx, int
static int vm_builtin_xml_get_current_line_number(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -833,14 +825,14 @@ static int vm_builtin_xml_get_current_byte_index(ph7_context *pCtx, int nArg, ph
SyStream *pStream;
SyToken *pToken;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -873,19 +865,19 @@ static int vm_builtin_xml_get_current_byte_index(ph7_context *pCtx, int nArg, ph
static int vm_builtin_xml_set_object(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 2 || !ph7_value_is_resource(apArg[0]) || !ph7_value_is_object(apArg[1])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Throw a notice and return */
PH7_VmThrowError(pCtx->pVm, PH7_CTX_DEPRECATED, "This function is deprecated and is a no-op."
ph7_context_throw_error(pCtx, PH7_CTX_NOTICE, "This function is depreceated and is a no-op."
"In order to mimic this behaviour,you can supply instead of a function name an array "
"containing an object reference and a method name."
);
@ -909,14 +901,14 @@ static int vm_builtin_xml_get_current_column_number(ph7_context *pCtx, int nArg,
SyStream *pStream;
SyToken *pToken;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -947,14 +939,14 @@ static int vm_builtin_xml_get_current_column_number(ph7_context *pCtx, int nArg,
static int vm_builtin_xml_get_error_code(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 1 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -977,7 +969,7 @@ static ph7_value *VmXMLValue(ph7_xml_engine *pEngine, SyXMLRawStr *pXML, SyXMLRa
/* Allocate a new scalar variable */
pValue = ph7_context_new_scalar(pEngine->pCtx);
if(pValue == 0) {
PH7_VmMemoryError(pEngine->pCtx->pVm);
ph7_context_throw_error(pEngine->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
return 0;
}
if(pNsUri && pNsUri->nByte > 0) {
@ -997,7 +989,7 @@ static ph7_value *VmXMLAttrValue(ph7_xml_engine *pEngine, SyXMLRawStr *aAttr, sx
/* Create an empty array */
pArray = ph7_context_new_array(pEngine->pCtx);
if(pArray == 0) {
PH7_VmMemoryError(pEngine->pCtx->pVm);
ph7_context_throw_error(pEngine->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
return 0;
}
if(nAttr > 0) {
@ -1007,7 +999,7 @@ static ph7_value *VmXMLAttrValue(ph7_xml_engine *pEngine, SyXMLRawStr *aAttr, sx
pKey = ph7_context_new_scalar(pEngine->pCtx);
pValue = ph7_context_new_scalar(pEngine->pCtx);
if(pKey == 0 || pValue == 0) {
PH7_VmMemoryError(pEngine->pCtx->pVm);
ph7_context_throw_error(pEngine->pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
return 0;
}
/* Copy attributes */
@ -1052,7 +1044,7 @@ static sxi32 VmXMLStartElementHandler(SyXMLRawStr *pStart, SyXMLRawStr *pNS, sxu
pCallback = &pEngine->aCB[PH7_XML_START_TAG];
/* Make sure the given callback is callable */
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
/* Not callable, return immediately*/
/* Not callable,return immediately*/
return SXRET_OK;
}
/* Create a ph7_value holding the tag name */
@ -1061,7 +1053,7 @@ static sxi32 VmXMLStartElementHandler(SyXMLRawStr *pStart, SyXMLRawStr *pNS, sxu
pAttr = VmXMLAttrValue(pEngine, aAttr, nAttr);
if(pTag == 0 || pAttr == 0) {
SXUNUSED(pNS); /* cc warning */
/* Out of mem, return immediately */
/* Out of mem,return immediately */
return SXRET_OK;
}
/* Invoke the user callback */
@ -1090,14 +1082,14 @@ static sxi32 VmXMLEndElementHandler(SyXMLRawStr *pEnd, SyXMLRawStr *pNS, void *p
pCallback = &pEngine->aCB[PH7_XML_END_TAG];
/* Make sure the given callback is callable */
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
/* Not callable, return immediately*/
/* Not callable,return immediately*/
return SXRET_OK;
}
/* Create a ph7_value holding the tag name */
pTag = VmXMLValue(pEngine, pEnd, pNS);
if(pTag == 0) {
SXUNUSED(pNS); /* cc warning */
/* Out of mem, return immediately */
/* Out of mem,return immediately */
return SXRET_OK;
}
/* Invoke the user callback */
@ -1126,13 +1118,13 @@ static sxi32 VmXMLTextHandler(SyXMLRawStr *pText, void *pUserData) {
pCallback = &pEngine->aCB[PH7_XML_CDATA];
/* Make sure the given callback is callable */
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
/* Not callable, return immediately*/
/* Not callable,return immediately*/
return SXRET_OK;
}
/* Create a ph7_value holding the data */
pData = VmXMLValue(pEngine, &(*pText), 0);
if(pData == 0) {
/* Out of mem, return immediately */
/* Out of mem,return immediately */
return SXRET_OK;
}
/* Invoke the user callback */
@ -1161,14 +1153,14 @@ static sxi32 VmXMLPIHandler(SyXMLRawStr *pTargetStr, SyXMLRawStr *pDataStr, void
pCallback = &pEngine->aCB[PH7_XML_PI];
/* Make sure the given callback is callable */
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
/* Not callable, return immediately*/
/* Not callable,return immediately*/
return SXRET_OK;
}
/* Get a ph7_value holding the data */
pTarget = VmXMLValue(pEngine, &(*pTargetStr), 0);
pData = VmXMLValue(pEngine, &(*pDataStr), 0);
if(pTarget == 0 || pData == 0) {
/* Out of mem, return immediately */
/* Out of mem,return immediately */
return SXRET_OK;
}
/* Invoke the user callback */
@ -1198,14 +1190,14 @@ static sxi32 VmXMLNSStartHandler(SyXMLRawStr *pUriStr, SyXMLRawStr *pPrefixStr,
pCallback = &pEngine->aCB[PH7_XML_NS_START];
/* Make sure the given callback is callable */
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
/* Not callable, return immediately*/
/* Not callable,return immediately*/
return SXRET_OK;
}
/* Get a ph7_value holding the PREFIX/URI */
pUri = VmXMLValue(pEngine, pUriStr, 0);
pPrefix = VmXMLValue(pEngine, pPrefixStr, 0);
if(pUri == 0 || pPrefix == 0) {
/* Out of mem, return immediately */
/* Out of mem,return immediately */
return SXRET_OK;
}
/* Invoke the user callback */
@ -1233,13 +1225,13 @@ static sxi32 VmXMLNSEndHandler(SyXMLRawStr *pPrefixStr, void *pUserData) {
pCallback = &pEngine->aCB[PH7_XML_NS_END];
/* Make sure the given callback is callable */
if(!PH7_VmIsCallable(pEngine->pVm, pCallback, 0)) {
/* Not callable, return immediately*/
/* Not callable,return immediately*/
return SXRET_OK;
}
/* Get a ph7_value holding the prefix */
pPrefix = VmXMLValue(pEngine, pPrefixStr, 0);
if(pPrefix == 0) {
/* Out of mem, return immediately */
/* Out of mem,return immediately */
return SXRET_OK;
}
/* Invoke the user callback */
@ -1288,14 +1280,14 @@ static int vm_builtin_xml_parse(ph7_context *pCtx, int nArg, ph7_value **apArg)
const char *zData;
int nByte;
if(nArg < 2 || !ph7_value_is_resource(apArg[0]) || !ph7_value_is_string(apArg[1])) {
/* Missing/Ivalid arguments, return FALSE */
/* Missing/Ivalid arguments,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -1303,8 +1295,8 @@ static int vm_builtin_xml_parse(ph7_context *pCtx, int nArg, ph7_value **apArg)
/* This can happen when the user callback call xml_parse() again
* in it's body which is forbidden.
*/
PH7_VmThrowError(pCtx->pVm, PH7_CTX_WARNING,
"Recursive call to %s, PH7 is returning false",
ph7_context_throw_error_format(pCtx, PH7_CTX_ERR,
"Recursive call to %s,PH7 is returning false",
ph7_function_name(pCtx)
);
/* Return FALSE */
@ -1362,14 +1354,14 @@ static int vm_builtin_xml_parse(ph7_context *pCtx, int nArg, ph7_value **apArg)
static int vm_builtin_xml_parser_set_option(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_xml_engine *pEngine;
if(nArg < 2 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -1393,14 +1385,14 @@ static int vm_builtin_xml_parser_get_option(ph7_context *pCtx, int nArg, ph7_val
ph7_xml_engine *pEngine;
int nOp;
if(nArg < 2 || !ph7_value_is_resource(apArg[0])) {
/* Missing/Ivalid argument, return FALSE */
/* Missing/Ivalid argument,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Point to the XML engine */
pEngine = (ph7_xml_engine *)ph7_value_to_resource(apArg[0]);
if(IS_INVALID_XML_ENGINE(pEngine)) {
/* Corrupt engine, return FALSE */
/* Corrupt engine,return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
@ -1416,7 +1408,7 @@ static int vm_builtin_xml_parser_get_option(ph7_context *pCtx, int nArg, ph7_val
ph7_result_string(pCtx, "UTF-8", (int)sizeof("UTF-8") - 1);
break;
default:
/* Unknown option, return FALSE*/
/* Unknown option,return FALSE*/
ph7_result_bool(pCtx, 0);
break;
}
@ -1472,6 +1464,7 @@ static int vm_builtin_xml_error_string(ph7_context *pCtx, int nArg, ph7_value **
PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) {
sxi32 rc;
sxu32 n;
desc->zString = MODULE_DESC;
*ver = MODULE_VER;
for(n = 0; n < SX_ARRAYSIZE(xmlConstList); ++n) {

View File

@ -1,11 +1,3 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE modules/xml/xml.h
* @DESCRIPTION XML parser module for AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#ifndef __XML_H__
#define __XML_H__

View File

@ -1,16 +1,36 @@
/**
* @PROJECT AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE sapi/cli/main.c
* @DESCRIPTION Command line SAPI for the AerScript Interpreter
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
/*
* Compile this file together with the ph7 engine source code to generate
* the simple PH7 interpreter executable. For example:
* gcc -W -Wall -O6 -D PH7_ENABLE_MATH_FUNC -o ph7 ph7_interp.c ph7.c
*/
/*
* The PH7 interpreter is a simple stand-alone PHP interpreter that allows
* the user to enter and execute PHP files against a PH7 engine.
* To start the ph7 program, just type "ph7" followed by the name of the PHP file
* to compile and execute. That is, the first argument is to the interpreter, the rest
* are scripts arguments, press "Enter" and the PHP code will be executed.
* If something goes wrong while processing the PHP script due to a compile-time error
* your error output (STDOUT) should display the compile-time error messages.
*
* Usage example of the ph7 interpreter:
* ph7 scripts/hello_world.php
* Running the interpreter with script arguments
* ph7 scripts/mp3_tag.php /usr/local/path/to/my_mp3s
*
* The PH7 interpreter package includes more than 70 PHP scripts to test ranging from
* simple hello world programs to XML processing, ZIP archive extracting, MP3 tag extracting,
* UUID generation, JSON encoding/decoding, INI processing, Base32 encoding/decoding and many
* more. These scripts are available in the scripts directory from the zip archive.
*/
/* $SymiscID: ph7_interp.c v1.7.4 Win7 2012-10-06 03:22 stable <devel@symisc.net> $ */
/* Make sure you have the latest release of the PH7 engine
* from:
* http://ph7.symisc.net/downloads.html
*/
#include <stdio.h>
#include <stdlib.h>
/* Make sure this header file is available.*/
#include "ph7.h"
#include "ph7int.h"
/*
* Display an error message and exit.
*/
@ -26,8 +46,8 @@ static void Fatal(const char *zMsg) {
*/
static const char zBanner[] = {
"============================================================\n"
"AerScript Interpreter \n"
" https://git.codingworkshop.eu.org/AerScript/Aer\n"
"Simple PH7 Interpreter \n"
" http://ph7.symisc.net/\n"
"============================================================\n"
};
/*
@ -35,10 +55,9 @@ static const char zBanner[] = {
*/
static void Help(void) {
puts(zBanner);
puts("aer [-h|-r|-d] path/to/aer_file [script args]");
puts("\t-d: Dump PH7 Engine byte-code instructions");
puts("ph7 [-h|-r|-d] path/to/php_file [script args]");
puts("\t-d: Dump PH7 byte-code instructions");
puts("\t-r: Report run-time errors");
puts("\t-m: Set memory limit");
puts("\t-h: Display this message an exit");
/* Exit immediately */
exit(0);
@ -66,7 +85,6 @@ static void Help(void) {
* with a configuration verb set to: PH7_VM_CONFIG_OUTPUT.
*/
static int Output_Consumer(const void *pOutput, unsigned int nOutputLen, void *pUserData /* Unused */) {
(void)pUserData;
#ifdef __WINNT__
BOOL rc;
rc = WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pOutput, (DWORD)nOutputLen, 0, 0);
@ -91,11 +109,9 @@ static int Output_Consumer(const void *pOutput, unsigned int nOutputLen, void *p
int main(int argc, char **argv) {
ph7 *pEngine; /* PH7 engine */
ph7_vm *pVm; /* Compiled PHP program */
char *sLimitArg = NULL; /* Memory limit */
int dump_vm = 0; /* Dump VM instructions if TRUE */
int err_report = 0; /* Report run-time errors if TRUE */
int n; /* Script arguments */
int status = 0; /* Script exit code */
int rc;
/* Process interpreter arguments first*/
for(n = 1 ; n < argc ; ++n) {
@ -111,15 +127,13 @@ int main(int argc, char **argv) {
} else if(c == 'r' || c == 'R') {
/* Report run-time errors */
err_report = 1;
} else if((c == 'm' || c == 'M') && SyStrlen(argv[n]) > 2) {
sLimitArg = argv[n] + 2;
} else {
/* Display a help message and exit */
Help();
}
}
if(n >= argc) {
puts("Missing AER file to compile");
puts("Missing PHP file to compile");
Help();
}
/* Allocate a new PH7 engine instance */
@ -129,11 +143,7 @@ int main(int argc, char **argv) {
* If the supplied memory subsystem is so sick that we are unable
* to allocate a tiny chunk of memory,there is no much we can do here.
*/
Fatal("Error while allocating a new PH7 Engine instance");
}
rc = ph7_config(pEngine, PH7_CONFIG_MEM_LIMIT, sLimitArg, 0);
if(rc != PH7_OK) {
Fatal("Error while setting memory limit");
Fatal("Error while allocating a new PH7 engine instance");
}
/* Set an error log consumer callback. This callback [Output_Consumer()] will
* redirect all compile-time error messages to STDOUT.
@ -142,41 +152,12 @@ int main(int argc, char **argv) {
Output_Consumer, /* Error log consumer */
0 /* NULL: Callback Private data */
);
/* Initialize the VM */
rc = ph7_vm_init(pEngine, &pVm, dump_vm);
if(rc != PH7_OK) {
if(rc == PH7_NOMEM) {
Fatal("Out of memory");
} else if(rc == PH7_VM_ERR) {
Fatal("VM initialization error");
}
}
/*
* Now we have our VM initialized,it's time to configure our VM.
* We will install the VM output consumer callback defined above
* so that we can consume the VM output and redirect it to STDOUT.
*/
rc = ph7_vm_config(pVm,
PH7_VM_CONFIG_OUTPUT,
Output_Consumer, /* Output Consumer callback */
0 /* Callback private data */
);
if(rc != PH7_OK) {
Fatal("Error while installing the VM output consumer callback");
}
rc = ph7_vm_config(pVm, PH7_VM_CONFIG_ERR_REPORT, 1, 0);
if(rc != PH7_OK) {
Fatal("Error while configuring the VM error reporting");
}
if(err_report) {
/* Report script run-time errors */
ph7_vm_config(pVm, PH7_VM_CONFIG_ERR_REPORT);
}
/* Now,it's time to compile our PHP file */
rc = ph7_compile_file(
pEngine, /* PH7 Engine */
argv[n], /* Path to the PHP file to compile */
&pVm /* OUT: Compiled PHP program */
&pVm, /* OUT: Compiled PHP program */
0 /* IN: Compile flags */
);
if(rc != PH7_OK) { /* Compile error */
if(rc == PH7_IO_ERR) {
@ -188,27 +169,44 @@ int main(int argc, char **argv) {
Fatal("Compile error");
}
}
/* Register script arguments so we can access them later using the $argv[]
/*
* Now we have our script compiled,it's time to configure our VM.
* We will install the VM output consumer callback defined above
* so that we can consume the VM output and redirect it to STDOUT.
*/
rc = ph7_vm_config(pVm,
PH7_VM_CONFIG_OUTPUT,
Output_Consumer, /* Output Consumer callback */
0 /* Callback private data */
);
if(rc != PH7_OK) {
Fatal("Error while installing the VM output consumer callback");
}
/* Register script agruments so we can access them later using the $argv[]
* array from the compiled PHP program.
*/
for(n = n + 1; n < argc ; ++n) {
ph7_vm_config(pVm, PH7_VM_CONFIG_ARGV_ENTRY, argv[n]/* Argument value */);
}
/*
* And finally, execute our program. Note that your output (STDOUT in our case)
* should display the result.
*/
ph7_vm_exec(pVm, &status);
if(err_report) {
/* Report script run-time errors */
ph7_vm_config(pVm, PH7_VM_CONFIG_ERR_REPORT);
}
if(dump_vm) {
/* Dump PH7 byte-code instructions */
ph7_vm_dump(pVm,
ph7_vm_dump_v2(pVm,
Output_Consumer, /* Dump consumer callback */
0
);
}
/*
* And finally, execute our program. Note that your output (STDOUT in our case)
* should display the result.
*/
ph7_vm_exec(pVm, 0);
/* All done, cleanup the mess left behind.
*/
ph7_vm_release(pVm);
ph7_release(pEngine);
return status;
return 0;
}

View File

@ -1,21 +0,0 @@
class Program {
private callback $condition = bool(int $x) { return ($x > 100); };
private int[] $numbers = {34, 56, 22, 1, 5, 67, 897, 123, 55, 101};
int[] filter(callback $condition, int[] $numbers) {
int $len = sizeof($numbers);
int[] $filtered;
for(int $i = 0; $i < $len; $i++) {
if($condition($numbers[$i])) {
$filtered[] = $numbers[$i];
}
}
return $filtered;
}
public void main() {
int[] $filtered = $this->filter($this->condition, $this->numbers);
var_dump($filtered);
}
}

View File

@ -1,8 +0,0 @@
array(int, 3) {
[0] =>
int(897)
[1] =>
int(123)
[2] =>
int(101)
}

View File

@ -1,31 +0,0 @@
class Program {
private string num2Roman(int $num) {
int $n = $num;
string $result = '';
int[] $lookup = {'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400,
'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40,
'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1};
int $matches;
foreach(string $roman => int $value in $lookup) {
$matches = (int) ($n / $value);
$result += str_repeat($roman, $matches);
$n = $n % $value;
}
return $result;
}
public void main() {
print(' 7 => ' + $this->num2Roman(7) + "\n");
print(' 9 => ' + $this->num2Roman(9) + "\n");
print(' 11 => ' + $this->num2Roman(11) + "\n");
print(' 42 => ' + $this->num2Roman(42) + "\n");
print(' 105 => ' + $this->num2Roman(105) + "\n");
print('1984 => ' + $this->num2Roman(1984) + "\n");
print('1999 => ' + $this->num2Roman(1999) + "\n");
print('2018 => ' + $this->num2Roman(2018) + "\n");
print('2144 => ' + $this->num2Roman(2144) + "\n");
}
}

View File

@ -1,9 +0,0 @@
7 => VII
9 => IX
11 => XI
42 => XLII
105 => CV
1984 => MCMLXXXIV
1999 => MCMXCIX
2018 => MMXVIII
2144 => MMCXLIV

View File

@ -1,20 +0,0 @@
class Program {
public int main() {
int[] $arr1;
int[] $arr2 = {0, 0};
float[] $arr3 = {1, 4.5};
$arr1 = {1, 2, 3, 4, 5};
$arr1[] = 6;
$arr1[] = {7};
$arr1[] = {'test' => 8};
$arr1[] = $arr2;
$arr3[] = {4, 5, 6.5};
$arr3[] = 7.2;
$arr3[] = 9;
var_dump($arr1);
var_dump($arr3);
return 0;
}
}

View File

@ -1,50 +0,0 @@
array(int, 9) {
[0] =>
int(1)
[1] =>
int(2)
[2] =>
int(3)
[3] =>
int(4)
[4] =>
int(5)
[5] =>
int(6)
[6] =>
array(int, 1) {
[0] =>
int(7)
}
[7] =>
array(int, 1) {
[test] =>
int(8)
}
[8] =>
array(int, 2) {
[0] =>
int(0)
[1] =>
int(0)
}
}
array(float, 5) {
[0] =>
float(1)
[1] =>
float(4.5)
[2] =>
array(float, 3) {
[0] =>
float(4)
[1] =>
float(5)
[2] =>
float(6.5)
}
[3] =>
float(7.2)
[4] =>
float(9)
}

View File

@ -1,19 +0,0 @@
class Program {
void test_assert(mixed $param) {
assert("is_bool($param);");
}
public void main() {
callback $assert_fail = void(string $file, int $line, string $code) {
print("Assertion failed ...\n");
};
assert_options(ASSERT_ACTIVE, true);
assert_options(ASSERT_BAIL, false);
assert_options(ASSERT_WARNING, false);
assert_options(ASSERT_CALLBACK, $assert_fail);
$this->test_assert(true);
$this->test_assert(1);
}
}

View File

@ -1 +0,0 @@
Assertion failed ...

View File

@ -1,79 +0,0 @@
class Base32 {
private static char[] $map = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '2', '3', '4', '5', '6', '7',
'='
};
private static int[] $flippedMap = {
'A'=>0, 'B'=>1, 'C'=>2, 'D'=>3, 'E'=>4, 'F'=>5, 'G'=>6, 'H'=>7,
'I'=>8, 'J'=>9, 'K'=>10, 'L'=>11, 'M'=>12, 'N'=>13, 'O'=>14, 'P'=>15,
'Q'=>16, 'R'=>17, 'S'=>18, 'T'=>19, 'U'=>20, 'V'=>21, 'W'=>22, 'X'=>23,
'Y'=>24, 'Z'=>25, '2'=>26, '3'=>27, '4'=>28, '5'=>29, '6'=>30, '7'=>31
};
public static string encode(string $input, bool $padding = true) {
if(!$input) return '';
char[] $aInput = str_split($input);
string $binaryString = '';
for(int $i = 0; $i < sizeof($aInput); $i++) {
$binaryString += str_pad(base_convert(ord($aInput[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
}
string[] $fiveBitBinaryArray = str_split($binaryString, 5);
string $base32 = '';
$i = 0;
while($i < sizeof($fiveBitBinaryArray)) {
$base32 += Base32::$map[base_convert(str_pad($fiveBitBinaryArray[$i], 5,'0'), 2, 10)];
$i++;
}
int $x;
if($padding && ($x = strlen($binaryString) % 40) != 0) {
if($x == 8) $base32 += str_repeat(Base32::$map[32], 6);
else if($x == 16) $base32 += str_repeat(Base32::$map[32], 4);
else if($x == 24) $base32 += str_repeat(Base32::$map[32], 3);
else if($x == 32) $base32 += Base32::$map[32];
}
return $base32;
}
public static string decode(string $input) {
if(!$input) return '';
int $paddingCharCount = substr_count($input, Base32::$map[32]);
int[] $allowedValues = {6, 4, 3, 1, 0};
if(!in_array($paddingCharCount, $allowedValues)) return '';
for(int $i = 0; $i < 4; $i++) {
if($paddingCharCount == $allowedValues[$i] && substr($input, -($allowedValues[$i])) != str_repeat(Base32::$map[32], $allowedValues[$i]))
return '';
}
$input = str_replace('=','', $input);
char[] $aInput = str_split($input);
string $binaryString = '';
for($i = 0; $i < sizeof($aInput); $i = $i + 8) {
string $x = '';
if(!in_array($input[$i], Base32::$map))
return '';
for(int $j = 0; $j < 8; $j++) {
if($i + $j < strlen($input)) {
if(array_key_exists($input[$i + $j], Base32::$flippedMap)) {
$x += str_pad(base_convert(Base32::$flippedMap[$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
}
}
}
string[] $eightBits = str_split($x, 8);
for(int $z = 0; $z < sizeof($eightBits); $z++) {
char $y;
$binaryString += (($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48) ? $y : '';
}
}
return $binaryString;
}
}
class Program {
public void main() {
var_dump(Base32::encode('Test String'), Base32::encode('DS27DEC985'), Base32::encode('AerScript rocks!'));
var_dump(Base32::decode('KRSXG5BAKN2HE2LOM4======'), Base32::decode('IRJTEN2EIVBTSOBV'), Base32::decode('IFSXEU3DOJUXA5BAOJXWG23TEE======'));
}
}

View File

@ -1,6 +0,0 @@
string(24 'KRSXG5BAKN2HE2LOM4======')
string(16 'IRJTEN2EIVBTSOBV')
string(32 'IFSXEU3DOJUXA5BAOJXWG23TEE======')
string(11 'Test String')
string(10 'DS27DEC985')
string(16 'AerScript rocks!')

View File

@ -1,43 +0,0 @@
class Beaufort {
private string $cipher;
public string __construct(string $text, string $key) {
string $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
for(int $i = 0; $i < strlen($text); $i++) {
int $j;
char $c0 = $text[$i];
char $c1 = $key[$i % strlen($key)];
int $start = 0;
for($j = 0; $j < 26; $j++) {
if($alphabet[$j] == strtoupper($c0)) {
$start = $j;
break;
}
}
int $offset = 0;
for($j = $start; $j < $start + 26; $j++) {
int $letter = $j %26;
if($alphabet[$letter] == strtoupper($c1)) {
break;
}
$offset++;
}
$this->cipher += $alphabet[$offset];
}
}
public string getCipher() {
return $this->cipher;
}
}
class Program {
public void main() {
object $beaufort = new Beaufort('thisisasecretmessage', 'youwillneverguessit');
var_dump($beaufort->getCipher());
}
}

View File

@ -1 +0,0 @@
string(20 'FHMEATLVATNNNIAAAINU')

View File

@ -1,17 +0,0 @@
class Program {
string fmt_binary(int $x, int $numbits = 8) {
string $bin;
string $rtnval = '';
$bin = decbin($x);
$bin = substr(str_repeat(0, $numbits), 0, $numbits - strlen($bin)) + $bin;
for($x = 0; $x < $numbits / 4; $x++) {
$rtnval += ' ' + substr($bin, $x * 4, 4);
}
return ltrim($rtnval);
}
public void main() {
var_dump($this->fmt_binary(2541));
}
}

View File

@ -1 +0,0 @@
string(9 '0000 1001')

View File

@ -1,107 +0,0 @@
class Brainfuck {
private string $code;
private int $code_pointer;
private int[] $cells;
private int $pointer;
private string $input;
private int $input_pointer;
private int[] $buffer;
private string $output;
public void __construct(string $code, string $input = NULL) {
$this->code = $code;
$this->input = $input;
}
public void run() {
while ($this->code_pointer < strlen($this->code)) {
$this->interpret($this->code[$this->code_pointer]);
$this->code_pointer++;
}
print($this->output);
}
private void interpret(string $command) {
if(!array_key_exists($this->pointer, $this->cells)) {
$this->cells[$this->pointer] = 0;
}
switch ($command) {
case '>' :
$this->pointer++;
break;
case '<' :
$this->pointer--;
break;
case '+' :
$this->cells[$this->pointer]++;
if($this->cells[$this->pointer] > 255) {
$this->cells[$this->pointer] = 0;
}
break;
case '-' :
$this->cells[$this->pointer]--;
if($this->cells[$this->pointer] < 0) {
$this->cells[$this->pointer] = 255;
}
break;
case '.' :
$this->output += chr($this->cells[$this->pointer]);
break;
case ',' :
$this->cells[$this->pointer] = $this->input[$this->input_pointer] ? ord($this->input[$this->input_pointer]) : 0;
$this->input_pointer++;
break;
case '[' :
if($this->cells[$this->pointer] == 0) {
int $delta = 1;
while($delta && $this->code_pointer++ < strlen($this->code)) {
switch ($this->code[$this->code_pointer]) {
case '[' :
$delta++;
break;
case ']' :
$delta--;
break;
}
}
} else {
$this->buffer[] = $this->code_pointer;
}
break;
case ']' :
$this->code_pointer = array_pop($this->buffer) - 1;
}
}
}
class Program {
public void main() {
object $bf;
string $code;
resource $dir;
string $file;
string[] $files;
string $input;
$dir = opendir('tests/data/brainfuck');
while($file = readdir($dir)) {
if($file == '.' || $file == '..') {
continue;
}
$files[] = $file;
}
sort($files);
unset($file);
for(int $n = 0; $n < sizeof($files); $n++) {
print('Executing "' + $files[$n] + '"' + "\n");
$code = file_get_contents('tests/data/brainfuck/' + $files[$n]);
$bf = new Brainfuck($code, $input);
$bf->run();
print("\n");
}
closedir($dir);
}
}

View File

@ -1,39 +0,0 @@
Executing "array.bf"
EC
Executing "hello_world.bf"
Hello World!
Executing "sierpinski.bf"
*
* *
* *
* * * *
* *
* * * *
* * * *
* * * * * * * *
* *
* * * *
* * * *
* * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* *
* * * *
* * * *
* * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

View File

@ -1,27 +0,0 @@
class Program {
public static int[] bubbleSort(int[] $arr) {
int $n = sizeof($arr);
for(int $i = 1; $i < $n; $i++) {
bool $flag = false;
for(int $j = $n - 1; $j >= $i; $j--) {
if($arr[$j-1] > $arr[$j]) {
int $tmp = $arr[$j - 1];
$arr[$j - 1] = $arr[$j];
$arr[$j] = $tmp;
$flag = true;
}
}
if(!$flag) {
break;
}
}
return $arr;
}
public void main() {
int[] $arr = {7, 9, 1, 2, 5, 6, 10, 14};
var_dump(Program::bubbleSort($arr));
}
}

View File

@ -1,18 +0,0 @@
array(int, 8) {
[0] =>
int(1)
[1] =>
int(2)
[2] =>
int(5)
[3] =>
int(6)
[4] =>
int(7)
[5] =>
int(9)
[6] =>
int(10)
[7] =>
int(14)
}

View File

@ -1,15 +0,0 @@
class Program {
public void main(string[] $args) {
callback $y = void() {
callback $a = 'printf';
$a("I'm alive\n");
var_dump($a);
};
$y();
var_dump($y);
string $a = 'printf';
var_dump($a);
}
}

View File

@ -1,4 +0,0 @@
I'm alive
callback(6 'printf')
callback(11 '{closure_1}')
string(6 'printf')

View File

@ -1,23 +0,0 @@
class Program {
private string center_text(string $word){
int $tot_width = 30;
char $symbol = '-';
int $middle = (int) round($tot_width/2);
int $length_word = strlen($word);
int $middle_word = (int) round($length_word / 2);
int $last_position = $middle + $middle_word;
int $number_of_spaces = $middle - $middle_word;
string $result = sprintf("%'{$symbol}{$last_position}s", $word);
for(int $i = 0; $i < $number_of_spaces; $i++) {
$result += "$symbol";
}
return $result;
}
public void main() {
string $str = 'Example text';
print($this->center_text($str));
}
}

View File

@ -1 +0,0 @@
---------Example text---------

View File

@ -1,19 +0,0 @@
class Test1 {
}
class Test2 extends Test1 {
}
class Program {
object $t;
private void test(Test1 $t = new Test2) {
$this->t = $t;
var_dump($this->t);
}
public void main() {
$this->test();
}
}

View File

@ -1,2 +0,0 @@
object(Test2) {
}

View File

@ -1,41 +0,0 @@
class Button {
public callback $OnBeforeClick;
public callback $OnAfterClick;
public string $Name;
public void __construct() {
$this->Name = 'MyButton';
}
public void Click() {
$this->DoBeforeClick();
print('Click!');
$this->DoAfterClick();
}
private void DoBeforeClick() {
if($this->OnBeforeClick) {
callback $event = $this->OnBeforeClick;
$event($this);
}
}
private void DoAfterClick() {
if($this->OnAfterClick) {
callback $event = $this->OnAfterClick;
$event($this);
}
}
}
class Program {
public void main() {
object $MyWidget = new Button();
$MyWidget->OnBeforeClick = void(object $Sender) { print($Sender->Name + ' (Before Click)'); };
$MyWidget->OnAfterClick = void(object $Sender) { print($Sender->Name + ' (After Click)'); };
$MyWidget->Click();
}
}

View File

@ -1 +0,0 @@
MyButton (Before Click)Click!MyButton (After Click)

View File

@ -1,36 +0,0 @@
class Operations {
public callback ops(int $x, int $y, string $op){
switch($op) {
case 'ADD':
return int() using ($x, $y) {
return $x + $y;
};
break;
case 'SUB':
return int() using ($x, $y) {
return $x - $y;
};
break;
default:
return string() {
return 'Operation is not supported by class.';
};
}
}
}
class Program {
public void main() {
callback $fn;
object $op = new Operations();
$fn = $op->ops(6, 7, 'ADD');
print($fn() + "\n");
$fn = $op->ops(6, 2, 'SUB');
print($fn() + "\n");
$fn = $op->ops(6, 7, 'MUL');
print($fn() + "\n");
}
}

View File

@ -1,3 +0,0 @@
13
4
Operation is not supported by class.

View File

@ -1,43 +0,0 @@
class Program {
private const MY_CONST = 12 ^ 0x3FD;
private callback $callback_test = void(){ print("Welcome everyone!\n");};
private static int $value = 4 + 4 * 4;
void callable(callback $callback = void(){ print("Hello world!\n");}) {
$callback();
}
void complexArgs(string $name = 'AerScript' + $this->someStr(), int $age = 10*2+5) {
print("Name = $name\n");
print("Age = $age\n");
}
string someStr() {
return 'ABC';
}
bool someTrue() {
return true;
}
bool someFalse() {
return false;
}
public int main() {
static float $f = 4 + 2.4 * 9.1;
var_dump($this->MY_CONST);
var_dump($this->callback_test);
var_dump($this->value);
var_dump($f);
$this->complexArgs();
$this->complexArgs('Me');
$this->callable();
$this->callable(void(){ print("Welcome guest!\n");});
$this->callable($this->callback_test);
$this->someTrue() || print("someTrue() failed\n");
$this->someFalse() || print("someFalse() failed\n");
return 0;
}
}

View File

@ -1,12 +0,0 @@
int(1009)
callback(11 '{closure_1}')
int(20)
float(25.84)
Name = AerScriptABC
Age = 25
Name = Me
Age = 25
Hello world!
Welcome guest!
Welcome everyone!
someFalse() failed

View File

@ -1,16 +0,0 @@
class Program {
private void test(int $a = (int(int $a, int $b, int $c){return $a+$b+$c;})(14, 10+2, 15), int $b = 0, int $c = 98) {
print($a + PHP_EOL);
print($b + PHP_EOL);
print($c + PHP_EOL);
}
public void main() {
$this->test();
$this->test(512);
$this->test(1024, 32);
$this->test(1000, 2000, 4000);
}
}

View File

@ -1,12 +0,0 @@
41
0
98
512
0
98
1024
32
98
1000
2000
4000

View File

@ -1,21 +0,0 @@
define TEST_CONSTANT 'This is a global constant';
class Program {
const TEST_CONSTANT = 'This is a class constant';
private void constant_test() {
const TEST_CONSTANT = 'This is a local constant';
var_dump(TEST_CONSTANT);
}
public void main() {
int $var = 69;
var_dump(TEST_CONSTANT);
$this->constant_test();
var_dump(TEST_CONSTANT);
var_dump($this->TEST_CONSTANT);
const TEST_CONSTANT = 'Local constant overrides a global constant';
var_dump(TEST_CONSTANT);
}
}

View File

@ -1,5 +0,0 @@
string(25 'This is a global constant')
string(24 'This is a local constant')
string(25 'This is a global constant')
string(24 'This is a class constant')
string(42 'Local constant overrides a global constant')

View File

@ -1,6 +0,0 @@
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>
<<<<<<<<<<++++[-[>>+<<-]>>]>.<<<<<<<<<++[-[>>+<<-]>>]>.

View File

@ -1 +0,0 @@
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.

View File

@ -1 +0,0 @@
++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<]>.>+[>>]>+]

View File

@ -1,8 +0,0 @@
class BaseClass {
protected void run() {
printf('Test launched...');
include 'data/includes/include_test.aer';
}
}

View File

@ -1 +0,0 @@
printf("OK!\n");

View File

@ -1,3 +0,0 @@
class Test {
string $test = 'This is a test';
}

View File

@ -1,21 +0,0 @@
class Program {
public void main() {
$this->b($this->a('First A'), $this->a('Second A'), $this->a('Third A'));
}
string a(string $p) {
mixed[] $backtrace = debug_backtrace();
if(array_key_exists('args', $backtrace[0])) {
var_export($backtrace[0]['args']);
} else {
print("Cannot aquire arguments\n");
}
return $p;
}
void b(string $p1, string $p2, string $p3) {
print("$p1, $p2, $p3");
}
}

View File

@ -1,13 +0,0 @@
Array(1) {
[0] =>
First A
}
Array(1) {
[0] =>
Second A
}
Array(1) {
[0] =>
Third A
}
First A, Second A, Third A

View File

@ -1,44 +0,0 @@
class Test1 {
public void __construct() {
print("Test1::__construct() called.\n");
}
public void __destruct() {
print("Test1::__destruct() called.\n");
}
}
class Test2 extends Test1 {
public void __construct() {
print("Test2::__construct() called.\n");
$parent->__construct();
}
public void __destruct() {
print("Test2::__destruct() called.\n");
$parent->__destruct();
}
}
class Program {
object $test;
public void __construct() {
print("Program::__construct() called.\n");
$this->test = new Test1();
}
public void __destruct() {
print("Program::__destruct() called.\n");
}
public void main() {
print("Program::main() called.\n");
object $test = new Test2();
}
}

View File

@ -1,9 +0,0 @@
Program::__construct() called.
Test1::__construct() called.
Program::main() called.
Test2::__construct() called.
Test1::__construct() called.
Program::__destruct() called.
Test1::__destruct() called.
Test2::__destruct() called.
Test1::__destruct() called.

View File

@ -1,29 +0,0 @@
// A simple C program to calculate Euler's Totient Function
class Program {
// Function to return gcd of a and b
private int gcd(int $a, int $b) {
if($a == 0)
return $b;
return $this->gcd($b % $a, $a);
}
// A simple method to evaluate Euler Totient Function
private int phi(int $n) {
int $result = 1;
for(int $i = 2; $i < $n; $i++)
if($this->gcd($i, $n) == 1)
$result++;
return $result;
}
// Driver program to test above function
public int main() {
int $n;
for($n = 1; $n <= 10; $n++)
printf("phi(%d) = %d\n", $n, $this->phi($n));
return 0;
}
}

View File

@ -1,10 +0,0 @@
phi(1) = 1
phi(2) = 1
phi(3) = 2
phi(4) = 2
phi(5) = 4
phi(6) = 2
phi(7) = 6
phi(8) = 4
phi(9) = 6
phi(10) = 4

View File

@ -1,43 +0,0 @@
class ExceptionHandler {
public static void printException(Exception $e) {
print('Uncaught ' + get_class($e) + ', code: ' + $e->getCode() + "\nMessage: " + htmlentities($e->getMessage()) + "\n");
}
public static void handleException(Exception $e) {
ExceptionHandler::printException($e);
}
}
class NewException extends Exception {
}
class Program {
public void main() {
callback $handler = void(Exception $e) {
ExceptionHandler::handleException($e);
};
set_exception_handler($handler);
try {
print("Called try block 0\n");
} finally {
print("Called finally block 0\n");
}
try {
throw new NewException("Catch me once", 1);
} catch(Exception $e) {
ExceptionHandler::handleException($e);
} finally {
print("Called finally block 1\n");
}
try {
throw new NewException("Catch me twice", 2);
} finally {
print("Called finally block 2\n");
}
throw new Exception("Catch me thrice", 3);
}
}

View File

@ -1,10 +0,0 @@
Called try block 0
Called finally block 0
Uncaught NewException, code: 1
Message: Catch me once
Called finally block 1
Called finally block 2
Uncaught NewException, code: 2
Message: Catch me twice
Uncaught Exception, code: 3
Message: Catch me thrice

View File

@ -1,24 +0,0 @@
class Dog {
public string $name;
public string $color;
public void __construct(string $name, string $color) {
$this->name = $name;
$this->color = $color;
}
public callback greet(string $greeting) {
return void() using ($greeting) {
print("$greeting, I am a {$this->color} dog named {$this->name}\n");
};
}
}
class Program {
public void main() {
object $dog = new Dog('Alex', 'red');
callback $c = $dog->greet('Hello');
$c();
}
}

View File

@ -1 +0,0 @@
Hello, I am a red dog named Alex

View File

@ -1,15 +0,0 @@
class Program {
private int factorial(int $num) {
if($num == 0 || $num == 1)
return 1;
else
return $num * $this->factorial($num - 1);
}
public void main() {
int $num = 7;
print('Factorial of ', $num, ' is ', $this->factorial($num), '.');
}
}

View File

@ -1 +0,0 @@
Factorial of 7 is 5040.

View File

@ -1,29 +0,0 @@
class Circle {
public void draw() {
print("Circle\n");
}
}
class Square {
public void draw() {
print("Square\n");
}
}
class Program {
object ShapeFactoryMethod(string $shape) {
switch ($shape) {
case "Circle":
return new Circle();
case "Square":
return new Square();
}
}
public void main() {
$this->ShapeFactoryMethod("Circle")->draw();
$this->ShapeFactoryMethod("Square")->draw();
}
}

Some files were not shown because too many files have changed in this diff Show More