first commit
CI / Build (clang, clang++, ubuntu-22.04, linux, 3.10, master, x86,x86_64) (push) Canceled after 0s
CI / Build (clang, clang++, windows-2022, windows, 3.10, master, x86,x86_64) (push) Canceled after 0s
CI / Release (push) Canceled after 0s

This commit is contained in:
2026-09-13 22:18:11 +01:00
commit 08c03ac533
6701 changed files with 1577314 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
if(ENABLE_THIRD_PARTY)
set(LIBLLHTTP_SOURCES
llhttp/src/api.c
llhttp/src/http.c
llhttp/src/llhttp.c
)
add_library(llhttp OBJECT ${LIBLLHTTP_SOURCES})
target_include_directories(llhttp PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/llhttp/include"
)
set_target_properties(llhttp PROPERTIES
POSITION_INDEPENDENT_CODE ON
)
set(LIBURL_PARSER_SOURCES
url-parser/url_parser.c
)
add_library(url-parser OBJECT ${LIBURL_PARSER_SOURCES})
set_target_properties(url-parser PROPERTIES
POSITION_INDEPENDENT_CODE ON)
if(HAVE_NEVERBLEED)
set(NEVERBLEED_SOURCES
neverbleed/neverbleed.c
)
add_library(neverbleed ${NEVERBLEED_SOURCES})
target_include_directories(neverbleed PRIVATE ${OPENSSL_INCLUDE_DIRS})
target_include_directories(neverbleed INTERFACE
"${CMAKE_SOURCE_DIR}/third-party/neverbleed"
)
target_link_libraries(neverbleed ${OPENSSL_LIBRARIES})
endif()
if(HAVE_MRUBY)
# EXTRA_DIST = build_config.rb mruby/*
set(MRUBY_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/mruby/build")
set(MRUBY_LIBRARY
"${CMAKE_STATIC_LIBRARY_PREFIX}mruby${CMAKE_STATIC_LIBRARY_SUFFIX}"
)
# The mruby build needs some env vars. Alternatively, look at cmake -P
if(CMAKE_VERSION VERSION_LESS "3.1")
# XXX works only for Unixes?
set(ENV_COMMAND env)
else()
set(ENV_COMMAND ${CMAKE_COMMAND} -E env)
endif()
# Required for the Ninja generator. For older CMake, you first have to
# invoke 'ninja mruby' before building dependents.
if(CMAKE_VERSION VERSION_LESS "3.2")
set(_byproducts)
else()
set(_byproducts BYPRODUCTS "mruby/build/lib/${MRUBY_LIBRARY}")
endif()
add_custom_target(mruby
COMMAND ${ENV_COMMAND}
"MRUBY_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/build_config.rb"
"BUILD_DIR=${MRUBY_BUILD_DIR}"
"INSTALL_DIR=${MRUBY_BUILD_DIR}/install/bin"
"CC=${CMAKE_C_COMPILER}" "CXX=${CMAKE_CXX_COMPILER}"
"${CMAKE_CURRENT_SOURCE_DIR}/mruby/minirake"
-f "${CMAKE_CURRENT_SOURCE_DIR}/mruby/Rakefile"
${_byproducts}
VERBATIM
)
# Make the mruby library available to others in this project without them
# having to worry about include dirs and the mruby location.
add_library(mruby-lib STATIC IMPORTED GLOBAL)
set_target_properties(mruby-lib PROPERTIES
IMPORTED_LOCATION "${MRUBY_BUILD_DIR}/lib/${MRUBY_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/mruby/include"
)
add_dependencies(mruby-lib mruby)
set_directory_properties(PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES mruby/build
)
endif()
endif()
+80
View File
@@ -0,0 +1,80 @@
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2014 Tatsuhiro Tsujikawa
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
AM_CPPFLAGS = @DEFS@
EXTRA_DIST = CMakeLists.txt
if ENABLE_THIRD_PARTY
noinst_LTLIBRARIES = liburl-parser.la
liburl_parser_la_SOURCES = \
url-parser/url_parser.c \
url-parser/url_parser.h
noinst_LTLIBRARIES += libllhttp.la
libllhttp_la_SOURCES = \
llhttp/src/api.c \
llhttp/src/http.c \
llhttp/src/llhttp.c \
llhttp/include/llhttp.h
libllhttp_la_CPPFLAGS = -I${srcdir}/llhttp/include
if HAVE_NEVERBLEED
noinst_LTLIBRARIES += libneverbleed.la
libneverbleed_la_CPPFLAGS = @OPENSSL_CFLAGS@
libneverbleed_la_LIBADD = @OPENSSL_LIBS@
libneverbleed_la_SOURCES = neverbleed/neverbleed.c neverbleed/neverbleed.h
endif # HAVE_NEVERBLEED
if HAVE_MRUBY
EXTRA_DIST += build_config.rb mruby/*
.PHONY: all-local clean mruby
mruby:
mkdir -p "${abs_builddir}/mruby/build"
diff "${srcdir}/build_config.rb" "${abs_builddir}/mruby/build/build_config.rb" >& /dev/null || \
cp "${srcdir}/build_config.rb" "${abs_builddir}/mruby/build"
MRUBY_CONFIG="${abs_builddir}/mruby/build/build_config.rb" \
BUILD_DIR="${abs_builddir}/mruby/build" \
INSTALL_DIR="${abs_builddir}/mruby/build/install/bin" \
CC="${CC}" CXX="$(firstword $(CXX))" LD="${LD}" \
CFLAGS="${CPPFLAGS} ${CFLAGS}" \
CXXFLAGS="$(wordlist 2, $(words $(CXX)), $(CXX)) ${CPPFLAGS} ${CXXFLAGS}" \
LDFLAGS="${LDFLAGS}" \
"${srcdir}/mruby/minirake" -f "${srcdir}/mruby/Rakefile"
all-local: mruby
clean-local:
[ ! -f "${abs_builddir}/mruby/build/build_config.rb" ] || \
MRUBY_CONFIG="${abs_builddir}/mruby/build/build_config.rb" \
BUILD_DIR="${abs_builddir}/mruby/build" \
CC="${CC}" \
"${srcdir}/mruby/minirake" -f "${srcdir}/mruby/Rakefile" clean
endif # HAVE_MRUBY
endif # ENABLE_THIRD_PARTY
+852
View File
@@ -0,0 +1,852 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2014 Tatsuhiro Tsujikawa
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@am__append_1 = libneverbleed.la
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@am__append_2 = build_config.rb mruby/*
subdir = third-party
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_boost_asio.m4 \
$(top_srcdir)/m4/ax_boost_base.m4 \
$(top_srcdir)/m4/ax_boost_system.m4 \
$(top_srcdir)/m4/ax_boost_thread.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
$(top_srcdir)/m4/ax_python_devel.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libllhttp_la_LIBADD =
am__libllhttp_la_SOURCES_DIST = llhttp/src/api.c llhttp/src/http.c \
llhttp/src/llhttp.c llhttp/include/llhttp.h
am__dirstamp = $(am__leading_dot)dirstamp
@ENABLE_THIRD_PARTY_TRUE@am_libllhttp_la_OBJECTS = \
@ENABLE_THIRD_PARTY_TRUE@ llhttp/src/libllhttp_la-api.lo \
@ENABLE_THIRD_PARTY_TRUE@ llhttp/src/libllhttp_la-http.lo \
@ENABLE_THIRD_PARTY_TRUE@ llhttp/src/libllhttp_la-llhttp.lo
libllhttp_la_OBJECTS = $(am_libllhttp_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
@ENABLE_THIRD_PARTY_TRUE@am_libllhttp_la_rpath =
libneverbleed_la_DEPENDENCIES =
am__libneverbleed_la_SOURCES_DIST = neverbleed/neverbleed.c \
neverbleed/neverbleed.h
@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@am_libneverbleed_la_OBJECTS = neverbleed/libneverbleed_la-neverbleed.lo
libneverbleed_la_OBJECTS = $(am_libneverbleed_la_OBJECTS)
@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@am_libneverbleed_la_rpath =
liburl_parser_la_LIBADD =
am__liburl_parser_la_SOURCES_DIST = url-parser/url_parser.c \
url-parser/url_parser.h
@ENABLE_THIRD_PARTY_TRUE@am_liburl_parser_la_OBJECTS = \
@ENABLE_THIRD_PARTY_TRUE@ url-parser/url_parser.lo
liburl_parser_la_OBJECTS = $(am_liburl_parser_la_OBJECTS)
@ENABLE_THIRD_PARTY_TRUE@am_liburl_parser_la_rpath =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = llhttp/src/$(DEPDIR)/libllhttp_la-api.Plo \
llhttp/src/$(DEPDIR)/libllhttp_la-http.Plo \
llhttp/src/$(DEPDIR)/libllhttp_la-llhttp.Plo \
neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Plo \
url-parser/$(DEPDIR)/url_parser.Plo
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libllhttp_la_SOURCES) $(libneverbleed_la_SOURCES) \
$(liburl_parser_la_SOURCES)
DIST_SOURCES = $(am__libllhttp_la_SOURCES_DIST) \
$(am__libneverbleed_la_SOURCES_DIST) \
$(am__liburl_parser_la_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
APPLDFLAGS = @APPLDFLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BOOST_ASIO_LIB = @BOOST_ASIO_LIB@
BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
BOOST_LDFLAGS = @BOOST_LDFLAGS@
BOOST_SYSTEM_LIB = @BOOST_SYSTEM_LIB@
BOOST_THREAD_LIB = @BOOST_THREAD_LIB@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CUNIT_CFLAGS = @CUNIT_CFLAGS@
CUNIT_LIBS = @CUNIT_LIBS@
CXX = @CXX@
CXX1XCXXFLAGS = @CXX1XCXXFLAGS@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
CYTHON = @CYTHON@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
EXTRACFLAG = @EXTRACFLAG@
FGREP = @FGREP@
GREP = @GREP@
HAVE_CXX14 = @HAVE_CXX14@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
JANSSON_CFLAGS = @JANSSON_CFLAGS@
JANSSON_LIBS = @JANSSON_LIBS@
JEMALLOC_LIBS = @JEMALLOC_LIBS@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBCARES_CFLAGS = @LIBCARES_CFLAGS@
LIBCARES_LIBS = @LIBCARES_LIBS@
LIBEVENT_OPENSSL_CFLAGS = @LIBEVENT_OPENSSL_CFLAGS@
LIBEVENT_OPENSSL_LIBS = @LIBEVENT_OPENSSL_LIBS@
LIBEV_CFLAGS = @LIBEV_CFLAGS@
LIBEV_LIBS = @LIBEV_LIBS@
LIBMRUBY_CFLAGS = @LIBMRUBY_CFLAGS@
LIBMRUBY_LIBS = @LIBMRUBY_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
LIBXML2_LIBS = @LIBXML2_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_AGE = @LT_AGE@
LT_CURRENT = @LT_CURRENT@
LT_REVISION = @LT_REVISION@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
OPENSSL_LIBS = @OPENSSL_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PYTHON = @PYTHON@
PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
PYTHON_LIBS = @PYTHON_LIBS@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
PYTHON_VERSION = @PYTHON_VERSION@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@
SYSTEMD_LIBS = @SYSTEMD_LIBS@
TESTLDADD = @TESTLDADD@
VERSION = @VERSION@
WARNCFLAGS = @WARNCFLAGS@
WARNCXXFLAGS = @WARNCXXFLAGS@
ZLIB_CFLAGS = @ZLIB_CFLAGS@
ZLIB_LIBS = @ZLIB_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AM_CPPFLAGS = @DEFS@
EXTRA_DIST = CMakeLists.txt $(am__append_2)
@ENABLE_THIRD_PARTY_TRUE@noinst_LTLIBRARIES = liburl-parser.la \
@ENABLE_THIRD_PARTY_TRUE@ libllhttp.la $(am__append_1)
@ENABLE_THIRD_PARTY_TRUE@liburl_parser_la_SOURCES = \
@ENABLE_THIRD_PARTY_TRUE@ url-parser/url_parser.c \
@ENABLE_THIRD_PARTY_TRUE@ url-parser/url_parser.h
@ENABLE_THIRD_PARTY_TRUE@libllhttp_la_SOURCES = \
@ENABLE_THIRD_PARTY_TRUE@ llhttp/src/api.c \
@ENABLE_THIRD_PARTY_TRUE@ llhttp/src/http.c \
@ENABLE_THIRD_PARTY_TRUE@ llhttp/src/llhttp.c \
@ENABLE_THIRD_PARTY_TRUE@ llhttp/include/llhttp.h
@ENABLE_THIRD_PARTY_TRUE@libllhttp_la_CPPFLAGS = -I${srcdir}/llhttp/include
@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@libneverbleed_la_CPPFLAGS = @OPENSSL_CFLAGS@
@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@libneverbleed_la_LIBADD = @OPENSSL_LIBS@
@ENABLE_THIRD_PARTY_TRUE@@HAVE_NEVERBLEED_TRUE@libneverbleed_la_SOURCES = neverbleed/neverbleed.c neverbleed/neverbleed.h
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu third-party/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu third-party/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
llhttp/src/$(am__dirstamp):
@$(MKDIR_P) llhttp/src
@: > llhttp/src/$(am__dirstamp)
llhttp/src/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) llhttp/src/$(DEPDIR)
@: > llhttp/src/$(DEPDIR)/$(am__dirstamp)
llhttp/src/libllhttp_la-api.lo: llhttp/src/$(am__dirstamp) \
llhttp/src/$(DEPDIR)/$(am__dirstamp)
llhttp/src/libllhttp_la-http.lo: llhttp/src/$(am__dirstamp) \
llhttp/src/$(DEPDIR)/$(am__dirstamp)
llhttp/src/libllhttp_la-llhttp.lo: llhttp/src/$(am__dirstamp) \
llhttp/src/$(DEPDIR)/$(am__dirstamp)
libllhttp.la: $(libllhttp_la_OBJECTS) $(libllhttp_la_DEPENDENCIES) $(EXTRA_libllhttp_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(am_libllhttp_la_rpath) $(libllhttp_la_OBJECTS) $(libllhttp_la_LIBADD) $(LIBS)
neverbleed/$(am__dirstamp):
@$(MKDIR_P) neverbleed
@: > neverbleed/$(am__dirstamp)
neverbleed/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) neverbleed/$(DEPDIR)
@: > neverbleed/$(DEPDIR)/$(am__dirstamp)
neverbleed/libneverbleed_la-neverbleed.lo: neverbleed/$(am__dirstamp) \
neverbleed/$(DEPDIR)/$(am__dirstamp)
libneverbleed.la: $(libneverbleed_la_OBJECTS) $(libneverbleed_la_DEPENDENCIES) $(EXTRA_libneverbleed_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(am_libneverbleed_la_rpath) $(libneverbleed_la_OBJECTS) $(libneverbleed_la_LIBADD) $(LIBS)
url-parser/$(am__dirstamp):
@$(MKDIR_P) url-parser
@: > url-parser/$(am__dirstamp)
url-parser/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) url-parser/$(DEPDIR)
@: > url-parser/$(DEPDIR)/$(am__dirstamp)
url-parser/url_parser.lo: url-parser/$(am__dirstamp) \
url-parser/$(DEPDIR)/$(am__dirstamp)
liburl-parser.la: $(liburl_parser_la_OBJECTS) $(liburl_parser_la_DEPENDENCIES) $(EXTRA_liburl_parser_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(am_liburl_parser_la_rpath) $(liburl_parser_la_OBJECTS) $(liburl_parser_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
-rm -f llhttp/src/*.$(OBJEXT)
-rm -f llhttp/src/*.lo
-rm -f neverbleed/*.$(OBJEXT)
-rm -f neverbleed/*.lo
-rm -f url-parser/*.$(OBJEXT)
-rm -f url-parser/*.lo
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@llhttp/src/$(DEPDIR)/libllhttp_la-api.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@llhttp/src/$(DEPDIR)/libllhttp_la-http.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@llhttp/src/$(DEPDIR)/libllhttp_la-llhttp.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@url-parser/$(DEPDIR)/url_parser.Plo@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
llhttp/src/libllhttp_la-api.lo: llhttp/src/api.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT llhttp/src/libllhttp_la-api.lo -MD -MP -MF llhttp/src/$(DEPDIR)/libllhttp_la-api.Tpo -c -o llhttp/src/libllhttp_la-api.lo `test -f 'llhttp/src/api.c' || echo '$(srcdir)/'`llhttp/src/api.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) llhttp/src/$(DEPDIR)/libllhttp_la-api.Tpo llhttp/src/$(DEPDIR)/libllhttp_la-api.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='llhttp/src/api.c' object='llhttp/src/libllhttp_la-api.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o llhttp/src/libllhttp_la-api.lo `test -f 'llhttp/src/api.c' || echo '$(srcdir)/'`llhttp/src/api.c
llhttp/src/libllhttp_la-http.lo: llhttp/src/http.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT llhttp/src/libllhttp_la-http.lo -MD -MP -MF llhttp/src/$(DEPDIR)/libllhttp_la-http.Tpo -c -o llhttp/src/libllhttp_la-http.lo `test -f 'llhttp/src/http.c' || echo '$(srcdir)/'`llhttp/src/http.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) llhttp/src/$(DEPDIR)/libllhttp_la-http.Tpo llhttp/src/$(DEPDIR)/libllhttp_la-http.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='llhttp/src/http.c' object='llhttp/src/libllhttp_la-http.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o llhttp/src/libllhttp_la-http.lo `test -f 'llhttp/src/http.c' || echo '$(srcdir)/'`llhttp/src/http.c
llhttp/src/libllhttp_la-llhttp.lo: llhttp/src/llhttp.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT llhttp/src/libllhttp_la-llhttp.lo -MD -MP -MF llhttp/src/$(DEPDIR)/libllhttp_la-llhttp.Tpo -c -o llhttp/src/libllhttp_la-llhttp.lo `test -f 'llhttp/src/llhttp.c' || echo '$(srcdir)/'`llhttp/src/llhttp.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) llhttp/src/$(DEPDIR)/libllhttp_la-llhttp.Tpo llhttp/src/$(DEPDIR)/libllhttp_la-llhttp.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='llhttp/src/llhttp.c' object='llhttp/src/libllhttp_la-llhttp.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o llhttp/src/libllhttp_la-llhttp.lo `test -f 'llhttp/src/llhttp.c' || echo '$(srcdir)/'`llhttp/src/llhttp.c
neverbleed/libneverbleed_la-neverbleed.lo: neverbleed/neverbleed.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libneverbleed_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT neverbleed/libneverbleed_la-neverbleed.lo -MD -MP -MF neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Tpo -c -o neverbleed/libneverbleed_la-neverbleed.lo `test -f 'neverbleed/neverbleed.c' || echo '$(srcdir)/'`neverbleed/neverbleed.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Tpo neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='neverbleed/neverbleed.c' object='neverbleed/libneverbleed_la-neverbleed.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libneverbleed_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o neverbleed/libneverbleed_la-neverbleed.lo `test -f 'neverbleed/neverbleed.c' || echo '$(srcdir)/'`neverbleed/neverbleed.c
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
-rm -rf llhttp/src/.libs llhttp/src/_libs
-rm -rf neverbleed/.libs neverbleed/_libs
-rm -rf url-parser/.libs url-parser/_libs
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
@ENABLE_THIRD_PARTY_FALSE@all-local:
@HAVE_MRUBY_FALSE@all-local:
all-am: Makefile $(LTLIBRARIES) all-local
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-rm -f llhttp/src/$(DEPDIR)/$(am__dirstamp)
-rm -f llhttp/src/$(am__dirstamp)
-rm -f neverbleed/$(DEPDIR)/$(am__dirstamp)
-rm -f neverbleed/$(am__dirstamp)
-rm -f url-parser/$(DEPDIR)/$(am__dirstamp)
-rm -f url-parser/$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
@ENABLE_THIRD_PARTY_FALSE@clean-local:
@HAVE_MRUBY_FALSE@clean-local:
clean: clean-am
clean-am: clean-generic clean-libtool clean-local \
clean-noinstLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -f llhttp/src/$(DEPDIR)/libllhttp_la-api.Plo
-rm -f llhttp/src/$(DEPDIR)/libllhttp_la-http.Plo
-rm -f llhttp/src/$(DEPDIR)/libllhttp_la-llhttp.Plo
-rm -f neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Plo
-rm -f url-parser/$(DEPDIR)/url_parser.Plo
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f llhttp/src/$(DEPDIR)/libllhttp_la-api.Plo
-rm -f llhttp/src/$(DEPDIR)/libllhttp_la-http.Plo
-rm -f llhttp/src/$(DEPDIR)/libllhttp_la-llhttp.Plo
-rm -f neverbleed/$(DEPDIR)/libneverbleed_la-neverbleed.Plo
-rm -f url-parser/$(DEPDIR)/url_parser.Plo
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am all-local am--depfiles check \
check-am clean clean-generic clean-libtool clean-local \
clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
@ENABLE_THIRD_PARTY_TRUE@@[email protected]: all-local clean mruby
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@mruby:
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ mkdir -p "${abs_builddir}/mruby/build"
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ diff "${srcdir}/build_config.rb" "${abs_builddir}/mruby/build/build_config.rb" >& /dev/null || \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ cp "${srcdir}/build_config.rb" "${abs_builddir}/mruby/build"
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ MRUBY_CONFIG="${abs_builddir}/mruby/build/build_config.rb" \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ BUILD_DIR="${abs_builddir}/mruby/build" \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ INSTALL_DIR="${abs_builddir}/mruby/build/install/bin" \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ CC="${CC}" CXX="$(firstword $(CXX))" LD="${LD}" \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ CFLAGS="${CPPFLAGS} ${CFLAGS}" \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ CXXFLAGS="$(wordlist 2, $(words $(CXX)), $(CXX)) ${CPPFLAGS} ${CXXFLAGS}" \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ LDFLAGS="${LDFLAGS}" \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ "${srcdir}/mruby/minirake" -f "${srcdir}/mruby/Rakefile"
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@all-local: mruby
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@clean-local:
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ [ ! -f "${abs_builddir}/mruby/build/build_config.rb" ] || \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ MRUBY_CONFIG="${abs_builddir}/mruby/build/build_config.rb" \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ BUILD_DIR="${abs_builddir}/mruby/build" \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ CC="${CC}" \
@ENABLE_THIRD_PARTY_TRUE@@HAVE_MRUBY_TRUE@ "${srcdir}/mruby/minirake" -f "${srcdir}/mruby/Rakefile" clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
+14
View File
@@ -0,0 +1,14 @@
MRuby::Build.new do |conf|
toolchain :clang if ENV['CC'].include? "clang"
toolchain :gcc if ENV['CC'].include? "gcc"
# C++ project needs this. Without this, mruby exception does not
# properly destory C++ object allocated on stack.
conf.enable_cxx_exception
conf.build_dir = ENV['BUILD_DIR']
# include the default GEMs
conf.gembox 'default'
conf.gem :core => 'mruby-eval'
end
+410
View File
@@ -0,0 +1,410 @@
#ifndef INCLUDE_LLHTTP_H_
#define INCLUDE_LLHTTP_H_
#define LLHTTP_VERSION_MAJOR 2
#define LLHTTP_VERSION_MINOR 2
#define LLHTTP_VERSION_PATCH 0
#ifndef LLHTTP_STRICT_MODE
# define LLHTTP_STRICT_MODE 0
#endif
#ifndef INCLUDE_LLHTTP_ITSELF_H_
#define INCLUDE_LLHTTP_ITSELF_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
typedef struct llhttp__internal_s llhttp__internal_t;
struct llhttp__internal_s {
int32_t _index;
void* _span_pos0;
void* _span_cb0;
int32_t error;
const char* reason;
const char* error_pos;
void* data;
void* _current;
uint64_t content_length;
uint8_t type;
uint8_t method;
uint8_t http_major;
uint8_t http_minor;
uint8_t header_state;
uint16_t flags;
uint8_t upgrade;
uint16_t status_code;
uint8_t finish;
void* settings;
};
int llhttp__internal_init(llhttp__internal_t* s);
int llhttp__internal_execute(llhttp__internal_t* s, const char* p, const char* endp);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* INCLUDE_LLHTTP_ITSELF_H_ */
#ifndef LLLLHTTP_C_HEADERS_
#define LLLLHTTP_C_HEADERS_
#ifdef __cplusplus
extern "C" {
#endif
enum llhttp_errno {
HPE_OK = 0,
HPE_INTERNAL = 1,
HPE_STRICT = 2,
HPE_LF_EXPECTED = 3,
HPE_UNEXPECTED_CONTENT_LENGTH = 4,
HPE_CLOSED_CONNECTION = 5,
HPE_INVALID_METHOD = 6,
HPE_INVALID_URL = 7,
HPE_INVALID_CONSTANT = 8,
HPE_INVALID_VERSION = 9,
HPE_INVALID_HEADER_TOKEN = 10,
HPE_INVALID_CONTENT_LENGTH = 11,
HPE_INVALID_CHUNK_SIZE = 12,
HPE_INVALID_STATUS = 13,
HPE_INVALID_EOF_STATE = 14,
HPE_INVALID_TRANSFER_ENCODING = 15,
HPE_CB_MESSAGE_BEGIN = 16,
HPE_CB_HEADERS_COMPLETE = 17,
HPE_CB_MESSAGE_COMPLETE = 18,
HPE_CB_CHUNK_HEADER = 19,
HPE_CB_CHUNK_COMPLETE = 20,
HPE_PAUSED = 21,
HPE_PAUSED_UPGRADE = 22,
HPE_USER = 23
};
typedef enum llhttp_errno llhttp_errno_t;
enum llhttp_flags {
F_CONNECTION_KEEP_ALIVE = 0x1,
F_CONNECTION_CLOSE = 0x2,
F_CONNECTION_UPGRADE = 0x4,
F_CHUNKED = 0x8,
F_UPGRADE = 0x10,
F_CONTENT_LENGTH = 0x20,
F_SKIPBODY = 0x40,
F_TRAILING = 0x80,
F_LENIENT = 0x100,
F_TRANSFER_ENCODING = 0x200
};
typedef enum llhttp_flags llhttp_flags_t;
enum llhttp_type {
HTTP_BOTH = 0,
HTTP_REQUEST = 1,
HTTP_RESPONSE = 2
};
typedef enum llhttp_type llhttp_type_t;
enum llhttp_finish {
HTTP_FINISH_SAFE = 0,
HTTP_FINISH_SAFE_WITH_CB = 1,
HTTP_FINISH_UNSAFE = 2
};
typedef enum llhttp_finish llhttp_finish_t;
enum llhttp_method {
HTTP_DELETE = 0,
HTTP_GET = 1,
HTTP_HEAD = 2,
HTTP_POST = 3,
HTTP_PUT = 4,
HTTP_CONNECT = 5,
HTTP_OPTIONS = 6,
HTTP_TRACE = 7,
HTTP_COPY = 8,
HTTP_LOCK = 9,
HTTP_MKCOL = 10,
HTTP_MOVE = 11,
HTTP_PROPFIND = 12,
HTTP_PROPPATCH = 13,
HTTP_SEARCH = 14,
HTTP_UNLOCK = 15,
HTTP_BIND = 16,
HTTP_REBIND = 17,
HTTP_UNBIND = 18,
HTTP_ACL = 19,
HTTP_REPORT = 20,
HTTP_MKACTIVITY = 21,
HTTP_CHECKOUT = 22,
HTTP_MERGE = 23,
HTTP_MSEARCH = 24,
HTTP_NOTIFY = 25,
HTTP_SUBSCRIBE = 26,
HTTP_UNSUBSCRIBE = 27,
HTTP_PATCH = 28,
HTTP_PURGE = 29,
HTTP_MKCALENDAR = 30,
HTTP_LINK = 31,
HTTP_UNLINK = 32,
HTTP_SOURCE = 33,
HTTP_PRI = 34,
HTTP_DESCRIBE = 35,
HTTP_ANNOUNCE = 36,
HTTP_SETUP = 37,
HTTP_PLAY = 38,
HTTP_PAUSE = 39,
HTTP_TEARDOWN = 40,
HTTP_GET_PARAMETER = 41,
HTTP_SET_PARAMETER = 42,
HTTP_REDIRECT = 43,
HTTP_RECORD = 44,
HTTP_FLUSH = 45
};
typedef enum llhttp_method llhttp_method_t;
#define HTTP_ERRNO_MAP(XX) \
XX(0, OK, OK) \
XX(1, INTERNAL, INTERNAL) \
XX(2, STRICT, STRICT) \
XX(3, LF_EXPECTED, LF_EXPECTED) \
XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \
XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \
XX(6, INVALID_METHOD, INVALID_METHOD) \
XX(7, INVALID_URL, INVALID_URL) \
XX(8, INVALID_CONSTANT, INVALID_CONSTANT) \
XX(9, INVALID_VERSION, INVALID_VERSION) \
XX(10, INVALID_HEADER_TOKEN, INVALID_HEADER_TOKEN) \
XX(11, INVALID_CONTENT_LENGTH, INVALID_CONTENT_LENGTH) \
XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \
XX(13, INVALID_STATUS, INVALID_STATUS) \
XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \
XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \
XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \
XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \
XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \
XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \
XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \
XX(21, PAUSED, PAUSED) \
XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \
XX(23, USER, USER) \
#define HTTP_METHOD_MAP(XX) \
XX(0, DELETE, DELETE) \
XX(1, GET, GET) \
XX(2, HEAD, HEAD) \
XX(3, POST, POST) \
XX(4, PUT, PUT) \
XX(5, CONNECT, CONNECT) \
XX(6, OPTIONS, OPTIONS) \
XX(7, TRACE, TRACE) \
XX(8, COPY, COPY) \
XX(9, LOCK, LOCK) \
XX(10, MKCOL, MKCOL) \
XX(11, MOVE, MOVE) \
XX(12, PROPFIND, PROPFIND) \
XX(13, PROPPATCH, PROPPATCH) \
XX(14, SEARCH, SEARCH) \
XX(15, UNLOCK, UNLOCK) \
XX(16, BIND, BIND) \
XX(17, REBIND, REBIND) \
XX(18, UNBIND, UNBIND) \
XX(19, ACL, ACL) \
XX(20, REPORT, REPORT) \
XX(21, MKACTIVITY, MKACTIVITY) \
XX(22, CHECKOUT, CHECKOUT) \
XX(23, MERGE, MERGE) \
XX(24, MSEARCH, M-SEARCH) \
XX(25, NOTIFY, NOTIFY) \
XX(26, SUBSCRIBE, SUBSCRIBE) \
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
XX(28, PATCH, PATCH) \
XX(29, PURGE, PURGE) \
XX(30, MKCALENDAR, MKCALENDAR) \
XX(31, LINK, LINK) \
XX(32, UNLINK, UNLINK) \
XX(33, SOURCE, SOURCE) \
XX(34, PRI, PRI) \
XX(35, DESCRIBE, DESCRIBE) \
XX(36, ANNOUNCE, ANNOUNCE) \
XX(37, SETUP, SETUP) \
XX(38, PLAY, PLAY) \
XX(39, PAUSE, PAUSE) \
XX(40, TEARDOWN, TEARDOWN) \
XX(41, GET_PARAMETER, GET_PARAMETER) \
XX(42, SET_PARAMETER, SET_PARAMETER) \
XX(43, REDIRECT, REDIRECT) \
XX(44, RECORD, RECORD) \
XX(45, FLUSH, FLUSH) \
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LLLLHTTP_C_HEADERS_ */
#ifndef INCLUDE_LLHTTP_API_H_
#define INCLUDE_LLHTTP_API_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
typedef llhttp__internal_t llhttp_t;
typedef struct llhttp_settings_s llhttp_settings_t;
typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length);
typedef int (*llhttp_cb)(llhttp_t*);
struct llhttp_settings_s {
/* Possible return values 0, -1, `HPE_PAUSED` */
llhttp_cb on_message_begin;
llhttp_data_cb on_url;
llhttp_data_cb on_status;
llhttp_data_cb on_header_field;
llhttp_data_cb on_header_value;
/* Possible return values:
* 0 - Proceed normally
* 1 - Assume that request/response has no body, and proceed to parsing the
* next message
* 2 - Assume absence of body (as above) and make `llhttp_execute()` return
* `HPE_PAUSED_UPGRADE`
* -1 - Error
* `HPE_PAUSED`
*/
llhttp_cb on_headers_complete;
llhttp_data_cb on_body;
/* Possible return values 0, -1, `HPE_PAUSED` */
llhttp_cb on_message_complete;
/* When on_chunk_header is called, the current chunk length is stored
* in parser->content_length.
* Possible return values 0, -1, `HPE_PAUSED`
*/
llhttp_cb on_chunk_header;
llhttp_cb on_chunk_complete;
};
/* Initialize the parser with specific type and user settings.
*
* NOTE: lifetime of `settings` has to be at least the same as the lifetime of
* the `parser` here. In practice, `settings` has to be either a static
* variable or be allocated with `malloc`, `new`, etc.
*/
void llhttp_init(llhttp_t* parser, llhttp_type_t type,
const llhttp_settings_t* settings);
/* Initialize the settings object */
void llhttp_settings_init(llhttp_settings_t* settings);
/* Parse full or partial request/response, invoking user callbacks along the
* way.
*
* If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing
* interrupts, and such errno is returned from `llhttp_execute()`. If
* `HPE_PAUSED` was used as a errno, the execution can be resumed with
* `llhttp_resume()` call.
*
* In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE`
* is returned after fully parsing the request/response. If the user wishes to
* continue parsing, they need to invoke `llhttp_resume_after_upgrade()`.
*
* NOTE: if this function ever returns a non-pause type error, it will continue
* to return the same error upon each successive call up until `llhttp_init()`
* is called.
*/
llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len);
/* This method should be called when the other side has no further bytes to
* send (e.g. shutdown of readable side of the TCP connection.)
*
* Requests without `Content-Length` and other messages might require treating
* all incoming bytes as the part of the body, up to the last byte of the
* connection. This method will invoke `on_message_complete()` callback if the
* request was terminated safely. Otherwise a error code would be returned.
*/
llhttp_errno_t llhttp_finish(llhttp_t* parser);
/* Returns `1` if the incoming message is parsed until the last byte, and has
* to be completed by calling `llhttp_finish()` on EOF
*/
int llhttp_message_needs_eof(const llhttp_t* parser);
/* Returns `1` if there might be any other messages following the last that was
* successfully parsed.
*/
int llhttp_should_keep_alive(const llhttp_t* parser);
/* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set
* appropriate error reason.
*
* Important: do not call this from user callbacks! User callbacks must return
* `HPE_PAUSED` if pausing is required.
*/
void llhttp_pause(llhttp_t* parser);
/* Might be called to resume the execution after the pause in user's callback.
* See `llhttp_execute()` above for details.
*
* Call this only if `llhttp_execute()` returns `HPE_PAUSED`.
*/
void llhttp_resume(llhttp_t* parser);
/* Might be called to resume the execution after the pause in user's callback.
* See `llhttp_execute()` above for details.
*
* Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE`
*/
void llhttp_resume_after_upgrade(llhttp_t* parser);
/* Returns the latest return error */
llhttp_errno_t llhttp_get_errno(const llhttp_t* parser);
/* Returns the verbal explanation of the latest returned error.
*
* Note: User callback should set error reason when returning the error. See
* `llhttp_set_error_reason()` for details.
*/
const char* llhttp_get_error_reason(const llhttp_t* parser);
/* Assign verbal description to the returned error. Must be called in user
* callbacks right before returning the errno.
*
* Note: `HPE_USER` error code might be useful in user callbacks.
*/
void llhttp_set_error_reason(llhttp_t* parser, const char* reason);
/* Returns the pointer to the last parsed byte before the returned error. The
* pointer is relative to the `data` argument of `llhttp_execute()`.
*
* Note: this method might be useful for counting the number of parsed bytes.
*/
const char* llhttp_get_error_pos(const llhttp_t* parser);
/* Returns textual name of error code */
const char* llhttp_errno_name(llhttp_errno_t err);
/* Returns textual name of HTTP method */
const char* llhttp_method_name(llhttp_method_t method);
/* Enables/disables lenient header value parsing (disabled by default).
*
* Lenient parsing disables header value token checks, extending llhttp's
* protocol support to highly non-compliant clients/server. No
* `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when
* lenient parsing is "on".
*
* **(USE AT YOUR OWN RISK)**
*/
void llhttp_set_lenient(llhttp_t* parser, int enabled);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* INCLUDE_LLHTTP_API_H_ */
#endif /* INCLUDE_LLHTTP_H_ */
+224
View File
@@ -0,0 +1,224 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "llhttp.h"
#define CALLBACK_MAYBE(PARSER, NAME, ...) \
do { \
llhttp_settings_t* settings; \
settings = (llhttp_settings_t*) (PARSER)->settings; \
if (settings == NULL || settings->NAME == NULL) { \
err = 0; \
break; \
} \
err = settings->NAME(__VA_ARGS__); \
} while (0)
void llhttp_init(llhttp_t* parser, llhttp_type_t type,
const llhttp_settings_t* settings) {
llhttp__internal_init(parser);
parser->type = type;
parser->settings = (void*) settings;
}
llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) {
return llhttp__internal_execute(parser, data, data + len);
}
void llhttp_settings_init(llhttp_settings_t* settings) {
memset(settings, 0, sizeof(*settings));
}
llhttp_errno_t llhttp_finish(llhttp_t* parser) {
int err;
/* We're in an error state. Don't bother doing anything. */
if (parser->error != 0) {
return 0;
}
switch (parser->finish) {
case HTTP_FINISH_SAFE_WITH_CB:
CALLBACK_MAYBE(parser, on_message_complete, parser);
if (err != HPE_OK) return err;
/* FALLTHROUGH */
case HTTP_FINISH_SAFE:
return HPE_OK;
case HTTP_FINISH_UNSAFE:
parser->reason = "Invalid EOF state";
return HPE_INVALID_EOF_STATE;
default:
abort();
}
}
void llhttp_pause(llhttp_t* parser) {
if (parser->error != HPE_OK) {
return;
}
parser->error = HPE_PAUSED;
parser->reason = "Paused";
}
void llhttp_resume(llhttp_t* parser) {
if (parser->error != HPE_PAUSED) {
return;
}
parser->error = 0;
}
void llhttp_resume_after_upgrade(llhttp_t* parser) {
if (parser->error != HPE_PAUSED_UPGRADE) {
return;
}
parser->error = 0;
}
llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) {
return parser->error;
}
const char* llhttp_get_error_reason(const llhttp_t* parser) {
return parser->reason;
}
void llhttp_set_error_reason(llhttp_t* parser, const char* reason) {
parser->reason = reason;
}
const char* llhttp_get_error_pos(const llhttp_t* parser) {
return parser->error_pos;
}
const char* llhttp_errno_name(llhttp_errno_t err) {
#define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return "HPE_" #NAME;
switch (err) {
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
default: abort();
}
#undef HTTP_ERRNO_GEN
}
const char* llhttp_method_name(llhttp_method_t method) {
#define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING;
switch (method) {
HTTP_METHOD_MAP(HTTP_METHOD_GEN)
default: abort();
}
#undef HTTP_METHOD_GEN
}
void llhttp_set_lenient(llhttp_t* parser, int enabled) {
if (enabled) {
parser->flags |= F_LENIENT;
} else {
parser->flags &= ~F_LENIENT;
}
}
/* Callbacks */
int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_message_begin, s);
return err;
}
int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_url, s, p, endp - p);
return err;
}
int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_status, s, p, endp - p);
return err;
}
int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_header_field, s, p, endp - p);
return err;
}
int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_header_value, s, p, endp - p);
return err;
}
int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_headers_complete, s);
return err;
}
int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_message_complete, s);
return err;
}
int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_body, s, p, endp - p);
return err;
}
int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_chunk_header, s);
return err;
}
int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_chunk_complete, s);
return err;
}
/* Private */
void llhttp__debug(llhttp_t* s, const char* p, const char* endp,
const char* msg) {
if (p == endp) {
fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type,
s->flags, msg);
} else {
fprintf(stderr, "p=%p type=%d flags=%02x next=%02x debug=%s\n", s,
s->type, s->flags, *p, msg);
}
}
+150
View File
@@ -0,0 +1,150 @@
#include <stdio.h>
#ifndef LLHTTP__TEST
# include "llhttp.h"
#else
# define llhttp_t llparse_t
#endif /* */
int llhttp_message_needs_eof(const llhttp_t* parser);
int llhttp_should_keep_alive(const llhttp_t* parser);
int llhttp__before_headers_complete(llhttp_t* parser, const char* p,
const char* endp) {
/* Set this here so that on_headers_complete() callbacks can see it */
if ((parser->flags & F_UPGRADE) &&
(parser->flags & F_CONNECTION_UPGRADE)) {
/* For responses, "Upgrade: foo" and "Connection: upgrade" are
* mandatory only when it is a 101 Switching Protocols response,
* otherwise it is purely informational, to announce support.
*/
parser->upgrade =
(parser->type == HTTP_REQUEST || parser->status_code == 101);
} else {
parser->upgrade = (parser->method == HTTP_CONNECT);
}
return 0;
}
/* Return values:
* 0 - No body, `restart`, message_complete
* 1 - CONNECT request, `restart`, message_complete, and pause
* 2 - chunk_size_start
* 3 - body_identity
* 4 - body_identity_eof
* 5 - invalid transfer-encoding for request
*/
int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
const char* endp) {
int hasBody;
hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;
if (parser->upgrade && (parser->method == HTTP_CONNECT ||
(parser->flags & F_SKIPBODY) || !hasBody)) {
/* Exit, the rest of the message is in a different protocol. */
return 1;
}
if (parser->flags & F_SKIPBODY) {
return 0;
} else if (parser->flags & F_CHUNKED) {
/* chunked encoding - ignore Content-Length header, prepare for a chunk */
return 2;
} else if (parser->flags & F_TRANSFER_ENCODING) {
if (parser->type == HTTP_REQUEST && (parser->flags & F_LENIENT) == 0) {
/* RFC 7230 3.3.3 */
/* If a Transfer-Encoding header field
* is present in a request and the chunked transfer coding is not
* the final encoding, the message body length cannot be determined
* reliably; the server MUST respond with the 400 (Bad Request)
* status code and then close the connection.
*/
return 5;
} else {
/* RFC 7230 3.3.3 */
/* If a Transfer-Encoding header field is present in a response and
* the chunked transfer coding is not the final encoding, the
* message body length is determined by reading the connection until
* it is closed by the server.
*/
return 4;
}
} else {
if (!(parser->flags & F_CONTENT_LENGTH)) {
if (!llhttp_message_needs_eof(parser)) {
/* Assume content-length 0 - read the next */
return 0;
} else {
/* Read body until EOF */
return 4;
}
} else if (parser->content_length == 0) {
/* Content-Length header given but zero: Content-Length: 0\r\n */
return 0;
} else {
/* Content-Length header given and non-zero */
return 3;
}
}
}
int llhttp__after_message_complete(llhttp_t* parser, const char* p,
const char* endp) {
int should_keep_alive;
should_keep_alive = llhttp_should_keep_alive(parser);
parser->finish = HTTP_FINISH_SAFE;
/* Keep `F_LENIENT` flag between messages, but reset every other flag */
parser->flags &= F_LENIENT;
/* NOTE: this is ignored in loose parsing mode */
return should_keep_alive;
}
int llhttp_message_needs_eof(const llhttp_t* parser) {
if (parser->type == HTTP_REQUEST) {
return 0;
}
/* See RFC 2616 section 4.4 */
if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
parser->status_code == 204 || /* No Content */
parser->status_code == 304 || /* Not Modified */
(parser->flags & F_SKIPBODY)) { /* response to a HEAD request */
return 0;
}
/* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */
if ((parser->flags & F_TRANSFER_ENCODING) &&
(parser->flags & F_CHUNKED) == 0) {
return 1;
}
if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) {
return 0;
}
return 1;
}
int llhttp_should_keep_alive(const llhttp_t* parser) {
if (parser->http_major > 0 && parser->http_minor > 0) {
/* HTTP/1.1 */
if (parser->flags & F_CONNECTION_CLOSE) {
return 0;
}
} else {
/* HTTP/1.0 or earlier */
if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
return 0;
}
}
return !llhttp_message_needs_eof(parser);
}
File diff suppressed because it is too large Load Diff
+45
View File
@@ -0,0 +1,45 @@
This is the (likely incomplete) list of "mruby developers".
If you submit a patch to mruby, please add your name to the end
of this list.
Yukihiro Matsumoto (Matz)
SCSK KYUSHU CORPORATION
Kyushu Institute of Technology
Network Applied Communication Laboratory, Inc.
Daniel Bovensiepen
Jon Maken
Bjorn De Meyer
Yuichiro MASUI
Masamitsu MURASE
Masaki Muranaka
Internet Initiative Japan Inc.
Tadashi FUKUZAWA
MATSUMOTO Ryosuke
Yasuhiro Matsumoto
Koji Yoshioka
Jun Hiroe
Narihiro Nakamura
Yuichi Nishiwaki
Tatsuhiko Kubo
Takeshi Watanabe
Yuki Kurihara
specified non-profit corporation mruby Forum
Kazuaki Tanaka
Hiromasa Ishii
Hiroshi Mimaki
Satoshi Odawara
Mitsubishi Electric Micro-Computer Application Software Co.,Ltd.
Ralph Desir(Mav7)
Hiroyuki Matsuzaki
Yuhei Okazaki
Manycolors, Inc.
Shota Nakano
Yuichi Osawa
Terence Lee
Zachary Scott
Tomasz Dąbrowski
Christopher Aue
Masahiro Wakame
YAMAMOTO Masaya
KOBAYASHI Shuji
RIZAL Reckordp
+75
View File
@@ -0,0 +1,75 @@
# How to contribute
mruby is an open-source project which is looking forward to each contribution.
## Your Pull Request
To make it easy to review and understand your change please keep the following
things in mind before submitting your pull request:
* Work on the latest possible state of **mruby/master**
* Create a branch which is dedicated to your change
* Test your changes before creating a pull request (```rake test```)
* If possible write a test case which confirms your change
* Don't mix several features or bug-fixes in one pull request
* Create a meaningful commit message
* Explain your change (i.e. with a link to the issue you are fixing)
* Use mrbgem to provide non ISO features (classes, modules and methods) unless
you have a special reason to implement them in the core
## Coding conventions
How to style your C and Ruby code which you want to submit.
### C code
The core part (parser, bytecode-interpreter, core-lib, etc.) of mruby is
written in the C programming language. Please note the following hints for your
C code:
#### Comply with C99 (ISO/IEC 9899:1999)
mruby should be highly portable to other systems and compilers. For this it is
recommended to keep your code as close as possible to the C99 standard
(http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf).
Although we target C99, we've heard some compilers in the embedded environment
still requires declarations of local variables to be at the beginning of a
scope. Until we confirm the situation has changed, we use the old-style
variable declaration.
Visual C++ is also an important target for mruby (supported version is 2013 or
later). For this reason features that are not supported by Visual C++ may not
be used (e.g. `%z` of `strftime()`).
NOTE: Old GCC requires `-std=gnu99` option to enable C99 support.
#### Reduce library dependencies to a minimum
The dependencies to libraries should be kept to an absolute minimum. This
increases the portability but makes it also easier to cut away parts of mruby
on-demand.
#### Don't use C++ style comments
/* This is the preferred comment style */
Use C++ style comments only for temporary comment e.g. commenting out some code lines.
#### Insert a break after the method return value:
int
main(void)
{
...
}
### Ruby code
Parts of the standard library of mruby are written in the Ruby programming
language itself. Please note the following hints for your Ruby code:
#### Comply with the Ruby standard (ISO/IEC 30170:2012)
mruby is currently targeting to execute Ruby code which complies to ISO/IEC
30170:2012 (http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579).
+2408
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
LEGAL NOTICE INFORMATION
------------------------
All the files in this distribution are covered under the MIT license
(see the file LICENSE) except some files mentioned below:
+20
View File
@@ -0,0 +1,20 @@
Copyright (c) 2020 mruby developers
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
+15
View File
@@ -0,0 +1,15 @@
# mruby is using Rake (http://rake.rubyforge.org) as a build tool.
RAKE = rake
all :
$(RAKE)
.PHONY : all
test : all
$(RAKE) test
.PHONY : test
clean :
$(RAKE) clean
.PHONY : clean
+13
View File
@@ -0,0 +1,13 @@
* NEWS
This document is a list of user visible feature changes made between
releases except for bug fixes.
Note that each entry is kept so brief that no reason behind or
reference information is supplied with. For a full list of changes
with all sufficient information, see the ChangeLog file.
** Information about first release v1.0.0
+105
View File
@@ -0,0 +1,105 @@
[![Build Status][build-status-img]][travis-ci]
## What is mruby
mruby is the lightweight implementation of the Ruby language complying to (part
of) the [ISO standard][ISO-standard]. Its syntax is Ruby 2.x compatible.
mruby can be linked and embedded within your application. We provide the
interpreter program "mruby" and the interactive mruby shell "mirb" as examples.
You can also compile Ruby programs into compiled byte code using the mruby
compiler "mrbc". All those tools reside in the "bin" directory. "mrbc" is
also able to generate compiled byte code in a C source file, see the "mrbtest"
program under the "test" directory for an example.
This achievement was sponsored by the Regional Innovation Creation R&D Programs
of the Ministry of Economy, Trade and Industry of Japan.
## How to get mruby
The stable version 2.1.2 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.1.2.zip](https://github.com/mruby/mruby/archive/2.1.2.zip)
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
The trunk of the mruby source tree can be checked out with the
following command:
$ git clone https://github.com/mruby/mruby.git
You can also install and compile mruby using [ruby-install](https://github.com/postmodern/ruby-install), [ruby-build](https://github.com/rbenv/ruby-build) or [rvm](https://github.com/rvm/rvm).
## mruby home-page
The URL of the mruby home-page is: https://mruby.org.
## Mailing list
We don't have a mailing list, but you can use [GitHub issues](https://github.com/mruby/mruby/issues).
## How to compile and install (mruby and gems)
See the [compile.md](https://github.com/mruby/mruby/blob/master/doc/guides/compile.md) file.
## Running Tests
To run the tests, execute the following from the project's root directory.
$ rake test
Note: `bison` bundled with MacOS is too old to compile `mruby`.
Try `brew install bison` and follow the instuction shown to update
the `$PATH` to compile `mruby`.
## Building documentation
There are two sets of documentation in mruby: the mruby API (generated by yard) and C API (Doxygen)
To build both of them, simply go
rake doc
You can also view them in your browser
rake view_api
rake view_capi
## How to customize mruby (mrbgems)
mruby contains a package manager called *mrbgems*. To create extensions
in C and/or Ruby you should create a *GEM*. For a documentation of how to
use mrbgems consult the file [mrbgems.md](https://github.com/mruby/mruby/blob/master/doc/guides/mrbgems.md).
For example code of how to use mrbgems look into the folder *examples/mrbgems/*.
## License
mruby is released under the [MIT License](https://github.com/mruby/mruby/blob/master/LICENSE).
## Note for License
mruby has chosen a MIT License due to its permissive license allowing
developers to target various environments such as embedded systems.
However, the license requires the display of the copyright notice and license
information in manuals for instance. Doing so for big projects can be
complicated or troublesome. This is why mruby has decided to display "mruby
developers" as the copyright name to make it simple conventionally.
In the future, mruby might ask you to distribute your new code
(that you will commit,) under the MIT License as a member of
"mruby developers" but contributors will keep their copyright.
(We did not intend for contributors to transfer or waive their copyrights,
Actual copyright holder name (contributors) will be listed in the AUTHORS
file.)
Please ask us if you want to distribute your code under another license.
## How to Contribute
See the [contribution guidelines][contribution-guidelines], and then send a pull
request to <http://github.com/mruby/mruby>. We consider you have granted
non-exclusive right to your contributed code under MIT license. If you want to
be named as one of mruby developers, please include an update to the AUTHORS
file in your pull request.
[ISO-standard]: http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579
[build-status-img]: https://travis-ci.org/mruby/mruby.svg?branch=master
[contribution-guidelines]: https://github.com/mruby/mruby/blob/master/CONTRIBUTING.md
[travis-ci]: https://travis-ci.org/mruby/mruby
+160
View File
@@ -0,0 +1,160 @@
# encoding: utf-8
# Build description.
# basic build file for mruby
MRUBY_ROOT = File.dirname(File.expand_path(__FILE__))
MRUBY_BUILD_HOST_IS_CYGWIN = RUBY_PLATFORM.include?('cygwin')
MRUBY_BUILD_HOST_IS_OPENBSD = RUBY_PLATFORM.include?('openbsd')
Rake.verbose(false) if Rake.verbose == Rake::DSL::DEFAULT
$LOAD_PATH << File.join(MRUBY_ROOT, "lib")
# load build systems
require "mruby-core-ext"
require "mruby/build"
# load configuration file
MRUBY_CONFIG = (ENV['MRUBY_CONFIG'] && ENV['MRUBY_CONFIG'] != '') ? ENV['MRUBY_CONFIG'] : "#{MRUBY_ROOT}/build_config.rb"
load MRUBY_CONFIG
# load basic rules
MRuby.each_target do |build|
build.define_rules
end
# load custom rules
load "#{MRUBY_ROOT}/src/mruby_core.rake"
load "#{MRUBY_ROOT}/mrblib/mrblib.rake"
load "#{MRUBY_ROOT}/tasks/mrbgems.rake"
load "#{MRUBY_ROOT}/tasks/libmruby.rake"
load "#{MRUBY_ROOT}/tasks/benchmark.rake"
load "#{MRUBY_ROOT}/tasks/gitlab.rake"
load "#{MRUBY_ROOT}/tasks/doc.rake"
def install_D(src, dst)
rm_f dst
mkdir_p File.dirname(dst)
cp src, dst
end
##############################
# generic build targets, rules
task :default => :all
bin_path = ENV['INSTALL_DIR'] || "#{MRUBY_ROOT}/bin"
depfiles = MRuby.targets['host'].bins.map do |bin|
install_path = MRuby.targets['host'].exefile("#{bin_path}/#{bin}")
source_path = MRuby.targets['host'].exefile("#{MRuby.targets['host'].build_dir}/bin/#{bin}")
file install_path => source_path do |t|
install_D t.prerequisites.first, t.name
end
install_path
end
MRuby.each_target do |target|
gems.map do |gem|
current_dir = gem.dir.relative_path_from(Dir.pwd)
relative_from_root = gem.dir.relative_path_from(MRUBY_ROOT)
current_build_dir = File.expand_path "#{build_dir}/#{relative_from_root}"
if current_build_dir !~ /^#{Regexp.escape(build_dir)}/
current_build_dir = "#{build_dir}/mrbgems/#{gem.name}"
end
gem.bins.each do |bin|
exec = exefile("#{build_dir}/bin/#{bin}")
objs = Dir.glob("#{current_dir}/tools/#{bin}/*.{c,cpp,cxx,cc}").map { |f| objfile(f.pathmap("#{current_build_dir}/tools/#{bin}/%n")) }
file exec => objs + target.libraries do |t|
gem_flags = gems.map { |g| g.linker.flags }
gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries }
gem_flags_after_libraries = gems.map { |g| g.linker.flags_after_libraries }
gem_libraries = gems.map { |g| g.linker.libraries }
gem_library_paths = gems.map { |g| g.linker.library_paths }
linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries, gem_flags_after_libraries
end
if target == MRuby.targets['host']
install_path = MRuby.targets['host'].exefile("#{bin_path}/#{bin}")
file install_path => exec do |t|
install_D t.prerequisites.first, t.name
end
depfiles += [ install_path ]
elsif target == MRuby.targets['host-debug']
unless MRuby.targets['host'].gems.map {|g| g.bins}.include?([bin])
install_path = MRuby.targets['host-debug'].exefile("#{bin_path}/#{bin}")
file install_path => exec do |t|
install_D t.prerequisites.first, t.name
end
depfiles += [ install_path ]
end
else
depfiles += [ exec ]
end
end
end
end
depfiles += MRuby.targets.map { |n, t|
t.libraries
}.flatten
depfiles += MRuby.targets.reject { |n, t| n == 'host' }.map { |n, t|
t.bins.map { |bin| t.exefile("#{t.build_dir}/bin/#{bin}") }
}.flatten
desc "build all targets, install (locally) in-repo"
task :all => depfiles do
puts
puts "Build summary:"
puts
MRuby.each_target do
print_build_summary
end
MRuby::Lockfile.write
end
desc "run all mruby tests"
task :test
MRuby.each_target do
if test_enabled?
t = :"test_#{self.name}"
task t => ["all"] do
run_test
end
task :test => t
end
if bintest_enabled?
t = :"bintest_#{self.name}"
task t => ["all"] do
run_bintest
end
task :test => t
end
end
desc "clean all built and in-repo installed artifacts"
task :clean do
MRuby.each_target do |t|
rm_rf t.build_dir
end
rm_f depfiles
puts "Cleaned up target build folder"
end
desc "clean everything!"
task :deep_clean => ["clean", "clean_doc"] do
MRuby.each_target do |t|
rm_rf t.gem_clone_dir
end
puts "Cleaned up mrbgems build folder"
end
+8
View File
@@ -0,0 +1,8 @@
Things to do (Things that are not done yet)
* special variables ($1,$2..)
* super in aliased methods
Things to improve (Done but things to fix)
* Make additions as they are noticed.
+39
View File
@@ -0,0 +1,39 @@
version: "{build}"
os: Visual Studio 2017
shallow_clone: true
environment:
matrix:
# Visual Studio 2017 64bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat
# Visual Studio 2017 32bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat
machine: x86
# Visual Studio 2015 64bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
machine: amd64
# Visual Studio 2015 32bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
machine: x86
# Visual Studio 2013 64bit
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat
machine: amd64
init:
- call "%visualcpp%" %machine%
# For using Rubyinstaller's Ruby 2.4 64bit
- set PATH=C:\Ruby24-x64\bin;%PATH%
- ruby --version
build_script:
- set MRUBY_CONFIG=appveyor_config.rb
- rake -m
- rake -E $stdout.sync=true test
+46
View File
@@ -0,0 +1,46 @@
def setup_option(conf)
conf.cc.flags[0].delete("/Zi") unless ENV['CFLAGS']
conf.cxx.flags[0].delete("/Zi") unless ENV['CFLAGS'] || ENV['CXXFLAGS']
conf.linker.flags << "/DEBUG:NONE" unless ENV['LDFLAGS']
end
MRuby::Build.new('full-debug') do |conf|
toolchain :visualcpp
enable_debug
# include all core GEMs
conf.gembox 'full-core'
conf.cc.defines += %w(MRB_GC_STRESS MRB_METHOD_CACHE MRB_ENABLE_DEBUG_HOOK)
setup_option(conf)
conf.enable_test
end
MRuby::Build.new do |conf|
toolchain :visualcpp
# include all core GEMs
conf.gembox 'full-core'
conf.compilers.each do |c|
c.defines += %w(MRB_GC_FIXED_ARENA)
end
setup_option(conf)
conf.enable_bintest
conf.enable_test
end
MRuby::Build.new('cxx_abi') do |conf|
toolchain :visualcpp
conf.gembox 'full-core'
conf.compilers.each do |c|
c.defines += %w(MRB_GC_FIXED_ARENA)
end
setup_option(conf)
conf.enable_bintest
conf.enable_test
enable_cxx_abi
build_mrbc_exec
end
+314
View File
@@ -0,0 +1,314 @@
# AO render benchmark
# Original program (C) Syoyo Fujita in Javascript (and other languages)
# https://code.google.com/p/aobench/
# Ruby(yarv2llvm) version by Hideki Miura
# mruby version by Hideki Miura
#
IMAGE_WIDTH = 64
IMAGE_HEIGHT = 64
NSUBSAMPLES = 2
NAO_SAMPLES = 8
module Rand
# Use xorshift
@@x = 123456789
@@y = 362436069
@@z = 521288629
@@w = 88675123
BNUM = 1 << 29
BNUMF = BNUM.to_f
def self.rand
x = @@x
t = x ^ ((x & 0xfffff) << 11)
w = @@w
@@x, @@y, @@z = @@y, @@z, w
w = @@w = (w ^ (w >> 19) ^ (t ^ (t >> 8)))
(w % BNUM) / BNUMF
end
end
class Vec
def initialize(x, y, z)
@x = x
@y = y
@z = z
end
def x=(v); @x = v; end
def y=(v); @y = v; end
def z=(v); @z = v; end
def x; @x; end
def y; @y; end
def z; @z; end
def vadd(b)
Vec.new(@x + b.x, @y + b.y, @z + b.z)
end
def vsub(b)
Vec.new(@x - b.x, @y - b.y, @z - b.z)
end
def vcross(b)
Vec.new(@y * b.z - @z * b.y,
@z * b.x - @x * b.z,
@x * b.y - @y * b.x)
end
def vdot(b)
r = @x * b.x + @y * b.y + @z * b.z
r
end
def vlength
Math.sqrt(@x * @x + @y * @y + @z * @z)
end
def vnormalize
len = vlength
v = Vec.new(@x, @y, @z)
if len > 1.0e-17
v.x = v.x / len
v.y = v.y / len
v.z = v.z / len
end
v
end
end
class Sphere
def initialize(center, radius)
@center = center
@radius = radius
end
def center; @center; end
def radius; @radius; end
def intersect(ray, isect)
rs = ray.org.vsub(@center)
b = rs.vdot(ray.dir)
c = rs.vdot(rs) - (@radius * @radius)
d = b * b - c
if d > 0.0
t = - b - Math.sqrt(d)
if t > 0.0 and t < isect.t
isect.t = t
isect.hit = true
isect.pl = Vec.new(ray.org.x + ray.dir.x * t,
ray.org.y + ray.dir.y * t,
ray.org.z + ray.dir.z * t)
n = isect.pl.vsub(@center)
isect.n = n.vnormalize
end
end
end
end
class Plane
def initialize(p, n)
@p = p
@n = n
end
def intersect(ray, isect)
d = -@p.vdot(@n)
v = ray.dir.vdot(@n)
v0 = v
if v < 0.0
v0 = -v
end
if v0 < 1.0e-17
return
end
t = -(ray.org.vdot(@n) + d) / v
if t > 0.0 and t < isect.t
isect.hit = true
isect.t = t
isect.n = @n
isect.pl = Vec.new(ray.org.x + t * ray.dir.x,
ray.org.y + t * ray.dir.y,
ray.org.z + t * ray.dir.z)
end
end
end
class Ray
def initialize(org, dir)
@org = org
@dir = dir
end
def org; @org; end
def org=(v); @org = v; end
def dir; @dir; end
def dir=(v); @dir = v; end
end
class Isect
def initialize
@t = 10000000.0
@hit = false
@pl = Vec.new(0.0, 0.0, 0.0)
@n = Vec.new(0.0, 0.0, 0.0)
end
def t; @t; end
def t=(v); @t = v; end
def hit; @hit; end
def hit=(v); @hit = v; end
def pl; @pl; end
def pl=(v); @pl = v; end
def n; @n; end
def n=(v); @n = v; end
end
def clamp(f)
i = f * 255.5
if i > 255.0
i = 255.0
end
if i < 0.0
i = 0.0
end
i.to_i
end
def otherBasis(basis, n)
basis[2] = Vec.new(n.x, n.y, n.z)
basis[1] = Vec.new(0.0, 0.0, 0.0)
if n.x < 0.6 and n.x > -0.6
basis[1].x = 1.0
elsif n.y < 0.6 and n.y > -0.6
basis[1].y = 1.0
elsif n.z < 0.6 and n.z > -0.6
basis[1].z = 1.0
else
basis[1].x = 1.0
end
basis[0] = basis[1].vcross(basis[2])
basis[0] = basis[0].vnormalize
basis[1] = basis[2].vcross(basis[0])
basis[1] = basis[1].vnormalize
end
class Scene
def initialize
@spheres = Array.new
@spheres[0] = Sphere.new(Vec.new(-2.0, 0.0, -3.5), 0.5)
@spheres[1] = Sphere.new(Vec.new(-0.5, 0.0, -3.0), 0.5)
@spheres[2] = Sphere.new(Vec.new(1.0, 0.0, -2.2), 0.5)
@plane = Plane.new(Vec.new(0.0, -0.5, 0.0), Vec.new(0.0, 1.0, 0.0))
end
def ambient_occlusion(isect)
basis = Array.new(3)
otherBasis(basis, isect.n)
ntheta = NAO_SAMPLES
nphi = NAO_SAMPLES
eps = 0.0001
occlusion = 0.0
p0 = Vec.new(isect.pl.x + eps * isect.n.x,
isect.pl.y + eps * isect.n.y,
isect.pl.z + eps * isect.n.z)
nphi.times do
ntheta.times do
r = Rand::rand
phi = 2.0 * 3.14159265 * Rand::rand
x = Math.cos(phi) * Math.sqrt(1.0 - r)
y = Math.sin(phi) * Math.sqrt(1.0 - r)
z = Math.sqrt(r)
rx = x * basis[0].x + y * basis[1].x + z * basis[2].x
ry = x * basis[0].y + y * basis[1].y + z * basis[2].y
rz = x * basis[0].z + y * basis[1].z + z * basis[2].z
raydir = Vec.new(rx, ry, rz)
ray = Ray.new(p0, raydir)
occisect = Isect.new
@spheres[0].intersect(ray, occisect)
@spheres[1].intersect(ray, occisect)
@spheres[2].intersect(ray, occisect)
@plane.intersect(ray, occisect)
if occisect.hit
occlusion = occlusion + 1.0
else
0.0
end
end
end
occlusion = (ntheta.to_f * nphi.to_f - occlusion) / (ntheta.to_f * nphi.to_f)
Vec.new(occlusion, occlusion, occlusion)
end
def render(w, h, nsubsamples)
cnt = 0
nsf = nsubsamples.to_f
h.times do |y|
w.times do |x|
rad = Vec.new(0.0, 0.0, 0.0)
# Subsmpling
nsubsamples.times do |v|
nsubsamples.times do |u|
cnt = cnt + 1
wf = w.to_f
hf = h.to_f
xf = x.to_f
yf = y.to_f
uf = u.to_f
vf = v.to_f
px = (xf + (uf / nsf) - (wf / 2.0)) / (wf / 2.0)
py = -(yf + (vf / nsf) - (hf / 2.0)) / (hf / 2.0)
eye = Vec.new(px, py, -1.0).vnormalize
ray = Ray.new(Vec.new(0.0, 0.0, 0.0), eye)
isect = Isect.new
@spheres[0].intersect(ray, isect)
@spheres[1].intersect(ray, isect)
@spheres[2].intersect(ray, isect)
@plane.intersect(ray, isect)
if isect.hit
col = ambient_occlusion(isect)
rad.x = rad.x + col.x
rad.y = rad.y + col.y
rad.z = rad.z + col.z
else
0.0
end
end
end
r = rad.x / (nsf * nsf)
g = rad.y / (nsf * nsf)
b = rad.z / (nsf * nsf)
printf("%c", clamp(r))
printf("%c", clamp(g))
printf("%c", clamp(b))
end
end
end
end
# File.open("ao.ppm", "w") do |fp|
printf("P6\n")
printf("%d %d\n", IMAGE_WIDTH, IMAGE_HEIGHT)
printf("255\n", IMAGE_WIDTH, IMAGE_HEIGHT)
Scene.new.render(IMAGE_WIDTH, IMAGE_HEIGHT, NSUBSAMPLES)
# Scene.new.render(256, 256, 2)
# end
File diff suppressed because one or more lines are too long
+7
View File
@@ -0,0 +1,7 @@
def fib n
return n if n < 2
fib(n-2) + fib(n-1)
end
puts fib(37)
+47
View File
@@ -0,0 +1,47 @@
#from http://www.bagley.org/~doug/shootout/bench/lists/lists.ruby
NUM = 300
SIZE = 10000
def test_lists()
# create a list of integers (Li1) from 1 to SIZE
li1 = (1..SIZE).to_a
# copy the list to li2 (not by individual items)
li2 = li1.dup
# remove each individual item from left side of li2 and
# append to right side of li3 (preserving order)
li3 = Array.new
while (not li2.empty?)
li3.push(li2.shift)
end
# li2 must now be empty
# remove each individual item from right side of li3 and
# append to right side of li2 (reversing list)
until li3.empty?
li2.push(li3.pop)
end
# li3 must now be empty
# reverse li1 in place
li1.reverse!
# check that first item is now SIZE
if li1[0] != SIZE
p "not SIZE"
0
else
# compare li1 and li2 for equality
if li1 != li2
return(0)
else
# return the length of the list
li1.length
end
end
end
i = 0
while i<NUM
i += 1
result = test_lists()
end
result
@@ -0,0 +1,28 @@
MRuby::Build.new do |conf|
toolchain :gcc
end
MRuby::Build.new('no_boxing') do |conf|
toolchain :gcc
conf.gembox 'default'
end
MRuby::Build.new('word_boxing') do |conf|
toolchain :gcc
conf.gembox 'default'
conf.compilers.each do |c|
c.defines += %w(MRB_WORD_BOXING)
end
end
MRuby::Build.new('nan_boxing') do |conf|
toolchain :gcc
conf.gembox 'default'
conf.compilers.each do |c|
c.defines += %w(MRB_NAN_BOXING)
end
end
+13
View File
@@ -0,0 +1,13 @@
MRuby::Build.new do |conf|
toolchain :gcc
end
MRuby::Build.new('gcc') do |conf|
toolchain :gcc
conf.gembox 'default'
end
MRuby::Build.new('clang') do |conf|
toolchain :clang
conf.gembox 'default'
end
+5
View File
@@ -0,0 +1,5 @@
set yrange [0:]
set terminal pngcairo font 'Sans, 8' lw 1 size 1400,1024
set xtics rotate by -45
set style histogram errorbars gap 2 lw 1
set style fill solid border -1
+152
View File
@@ -0,0 +1,152 @@
MRuby::Build.new do |conf|
# load specific toolchain settings
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
# Turn on `enable_debug` for better debugging
# enable_debug
# Use mrbgems
# conf.gem 'examples/mrbgems/ruby_extension_example'
# conf.gem 'examples/mrbgems/c_extension_example' do |g|
# g.cc.flags << '-g' # append cflags in this gem
# end
# conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
# conf.gem :core => 'mruby-eval'
# conf.gem :mgem => 'mruby-onig-regexp'
# conf.gem :github => 'mattn/mruby-onig-regexp'
# conf.gem :git => '[email protected]:mattn/mruby-onig-regexp.git', :branch => 'master', :options => '-v'
# include the default GEMs
conf.gembox 'default'
# C compiler settings
# conf.cc do |cc|
# cc.command = ENV['CC'] || 'gcc'
# cc.flags = [ENV['CFLAGS'] || %w()]
# cc.include_paths = ["#{root}/include"]
# cc.defines = %w()
# cc.option_include_path = %q[-I"%s"]
# cc.option_define = '-D%s'
# cc.compile_options = %Q[%{flags} -MMD -o "%{outfile}" -c "%{infile}"]
# end
# mrbc settings
# conf.mrbc do |mrbc|
# mrbc.compile_options = "-g -B%{funcname} -o-" # The -g option is required for line numbers
# end
# Linker settings
# conf.linker do |linker|
# linker.command = ENV['LD'] || 'gcc'
# linker.flags = [ENV['LDFLAGS'] || []]
# linker.flags_before_libraries = []
# linker.libraries = %w()
# linker.flags_after_libraries = []
# linker.library_paths = []
# linker.option_library = '-l%s'
# linker.option_library_path = '-L%s'
# linker.link_options = "%{flags} -o "%{outfile}" %{objs} %{libs}"
# end
# Archiver settings
# conf.archiver do |archiver|
# archiver.command = ENV['AR'] || 'ar'
# archiver.archive_options = 'rs "%{outfile}" %{objs}'
# end
# Parser generator settings
# conf.yacc do |yacc|
# yacc.command = ENV['YACC'] || 'bison'
# yacc.compile_options = %q[-o "%{outfile}" "%{infile}"]
# end
# gperf settings
# conf.gperf do |gperf|
# gperf.command = 'gperf'
# gperf.compile_options = %q[-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"]
# end
# file extensions
# conf.exts do |exts|
# exts.object = '.o'
# exts.executable = '' # '.exe' if Windows
# exts.library = '.a'
# end
# file separetor
# conf.file_separator = '/'
# bintest
# conf.enable_bintest
end
MRuby::Build.new('host-debug') do |conf|
# load specific toolchain settings
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
# include the default GEMs
conf.gembox 'default'
# C compiler settings
conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK)
# Generate mruby debugger command (require mruby-eval)
conf.gem :core => "mruby-bin-debugger"
# bintest
# conf.enable_bintest
end
MRuby::Build.new('test') do |conf|
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
conf.enable_bintest
conf.enable_test
conf.gembox 'default'
end
#MRuby::Build.new('bench') do |conf|
# # Gets set by the VS command prompts.
# if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
# toolchain :visualcpp
# else
# toolchain :gcc
# conf.cc.flags << '-O3'
# end
#
# conf.gembox 'default'
#end
# Define cross build settings
# MRuby::CrossBuild.new('32bit') do |conf|
# toolchain :gcc
#
# conf.cc.flags << "-m32"
# conf.linker.flags << "-m32"
#
# conf.build_mrbtest_lib_only
#
# conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
#
# conf.test_runner.command = 'env'
# end
+492
View File
@@ -0,0 +1,492 @@
# Compile
mruby uses Rake to compile and cross-compile all libraries and
binaries.
## Prerequisites
To compile mruby out of the source code you need the following tools:
* C Compiler (e.g. `gcc` or `clang`)
* Linker (e.g. `gcc` or `clang`)
* Archive utility (e.g. `ar`)
* Parser generator (e.g. `bison`)
* Ruby 2.0 or later (e.g. `ruby` or `jruby`)
Note that `bison` bundled with MacOS is too old to compile `mruby`.
Try `brew install bison` and follow the instuction shown to update
the `$PATH` to compile `mruby`.
Optional:
* GIT (to update mruby source and integrate mrbgems easier)
* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc)
* Assembler (to use GEMs which include \*.asm)
## Usage
Inside of the root directory of the mruby source a file exists
called *build_config.rb*. This file contains the build configuration
of mruby and looks like this for example:
```ruby
MRuby::Build.new do |conf|
toolchain :gcc
end
```
All tools necessary to compile mruby can be set or modified here. In case
you want to maintain an additional *build_config.rb* you can define a
customized path using the *$MRUBY_CONFIG* environment variable.
To compile just call `rake` inside of the mruby source root. To
generate and execute the test tools call `rake test`. To clean
all build files call `rake clean`. To see full command line on
build, call `rake -v`.
## Build Configuration
Inside of the *build_config.rb* the following options can be configured
based on your environment.
### Toolchains
The mruby build system already contains a set of toolchain templates which
configure the build environment for specific compiler infrastructures.
#### GCC
Toolchain configuration for the GNU C Compiler.
```ruby
toolchain :gcc
```
#### clang
Toolchain configuration for the LLVM C Compiler clang. Mainly equal to the
GCC toolchain.
```ruby
toolchain :clang
```
#### Visual Studio 2010, 2012 and 2013
Toolchain configuration for Visual Studio on Windows. If you use the
[Visual Studio Command Prompt](http://msdn.microsoft.com/en-us/library/ms229859\(v=vs.110\).aspx),
you normally do not have to specify this manually, since it gets automatically detected by our build process.
```ruby
toolchain :visualcpp
```
#### Android
Toolchain configuration for Android.
```ruby
toolchain :android
```
Requires the custom standalone Android NDK and the toolchain path
in `ANDROID_STANDALONE_TOOLCHAIN`.
### Binaries
It is possible to select which tools should be compiled during the compilation
process. The following tools can be selected:
* mruby (mruby interpreter)
* mirb (mruby interactive shell)
To select them declare conf.gem as follows:
```ruby
conf.gem "#{root}/mrbgems/mruby-bin-mruby"
conf.gem "#{root}/mrbgems/mruby-bin-mirb"
```
### File Separator
Some environments require a different file separator character. It is possible to
set the character via `conf.file_separator`.
```ruby
conf.file_separator = '/'
```
### C Compiler
Configuration of the C compiler binary, flags and include paths.
```ruby
conf.cc do |cc|
cc.command = ...
cc.flags = ...
cc.include_paths = ...
cc.defines = ...
cc.option_include_path = ...
cc.option_define = ...
cc.compile_options = ...
end
```
C Compiler has header searcher to detect installed library.
If you need a include path of header file use `search_header_path`:
```ruby
# Searches ```iconv.h```.
# If found it will return include path of the header file.
# Otherwise it will return nil .
fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h'
```
If you need a full file name of header file use `search_header`:
```ruby
# Searches ```iconv.h```.
# If found it will return full path of the header file.
# Otherwise it will return nil .
iconv_h = conf.cc.search_header 'iconv.h'
print "iconv.h found: #{iconv_h}\n"
```
Header searcher uses compiler's `include_paths` by default.
When you are using GCC toolchain (including clang toolchain since its base is gcc toolchain)
it will use compiler specific include paths too. (For example `/usr/local/include`, `/usr/include`)
If you need a special header search paths define a singleton method `header_search_paths` to C compiler:
```ruby
def conf.cc.header_search_paths
['/opt/local/include'] + include_paths
end
```
### Linker
Configuration of the Linker binary, flags and library paths.
```ruby
conf.linker do |linker|
linker.command = ...
linker.flags = ...
linker.flags_before_libraries = ...
linker.libraries = ...
linker.flags_after_libraries = ...
linker.library_paths = ....
linker.option_library = ...
linker.option_library_path = ...
linker.link_options = ...
end
```
### Archiver
Configuration of the Archiver binary and flags.
```ruby
conf.archiver do |archiver|
archiver.command = ...
archiver.archive_options = ...
end
```
### Parser Generator
Configuration of the Parser Generator binary and flags.
```ruby
conf.yacc do |yacc|
yacc.command = ...
yacc.compile_options = ...
end
```
### GPerf
Configuration of the GPerf binary and flags.
```ruby
conf.gperf do |gperf|
gperf.command = ...
gperf.compile_options = ...
end
```
### File Extensions
```ruby
conf.exts do |exts|
exts.object = ...
exts.executable = ...
exts.library = ...
end
```
### Mrbgems
Integrate GEMs in the build process.
```ruby
# Integrate GEM with additional configuration
conf.gem 'path/to/gem' do |g|
g.cc.flags << ...
end
# Integrate GEM without additional configuration
conf.gem 'path/to/another/gem'
```
See doc/mrbgems/README.md for more option about mrbgems.
### Mrbtest
Configuration Mrbtest build process.
If you want mrbtest.a only, You should set `conf.build_mrbtest_lib_only`
```ruby
conf.build_mrbtest_lib_only
```
### Bintest
Tests for mrbgem tools using CRuby.
To have bintests place \*.rb scripts to `bintest/` directory of mrbgems.
See `mruby-bin-*/bintest/*.rb` if you need examples.
If you want a temporary files use `tempfile` module of CRuby instead of `/tmp/`.
You can enable it with following:
```ruby
conf.enable_bintest
```
### C++ ABI
By default, mruby uses setjmp/longjmp to implement its
exceptions. But it doesn't release C++ stack object
correctly. To support mrbgems written in C++, mruby can be
configured to use C++ exception.
There are two levels of C++ exception handling. The one is
`enable_cxx_exception` that enables C++ exception, but
uses C ABI. The other is `enable_cxx_abi` where all
files are compiled by C++ compiler.
When you mix C++ code, C++ exception would be enabled automatically.
If you need to enable C++ exception explicitly add the following:
```ruby
conf.enable_cxx_exception
```
#### C++ exception disabling.
If your compiler does not support C++ and you want to ensure
you don't use mrbgem written in C++, you can explicitly disable
C++ exception, add following:
```ruby
conf.disable_cxx_exception
```
and you will get an error when you try to use C++ gem.
Note that it must be called before `enable_cxx_exception` or `gem` method.
### Debugging mode
To enable debugging mode add the following:
```ruby
conf.enable_debug
```
When debugging mode is enabled
* Macro `MRB_DEBUG` would be defined.
* Which means `mrb_assert()` macro is enabled.
* Debug information of irep would be generated by `mrbc`.
* Because `-g` flag would be added to `mrbc` runner.
* You can have better backtrace of mruby scripts with this.
## Cross-Compilation
mruby can also be cross-compiled from one platform to another. To
achieve this the *build_config.rb* needs to contain an instance of
`MRuby::CrossBuild`. This instance defines the compilation
tools and flags for the target platform. An example could look
like this:
```ruby
MRuby::CrossBuild.new('32bit') do |conf|
toolchain :gcc
conf.cc.flags << "-m32"
conf.linker.flags << "-m32"
end
```
All configuration options of `MRuby::Build` can also be used
in `MRuby::CrossBuild`.
### Mrbtest in Cross-Compilation
In cross compilation, you can run `mrbtest` on emulator if
you have it by changing configuration of test runner.
```ruby
conf.test_runner do |t|
t.command = ... # set emulator. this value must be non nil or false
t.flags = ... # set flags of emulator
def t.run(bin) # override `run` if you need to change the behavior of it
... # `bin` is the full path of mrbtest
end
end
```
## Build process
During the build process the directory *build* will be created in the
root directory. The structure of this directory will look like this:
+- build
|
+- host
|
+- bin <- Binaries (mirb, mrbc and mruby)
|
+- lib <- Libraries (libmruby.a and libmruby_core.a)
|
+- mrblib
|
+- src
|
+- test <- mrbtest tool
|
+- tools
|
+- mirb
|
+- mrbc
|
+- mruby
The compilation workflow will look like this:
* compile all files under *src* (object files will be stored
in *build/host/src*)
* generate parser grammar out of *src/parse.y* (generated
result will be stored in *build/host/src/y.tab.c*)
* compile *build/host/src/y.tab.c* to *build/host/src/y.tab.o*
* create *build/host/lib/libmruby_core.a* out of all object files (C only)
* create `build/host/bin/mrbc` by compiling *tools/mrbc/mrbc.c* and
linking with *build/host/lib/libmruby_core.a*
* create *build/host/mrblib/mrblib.c* by compiling all \*.rb files
under *mrblib* with `build/host/bin/mrbc`
* compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
* create *build/host/lib/libmruby.a* out of all object files (C and Ruby)
* create `build/host/bin/mruby` by compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
linking with *build/host/lib/libmruby.a*
* create `build/host/bin/mirb` by compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
linking with *build/host/lib/libmruby.a*
```
_____ _____ ______ ____ ____ _____ _____ ____
| CC |->|GEN |->|AR |->|CC |->|CC |->|AR |->|CC |->|CC |
| *.c | |y.tab| |core.a| |mrbc| |*.rb| |lib.a| |mruby| |mirb|
----- ----- ------ ---- ---- ----- ----- ----
```
### Cross-Compilation
In case of a cross-compilation to *i386* the *build* directory structure looks
like this:
+- build
|
+- host
| |
| +- bin <- Native Binaries
| |
| +- lib <- Native Libraries
| |
| +- mrblib
| |
| +- src
| |
| +- test <- Native mrbtest tool
| |
| +- tools
| |
| +- mirb
| |
| +- mrbc
| |
| +- mruby
+- i386
|
+- bin <- Cross-compiled Binaries
|
+- lib <- Cross-compiled Libraries
|
+- mrblib
|
+- src
|
+- test <- Cross-compiled mrbtest tool
|
+- tools
|
+- mirb
|
+- mrbc
|
+- mruby
An extra directory is created for the target platform. In case you
compile for *i386* a directory called *i386* is created under the
build directory.
The cross compilation workflow starts in the same way as the normal
compilation by compiling all *native* libraries and binaries.
Afterwards the cross compilation process proceeds like this:
* cross-compile all files under *src* (object files will be stored
in *build/i386/src*)
* generate parser grammar out of *src/parse.y* (generated
result will be stored in *build/i386/src/y.tab.c*)
* cross-compile *build/i386/src/y.tab.c* to *build/i386/src/y.tab.o*
* create *build/i386/mrblib/mrblib.c* by compiling all \*.rb files
under *mrblib* with the native `build/host/bin/mrbc`
* cross-compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
* create *build/i386/lib/libmruby.a* out of all object files (C and Ruby)
* create `build/i386/bin/mruby` by cross-compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
linking with *build/i386/lib/libmruby.a*
* create `build/i386/bin/mirb` by cross-compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
linking with *build/i386/lib/libmruby.a*
* create *build/i386/lib/libmruby_core.a* out of all object files (C only)
* create `build/i386/bin/mrbc` by cross-compiling *tools/mrbc/mrbc.c* and
linking with *build/i386/lib/libmruby_core.a*
```
_______________________________________________________________
| Native Compilation for Host System |
| _____ ______ _____ ____ ____ _____ |
| | CC | -> |AR | -> |GEN | -> |CC | -> |CC | -> |AR | |
| | *.c | |core.a| |y.tab| |mrbc| |*.rb| |lib.a| |
| ----- ------ ----- ---- ---- ----- |
---------------------------------------------------------------
||
\||/
\/
________________________________________________________________
| Cross Compilation for Target System |
| _____ _____ _____ ____ ______ _____ |
| | CC | -> |AR | -> |CC | -> |CC | -> |AR | -> |CC | |
| | *.c | |lib.a| |mruby| |mirb| |core.a| |mrbc | |
| ----- ----- ----- ---- ------ ----- |
----------------------------------------------------------------
```
## Build Configuration Examples
### Minimal Library
To build a minimal mruby library you need to use the Cross Compiling
feature due to the reason that there are functions (e.g. stdio) which
can't be disabled for the main build.
```ruby
MRuby::CrossBuild.new('Minimal') do |conf|
toolchain :gcc
conf.cc.defines = %w(MRB_DISABLE_STDIO)
conf.bins = []
end
```
This configuration defines a cross compile build called 'Minimal' which
is using the GCC and compiles for the host machine. It also disables
all usages of stdio and doesn't compile any binaries (e.g. mrbc).
## Test Environment
mruby's build process includes a test environment. In case you start the testing
of mruby, a native binary called `mrbtest` will be generated and executed.
This binary contains all test cases which are defined under *test/t*. In case
of a cross-compilation an additional cross-compiled *mrbtest* binary is
generated. You can copy this binary and run on your target system.
+370
View File
@@ -0,0 +1,370 @@
# How to Use the mruby Debugger
copyright (c) 2014 Specified Non-Profit Corporation mruby Forum
## 1. Summary
This file documents the mruby debugger ('mrdb') methods.
## 2 Debugging with mrdb
## 2.1 Building mrdb
The trunk of the mruby source tree, with the most recent mrdb, can be checked out with the following command:
```bash
$ git clone https://github.com/mruby/mruby.git
```
To run the `make` command:
```bash
$ cd mruby
$ make
```
By default, the `make` command will install the debugger files into mruby/bin.
You can add the path for mrdb on your host environment with the following command:
```bash
$ echo "export PATH=\$PATH:MRUBY_ROOT/bin" >> ~/.bashrc
$ source ~/.bashrc
```
`*MRUBY_ROOT` is the directory in which mruby source code will be installed.
To confirm mrdb was installed properly, run mrdb with the `--version` option:
```bash
$ mrdb --version
mruby 2.1.2 (2020-08-06)
```
## 2.2 Basic Operation
### 2.2.1 Debugging mruby Script Files (rb file) with mrdb
To invoke the mruby debugger, just type `mrdb`.
To specify the script file:
```bash
$ mrdb [option] file name
```
For example: Debugging sample.rb
```bash
$ mrdb sample.rb
```
You can execute the shell commands listed below:
|command|description|
|:-:|:--|
|run|execute programs|
|step|execute stepping|
|continue|execute continuing program|
|break|configure the breaking point|
|delete|deleting the breaking points|
|disable|disabling the breaking points|
|enable|enabling the breaking points|
|info breakpoints|showing list of the breaking points|
|print|evaluating and printing the values of the mruby expressions in the script|
|list|displaying the source cords|
|help|showing help|
|quit|terminating the mruby debugger|
### 2.2.2 Debugging mruby Binary Files (mrb file) with mrdb
You can debug the mruby binary files.
#### 2.2.2.1 Debugging the binary files
* notice
To debug mruby binary files, you need to compile mruby files with option `-g`.
```bash
$ mrbc -g sample.rb
```
You can debug the mruby binary files with following command and the option `-b`.
```bash
$ mrdb -b sample.mrb
```
Then you can execute all debugger shell commands.
#### Break Command
You can use any breakpoint to stop the program by specifying the line number and method name.
The breakpoint list will be displayed after you have set the breakpoint successfully.
Usage:
```
break [file:]linenum
b [file:]linenum
break [class:]method
b [class:]method
```
The breakpoint will be ordered in serial from 1.
The number, which was given to the deleted breakpoint, will never be given to another breakpoint again.
You can give multiple breakpoints to specified the line number and method.
Be ware that breakpoint command will not check the validity of the class name and method name.
You can get the current breakpoint information by the following options.
breakpoint breakpoint number : file name. line number
breakpoint breakpoint number : [class name,] method name
#### Continue Command
Usage:
```
continue [N]
c [N]
```
N: the next breakpoint number
When resuming the program, it will stop at breakpoint N (N-1 breakpoint will be ignored).
When you run the `continue` command without specifying N, the program will be stopped at the next breakpoint.
Example:
```
(foo.rb:1) continue 3
```
This will resume the program and stop it at the third breakpoint.
#### Delete Command
This will delete the specified breakpoint.
Usage:
```
delete [breakpoint-no]
d [breakpoint-no]
```
breakpoint-no: breakpoint number
Example:
```
(foo.rb:1) delete
```
This will delete all of the breakpoints.
```
(foo.rb:1) delete 1 3
```
This will delete the breakpoint at 1 and 3.
#### Disable Command
This will disable the specified breakpoint.
Usage:
```
disable [breakpoint-no]
dis [breakpoint-no]
```
reappointing: breakpoint number
Example:
```
(foo.rb:1) disable
```
Use `disable` if you would like to disable all of the breakpoints.
```
(foo.rb:1) disable 1 3
```
This will disable the breakpoints at 1 and 3.
#### Enable Command
This will enable the specified breakpoints.
Usage:
```
enable [breakpoint-no]
e [breakpoint-no]
```
breakpoint-no: breakpoint number
Example:
```
(foo.rb:1) enable
```
Enabling all breakpoints
```
(foo.rb:1) enable 1 3
```
Enabling the breakpoint 1 and 3
#### eval command
Evaluating the string as source code and printing the value.
Same as print command, please see print command.
#### help command
Displaying the help message.
Usage:
```
help [command]
h [command]
```
Typing `help` without any options will display the command list.
#### Info Breakpoints Command
Displaying the specified breakpoint information.
Usage:
```
info breakpoints [breakpoint-no]
i b [breakpoint-no]
```
breakpoint-no: breakpoint number
Typing "info breakpoints" without ant option will display all breakpoint information.
Example:
```
(sample.rb:1) info breakpoints
Num Type Enb What
1 breakpoint y at sample.rb:3 -> file name,line number
2 breakpoint n in Sample_class:sample_class_method -> [class:]method name
3 breakpoint y in sample_global_method
```
Displaying the specified breakpoint number:
```
(foo.rb:1) info breakpoints 1 3
Num Type Enb What
1 breakpoint y at sample.rb:3
3 breakpoint y in sample_global_method
```
#### List Command
To display the code of the source file.
Usage:
```
list [filename:]first[,last]
l [filename]:first[,last]
```
first: the opening row number
last : the closing row number
When you specify the `first`, but not the `last` option, you will receive 10 rows.
When you do not specify both the `first` and `last` options, you will receive the next 10 rows.
Example:
```
Specifying file name and first row number
sample.rb:1) list sample2.rb:5
```
Specifying the file name and the first and last row number:
```
(sample.rb:1) list sample2.rb:6,7
```
#### Print Command
Evaluating the string as source code and printing the value.
Usage:
```
print [expr]
p [expr]
```
expr: expression
The expression is mandatory.
The displayed expressions will be serially ordered from 1.
If an exception occurs, the exception information will be displayed and the debugging will be continued.
Example:
```
(sample.rb:1) print 1+2
$1 = 3
(sample.rb:1) print self
$2 = main
```
Below is the case of the exception:
```
(sample.rb:1) print (1+2
$1 = SyntaxError: line 1: syntax error, unexpected $end, expecting ')'
```
#### Quit Command
Quitting the debugger.
Usage:
```
quit
q
```
#### Run Command
Running the program and stopping at the first breakpoint.
Usage:
```
run
r
```
#### Step Command
This will run the program step by step.
When the method and the block are invoked, the program will be stop at the first row.
The program, which is developed in C, will be ignored.
+177
View File
@@ -0,0 +1,177 @@
# How to use `mrb_gc_arena_save()`/`mrb_gc_arena_restore()`/`mrb_gc_protect()`
_This is an English translation of [Matz's blog post][matz blog post]
written in Japanese._
_Some parts are updated to reflect recent changes._
[matz blog post]: http://www.rubyist.net/~matz/20130731.html
When you are extending mruby using C language, you may encounter
mysterious "arena overflow error" or memory leak or very slow
execution speed. This is an error indicating overflow of "GC arena"
implementing "conservative GC".
GC (garbage collector) must ensure that object is "alive", in other
words, that it is referenced by somewhere from program. This can be
determined by checking if the object can be directly or indirectly
referenced by root. The local variables, global variables and
constants etc are root.
If program execution is performed inside mruby VM, there is nothing to
worry about because GC can access all roots owned by VM.
The problem arises when executing C functions. The object referenced
by C variable is also "alive", but mruby GC cannot aware of this, so
it might mistakenly recognize the objects referenced by only C
variables as dead.
This can be a fatal bug if the GC tries to collect a live object.
In CRuby, we scan C stack area, and use C variable as root to check
whether object is alive or not. Of course, because we are accessing C
stack just as memory region, we never know it is an integer or a
pointer. We workaround this by assuming that if it looks like a
pointer, then assume it as a pointer. We call it "conservative".
By the way, CRuby's "conservative GC" has some problems.
The biggest problem is we have no way to access to the stack area in
portable way. Therefore, we cannot use this method if we'd like to
implement highly portable runtime, like mruby.
So we came up with an another plan to implement "conservative GC" in mruby.
Again, the problem is when an object which was created in C function, becomes
no longer referenced in the Ruby world, and cannot be treated as garbage.
In mruby, we recognize all objects created in C function are alive.
Then we have no problem such as confusing a live object as dead.
This means that because we cannot collect truly dead object, we may
lose efficiency, but as a trade-off the GC itself is highly portable.
We can say goodbye to the problem that GC deletes live objects due to
optimization which sometimes occurs in CRuby.
According to this idea, we have a table, called "GC arena", which
remembers objects created in C function.
The arena is stack structure, when C function execution is returned to mruby
VM, all objects registered in the arena are popped.
This works very well, but can cause another problem: "arena overflow error" or
memory leak.
As of this writing, mruby automatically extend arena to remember
objects (See `MRB_GC_FIXED_ARENA` and `MRB_GC_ARENA_SIZE` in
doc/guides/mrbconf.md).
If you create many objects in C functions, memory usage will increase, since
GC never kick in. This memory usage may look like memory leak, but will also
make execution slower as more memory will need to be allocated.
With the build time configuration, you can limit the maximum size of
arena (e.g., 100). Then if you create many objects, arena overflows,
thus you will get an "arena overflow error".
To workaround these problems, we have `mrb_gc_arena_save()` and
`mrb_gc_arena_restore()` functions.
`int mrb_gc_arena_save(mrb)` returns the current position of the stack
top of GC arena, and `void mrb_gc_arena_restore(mrb, idx)` sets the
stack top position to back to given `idx`.
We can use them like this:
```c
int arena_idx = mrb_gc_arena_save(mrb);
// ...create objects...
mrb_gc_arena_restore(mrb, arena_idx);
```
In mruby, C function calls are surrounded by this save/restore, but we
can further optimize memory usage by surrounding save/restore, and can
avoid creating arena overflow bugs.
Let's take a real example. Here is the source code of `Array#inspect`:
```c
static mrb_value
inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
{
mrb_int i;
mrb_value s, arystr;
char head[] = { '[' };
char sep[] = { ',', ' ' };
char tail[] = { ']' };
/* check recursive */
for(i=0; i<RARRAY_LEN(list); i++) {
if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) {
return mrb_str_new(mrb, "[...]", 5);
}
}
mrb_ary_push(mrb, list, ary);
arystr = mrb_str_new_capa(mrb, 64);
mrb_str_cat(mrb, arystr, head, sizeof(head));
for(i=0; i<RARRAY_LEN(ary); i++) {
int ai = mrb_gc_arena_save(mrb);
if (i > 0) {
mrb_str_cat(mrb, arystr, sep, sizeof(sep));
}
if (mrb_array_p(RARRAY_PTR(ary)[i])) {
s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list);
}
else {
s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]);
}
mrb_str_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
mrb_gc_arena_restore(mrb, ai);
}
mrb_str_cat(mrb, arystr, tail, sizeof(tail));
mrb_ary_pop(mrb, list);
return arystr;
}
```
This is a real example, so a little bit complicated, but bear with me.
The essence of `Array#inspect` is that after stringifying each element
of array using `inspect` method, we join them together so that we can
get `inspect` representation of the entire array.
After the `inspect` representation is created, we no longer require the
individual string representation. This means that we don't have to register
these temporal objects into GC arena.
Therefore, in order to keep the arena size small; the `ary_inspect()` function
will do the following:
* save the position of the stack top using `mrb_gc_arena_save()`.
* get `inspect` representation of each element.
* append it to the constructing entire `inspect` representation of array.
* restore stack top position using `mrb_gc_arena_restore()`.
Please note that the final `inspect` representation of entire array
was created before the call of `mrb_gc_arena_restore()`. Otherwise,
required temporal object may be deleted by GC.
We may have a usecase where after creating many temporal objects, we'd
like to keep some of them. In this case, we cannot use the same idea
in `ary_inspect()` like appending objects to existing one.
Instead, after `mrb_gc_arena_restore()`, we must re-register the objects we
want to keep in the arena using `mrb_gc_protect(mrb, obj)`.
Use `mrb_gc_protect()` with caution because it could also lead to an "arena
overflow error".
We must also mention that when `mrb_funcall` is called in top level, the return
value is also registered to GC arena, so repeated use of `mrb_funcall` may
eventually lead to an "arena overflow error".
Use `mrb_gc_arena_save()` and `mrb_gc_arena_restore()` or possible use of
`mrb_gc_protect()` to workaround this.
+181
View File
@@ -0,0 +1,181 @@
# mruby configuration macros.
## How to use these macros.
You can use mrbconfs with following ways:
* Write them in `mrbconf.h`.
* Using compiler flags is preferred when building a cross binaries or multiple mruby binaries
since it's easier to use different mrbconf per each `MRuby::Build`.
* Most flags can be enabled by just commenting in.
* Pass them as compiler flags.
* Make sure you pass the same flags to all compilers since some mrbconf(e.g., `MRB_GC_FIXED_ARENA`)
changes `struct` layout and cause memory access error when C and other language(e.g., C++) is mixed.
## stdio setting.
`MRB_DISABLE_STDIO`
* When defined `<stdio.h>` functions won't be used.
* Some features will be disabled when this is enabled:
* `mrb_irep` load/dump from/to file.
* Compiling mruby script from file.
* Printing features in **src/print.c**.
## Debug macros.
`MRB_ENABLE_DEBUG_HOOK`
* When defined code fetch hook and debug OP hook will be enabled.
* When using any of the hook set function pointer `code_fetch_hook` and/or `debug_op_hook` of `mrb_state`.
* Fetch hook will be called before any OP.
* Debug OP hook will be called when dispatching `OP_DEBUG`.
`MRB_DEBUG`
* When defined `mrb_assert*` macro will be defined with macros from `<assert.h>`.
* Could be enabled via `enable_debug` method of `MRuby::Build`.
## Stack configuration
`MRB_STACK_EXTEND_DOUBLING`
* If defined doubles the stack size when extending it.
* Else extends stack with `MRB_STACK_GROWTH`.
`MRB_STACK_GROWTH`
* Default value is `128`.
* Used in stack extending.
* Ignored when `MRB_STACK_EXTEND_DOUBLING` is defined.
`MRB_STACK_MAX`
* Default value is `0x40000 - MRB_STACK_GROWTH`.
* Raises `RuntimeError` when stack size exceeds this value.
## Primitive type configuration.
`MRB_USE_FLOAT`
* When defined single precision floating point type(C type `float`) is used as `mrb_float`.
* Else double precision floating point type(C type `double`) is used as `mrb_float`.
`MRB_WITHOUT_FLOAT`
* When defined removes floating point numbers from mruby.
* It makes mruby easier to handle in "Microcontroller without FPU" and "Kernel Space".
`MRB_INT32`
* When defined, or `MRB_INT64` are not defined on 32-bit CPU mode, `mrb_int` will be defined as `int32_t`.
* Conflicts with `MRB_INT64`.
`MRB_INT64`
* When defined, or `MRB_INT32` are not defined on 64-bit CPU mode, `mrb_int` will be defined as `int64_t`.
* Conflicts with `MRB_INT32`.
## Garbage collector configuration.
`MRB_GC_STRESS`
* When defined full GC is emitted per each `RBasic` allocation.
* Mainly used in memory manager debugging.
`MRB_GC_TURN_OFF_GENERATIONAL`
* When defined turns generational GC by default.
`MRB_GC_FIXED_ARENA`
* When defined used fixed size GC arena.
* Raises `RuntimeError` when this is defined and GC arena size exceeds `MRB_GC_ARENA_SIZE`.
* Useful tracking unnecessary mruby object allocation.
`MRB_GC_ARENA_SIZE`
* Default value is `100`.
* Ignored when `MRB_GC_FIXED_ARENA` isn't defined.
* Defines fixed GC arena size.
`MRB_HEAP_PAGE_SIZE`
* Defines value is `1024`.
* Specifies number of `RBasic` per each heap page.
## Memory pool configuration.
`POOL_ALIGNMENT`
* Default value is `4`.
* If you're allocating data types that requires alignment more than default value define the
largest value of required alignment.
`POOL_PAGE_SIZE`
* Default value is `16000`.
* Specifies page size of pool page.
* Smaller the value is increases memory overhead.
## State atexit configuration.
`MRB_FIXED_STATE_ATEXIT_STACK`
* If defined enables fixed size `mrb_state` atexit stack.
* Raises `RuntimeError` when `mrb_state_atexit` call count to same `mrb_state` exceeds
`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`'s value.
`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`
* Default value is `5`.
* If `MRB_FIXED_STATE_ATEXIT_STACK` isn't defined this macro is ignored.
## `mrb_value` configuration.
`MRB_ENDIAN_BIG`
* If defined compiles mruby for big endian machines.
* Used in `MRB_NAN_BOXING`.
* Some mrbgem use this mrbconf.
`MRB_NAN_BOXING`
* If defined represent `mrb_value` in boxed `double`.
* Conflicts with `MRB_USE_FLOAT` and `MRB_WITHOUT_FLOAT`.
`MRB_WORD_BOXING`
* If defined represent `mrb_value` as a word.
* If defined `Float` will be a mruby object with `RBasic`.
## Instance variable configuration.
`MRB_IV_SEGMENT_SIZE`
* Default value is `4`.
* Specifies size of each segment in segment list.
## Reduce heap memory configuration.
`MRB_USE_LINK_TIME_RO_DATA_P`
* Only available on ELF platforms.
* If you specify the address of a read-only section when creating a symbol or string, that string will be used as it is.
* Heap memory can be saved.
* Uses `__ehdr_start` and `__init_array_start`.
* It must be `__ehdr_start < data_addr < __init_array_start`.
`MRB_USE_CUSTOM_RO_DATA_P`
* Takes precedence over `MRB_USE_LINK_TIME_RO_DATA_P`.
* Please try if `MRB_USE_LINK_TIME_RO_DATA_P` is not available.
* The `mrb_ro_data_p()` function is implemented by the user in an arbitrary file.
* The prototype declaration is `mrb_bool mrb_ro_data_p(const char *ptr)`.
* Return `TRUE` if `ptr` is in read-only section, otherwise return `FALSE`.
## Other configuration.
`MRB_UTF8_STRING`
* Adds UTF-8 encoding support to character-oriented String instance methods.
* If it isn't defined, they only support the US-ASCII encoding.
`MRB_FUNCALL_ARGC_MAX`
* Default value is `16`.
* Specifies 4th argument(`argc`) max value of `mrb_funcall`.
* Raises `ArgumentError` when the `argc` argument is bigger then this value `mrb_funcall`.
`KHASH_DEFAULT_SIZE`
* Default value is `32`.
* Specifies default size of khash table bucket.
* Used in `kh_init_ ## name` function.
`MRB_STR_BUF_MIN_SIZE`
* Default value is `128`.
* Specifies initial capacity of `RString` created by `mrb_str_buf_new` function..
`MRB_METHOD_CACHE`
* Improve performance for method dispatch.
`MRB_METHOD_CACHE_SIZE`
* Default value is `128`.
* Ignored if `MRB_METHOD_CACHE` is not defined.
* Need to be the power of 2.
`MRB_METHOD_T_STRUCT`
* Use C struct to represent `mrb_method_t`
* No `MRB_METHOD_T_STRUCT` requires highest 2 bits of function pointers to be zero
* Define this macro on machines that use higher bits of pointers
`MRB_ENABLE_ALL_SYMBOLS`
* Make it available `Symbols.all_symbols` in `mrbgems/mruby-symbol-ext`
* Increase heap memory usage.
+350
View File
@@ -0,0 +1,350 @@
# mrbgems
mrbgems is a library manager to integrate C and Ruby extension in an easy and
standardised way into mruby.
## Usage
By default mrbgems is currently deactivated. As soon as you add a GEM to your
build configuration (i.e. *build_config.rb*), mrbgems will be activated and the
extension integrated.
To add a GEM into the *build_config.rb* add the following line for example:
```ruby
conf.gem '/path/to/your/gem/dir'
```
You can also use a relative path which would be relative from the mruby root:
```ruby
conf.gem 'examples/mrbgems/ruby_extension_example'
```
A remote GIT repository location for a GEM is also supported:
```ruby
conf.gem :git => 'https://github.com/masuidrive/mrbgems-example.git', :branch => 'master'
conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master'
conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master'
```
You can specify the sub directory of the repository with `:path` option:
```ruby
conf.gem github: 'mruby/mruby', path: 'mrbgems/mruby-socket'
```
To use mrbgem from [mgem-list](https://github.com/mruby/mgem-list) use `:mgem` option:
```ruby
conf.gem :mgem => 'mruby-yaml'
conf.gem :mgem => 'yaml' # 'mruby-' prefix could be omitted
```
For specifying commit hash to checkout use `:checksum_hash` option:
```ruby
conf.gem mgem: 'mruby-redis', checksum_hash: '3446d19fc4a3f9697b5ddbf2a904f301c42f2f4e'
```
If there is missing dependencies, mrbgem dependencies solver will reference
mrbgem from core or mgem-list.
To pull all gems from remote GIT repository on build, call ```rake -p```,
or ```rake --pull-gems```.
NOTE: `:bitbucket` option supports only git. Hg is unsupported in this version.
## GemBox
There are instances when you wish to add a collection of mrbgems into mruby at
once, or be able to substitute mrbgems based on configuration, without having to
add each gem to the *build_config.rb* file. A packaged collection of mrbgems
is called a GemBox. A GemBox is a file that contains a list of mrbgems to load
into mruby, in the same format as if you were adding them to *build_config.rb*
via `config.gem`, but wrapped in an `MRuby::GemBox` object. GemBoxes are
loaded into mruby via `config.gembox 'boxname'`.
Below we have created a GemBox containing *mruby-time* and *mrbgems-example*:
```ruby
MRuby::GemBox.new do |conf|
conf.gem "#{root}/mrbgems/mruby-time"
conf.gem :github => 'masuidrive/mrbgems-example'
end
```
As mentioned, the GemBox uses the same conventions as `MRuby::Build`. The GemBox
must be saved with a *.gembox* extension inside the *mrbgems* directory to to be
picked up by mruby.
To use this example GemBox, we save it as `custom.gembox` inside the *mrbgems*
directory in mruby, and add the following to our *build_config.rb* file inside
the build block:
```ruby
conf.gembox 'custom'
```
This will cause the *custom* GemBox to be read in during the build process,
adding *mruby-time* and *mrbgems-example* to the build.
If you want, you can put GemBox outside of mruby directory. In that case you must
specify an absolute path like below.
```ruby
conf.gembox "#{ENV["HOME"]}/mygemboxes/custom"
```
There are two GemBoxes that ship with mruby: [default](../../mrbgems/default.gembox)
and [full-core](../../mrbgems/full-core.gembox). The [default](../../mrbgems/default.gembox) GemBox
contains several core components of mruby, and [full-core](../../mrbgems/full-core.gembox)
contains every gem found in the *mrbgems* directory.
## GEM Structure
The maximal GEM structure looks like this:
+- GEM_NAME <- Name of GEM
|
+- include/ <- Header for Ruby extension (will exported)
|
+- mrblib/ <- Source for Ruby extension
|
+- src/ <- Source for C extension
|
+- test/ <- Test code (Ruby)
|
+- mrbgem.rake <- GEM Specification
|
+- README.md <- Readme for GEM
The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src*
contains C/C++ files to extend mruby. The folder *include* contains C/C++ header
files. The folder *test* contains C/C++ and pure Ruby files for testing purposes
which will be used by `mrbtest`. *mrbgem.rake* contains the specification
to compile C and Ruby files. *README.md* is a short description of your GEM.
## Build process
mrbgems expects a specification file called *mrbgem.rake* inside of your
GEM directory. A typical GEM specification could look like this for example:
```ruby
MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'Example mrbgem using C and ruby'
end
```
The mrbgems build process will use this specification to compile Object and Ruby
files. The compilation results will be added to *lib/libmruby.a*. This file exposes
the GEM functionality to tools like `mruby` and `mirb`.
The following properties can be set inside of your `MRuby::Gem::Specification` for
information purpose:
* `spec.license` or `spec.licenses` (A single license or a list of them under which this GEM is licensed)
* `spec.author` or `spec.authors` (Developer name or a list of them)
* `spec.version` (Current version)
* `spec.description` (Detailed description)
* `spec.summary`
* One line short description of mrbgem.
* Printed in build summary of rake when set.
* `spec.homepage` (Homepage)
* `spec.requirements` (External requirements as information for user)
The `license` and `author` properties are required in every GEM!
In case your GEM is depending on other GEMs please use
`spec.add_dependency(gem, *requirements[, default_get_info])` like:
```ruby
MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
# Add GEM dependency mruby-parser.
# The version must be between 1.0.0 and 1.5.2 .
spec.add_dependency('mruby-parser', '>= 1.0.0', '<= 1.5.2')
# Use any version of mruby-uv from github.
spec.add_dependency('mruby-uv', '>= 0.0.0', :github => 'mattn/mruby-uv')
# Use latest mruby-onig-regexp from github. (version requirements can be omitted)
spec.add_dependency('mruby-onig-regexp', :github => 'mattn/mruby-onig-regexp')
# You can add extra mgems active only on test
spec.add_test_dependency('mruby-process', :github => 'iij/mruby-process')
end
```
The version requirements and default gem information are optional.
Version requirement supports following operators:
* '=': is equal
* '!=': is not equal
* '>': is greater
* '<': is lesser
* '>=': is equal or greater
* '<=': is equal or lesser
* '~>': is equal or greater and is lesser than the next major version
* example 1: '~> 2.2.2' means '>= 2.2.2' and '< 2.3.0'
* example 2: '~> 2.2' means '>= 2.2.0' and '< 3.0.0'
When more than one version requirements is passed, the dependency must satisfy all of it.
You can have default gem to use as dependency when it's not defined in *build_config.rb*.
When the last argument of `add_dependency` call is `Hash`, it will be treated as default gem information.
Its format is same as argument of method `MRuby::Build#gem`, expect that it can't be treated as path gem location.
When a special version of dependency is required,
use `MRuby::Build#gem` in *build_config.rb* to override default gem.
If you have conflicting GEMs use the following method:
* `spec.add_conflict(gem, *requirements)`
* The `requirements` argument is same as in `add_dependency` method.
like following code:
```ruby
MRuby::Gem::Specification.new 'some-regexp-binding' do |spec|
spec.license = 'BSD'
spec.author = 'John Doe'
spec.add_conflict 'mruby-onig-regexp', '> 0.0.0'
spec.add_conflict 'mruby-hs-regexp'
spec.add_conflict 'mruby-pcre-regexp'
spec.add_conflict 'mruby-regexp-pcre'
end
```
In case your GEM has more complex build requirements you can use
the following options additionally inside of your GEM specification:
* `spec.cc.flags` (C compiler flags)
* `spec.cc.defines` (C compiler defines)
* `spec.cc.include_paths` (C compiler include paths)
* `spec.linker.flags` (Linker flags)
* `spec.linker.libraries` (Linker libraries)
* `spec.linker.library_paths` (Linker additional library path)
* `spec.bins` (Generate binary file)
* `spec.rbfiles` (Ruby files to compile)
* `spec.objs` (Object files to compile)
* `spec.test_rbfiles` (Ruby test files for integration into mrbtest)
* `spec.test_objs` (Object test files for integration into mrbtest)
* `spec.test_preload` (Initialization files for mrbtest)
You also can use `spec.mruby.cc` and `spec.mruby.linker` to add extra global parameters for compiler and linker.
### include_paths and dependency
Your GEM can export include paths to another GEMs that depends on your GEM.
By default, `/...absolute path.../{GEM_NAME}/include` will be exported.
So it is recommended not to put GEM's local header files on include/.
These exports are retroactive.
For example: when B depends to C and A depends to B, A will get include paths exported by C.
Exported include_paths are automatically appended to GEM local include_paths by rake.
You can use `spec.export_include_paths` accessor if you want more complex build.
## C Extension
mruby can be extended with C. This is possible by using the C API to
integrate C libraries into mruby.
### Preconditions
mrbgems expects that you have implemented a C method called
`mrb_YOURGEMNAME_gem_init(mrb_state)`. `YOURGEMNAME` will be replaced
by the name of your GEM. If you call your GEM *c_extension_example*, your
initialisation method could look like this:
```C
void
mrb_c_extension_example_gem_init(mrb_state* mrb) {
struct RClass *class_cextension = mrb_define_module(mrb, "CExtension");
mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE());
}
```
### Finalize
mrbgems expects that you have implemented a C method called
`mrb_YOURGEMNAME_gem_final(mrb_state)`. `YOURGEMNAME` will be replaced
by the name of your GEM. If you call your GEM *c_extension_example*, your
finalizer method could look like this:
```C
void
mrb_c_extension_example_gem_final(mrb_state* mrb) {
free(someone);
}
```
### Example
+- c_extension_example/
|
+- src/
| |
| +- example.c <- C extension source
|
+- test/
| |
| +- example.rb <- Test code for C extension
|
+- mrbgem.rake <- GEM specification
|
+- README.md
## Ruby Extension
mruby can be extended with pure Ruby. It is possible to override existing
classes or add new ones in this way. Put all Ruby files into the *mrblib*
folder.
### Pre-Conditions
none
### Example
+- ruby_extension_example/
|
+- mrblib/
| |
| +- example.rb <- Ruby extension source
|
+- test/
| |
| +- example.rb <- Test code for Ruby extension
|
+- mrbgem.rake <- GEM specification
|
+- README.md
## C and Ruby Extension
mruby can be extended with C and Ruby at the same time. It is possible to
override existing classes or add new ones in this way. Put all Ruby files
into the *mrblib* folder and all C files into the *src* folder.
mruby codes under *mrblib* directory would be executed after gem init C
function is called. Make sure *mruby script* depends on *C code* and
*C code* doesn't depend on *mruby script*.
### Pre-Conditions
See C and Ruby example.
### Example
+- c_and_ruby_extension_example/
|
+- mrblib/
| |
| +- example.rb <- Ruby extension source
|
+- src/
| |
| +- example.c <- C extension source
|
+- test/
| |
| +- example.rb <- Test code for C and Ruby extension
|
+- mrbgem.rake <- GEM specification
|
+- README.md
+299
View File
@@ -0,0 +1,299 @@
# Limitations and Differences
The philosophy of mruby is to be a lightweight implementation of
the Ruby ISO standard. These two objectives are partially contradicting.
Ruby is an expressive language with complex implementation details which
are difficult to implement in a lightweight manner. To cope with this,
limitations to the "Ruby Compatibility" are defined.
This document is collecting these limitations.
## Integrity
This document does not contain a complete list of limitations.
Please help to improve it by submitting your findings.
## `1/2` gives `0.5`
Since mruby does not have `Bignum`, bigger integers are represented
by `Float` numbers. To enhance interoperability between `Fixnum`
and `Float`, mruby provides `Float#upto` and other iterating
methods for the `Float` class. As a side effect, `1/2` gives `0.5`
not `0`.
## `Array` passed to `puts`
Passing an Array to `puts` results in different output.
```ruby
puts [1,2,3]
```
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
```
1
2
3
```
#### mruby [2.1.2 (2020-08-06)]
```
[1, 2, 3]
```
## `Kernel.raise` in rescue clause
`Kernel.raise` without arguments does not raise the current exception within
a rescue clause.
```ruby
begin
1 / 0
rescue
raise
end
```
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
`ZeroDivisionError` is raised.
#### mruby [2.1.2 (2020-08-06)]
No exception is raised.
## Fiber execution can't cross C function boundary
mruby's `Fiber` is implemented in a similar way to Lua's co-routine. This
results in the consequence that you can't switch context within C functions.
Only exception is `mrb_fiber_yield` at return.
## `Array` does not support instance variables
To reduce memory consumption `Array` does not support instance variables.
```ruby
class Liste < Array
def initialize(str = nil)
@feld = str
end
end
p Liste.new "foobar"
```
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
` [] `
#### mruby [2.1.2 (2020-08-06)]
`ArgumentError` is raised.
## Method visibility
For simplicity reasons no method visibility (public/private/protected) is
supported. Those methods are defined but they are dummy methods.
```ruby
class VisibleTest
def public_method; end
private
def private_method; end
end
p VisibleTest.new.respond_to?(:private_method, false)
p VisibleTest.new.respond_to?(:private_method, true)
```
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
```
false
true
```
#### mruby [2.1.2 (2020-08-06)]
```
true
true
```
### Visibility Declaration
The declaration form of following visibility methods are not implemented.
* `public`
* `private`
* `protected`
* `module_function`
Especially, `module_function` method is not dummy, but no declaration form.
```
module TestModule
module_function
def test_func
p 'test_func called'
end
test_func
end
p 'ok'
```
#### Ruby [ruby 2.5.5p157 (2019-03-15 revision 67260)]
```
ok
```
#### mruby [2.1.2 (2020-08-06)]
```
test.rb:8: undefined method 'test_func' (NoMethodError)
```
## `defined?`
The `defined?` keyword is considered too complex to be fully
implemented. It is recommended to use `const_defined?` and
other reflection methods instead.
```ruby
defined?(Foo)
```
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
```
nil
```
#### mruby [2.1.2 (2020-08-06)]
`NameError` is raised.
## `alias` on global variables
Aliasing a global variable works in CRuby but is not part
of the ISO standard.
```ruby
alias $a $__a__
```
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
` nil `
#### mruby [2.1.2 (2020-08-06)]
Syntax error
## Operator modification
An operator can't be overwritten by the user.
```ruby
class String
def +
end
end
'a' + 'b'
```
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
`ArgumentError` is raised.
The re-defined `+` operator does not accept any arguments.
#### mruby [2.1.2 (2020-08-06)]
` 'ab' `
Behavior of the operator wasn't changed.
## `Kernel#binding` is not supported
`Kernel#binding` method is not supported.
#### Ruby [ruby 2.5.1p57 (2018-03-29 revision 63029)]
```
$ ruby -e 'puts Proc.new {}.binding'
#<Binding:0x00000e9deabb9950>
```
#### mruby [2.1.2 (2020-08-06)]
```
$ ./bin/mruby -e 'puts Proc.new {}.binding'
trace (most recent call last):
[0] -e:1
-e:1: undefined method 'binding' (NoMethodError)
```
## Keyword arguments
mruby keyword arguments behave slightly different from CRuby 2.5
to make the behavior simpler and less confusing. Maybe in the
future, the simpler behavior will be adopted to CRuby as well.
#### Ruby [ruby 2.5.1p57 (2018-03-29 revision 63029)]
```
$ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
[[{"a"=>1}], {:b=>2}]
```
#### mruby [mruby 2.1.2]
```
$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
trace (most recent call last):
[0] -e:1
-e:1: keyword argument hash with non symbol keys (ArgumentError)
```
## Argument Destructuring
```ruby
def m(a,(b,c),d); p [a,b,c,d]; end
m(1,[2,3],4) # => [1,2,3,4]
```
Destructured arguments (`b` and `c` in above example) cannot be accessed
from the default expression of optional arguments and keyword arguments,
since actual assignment is done after the evaluation of those default
expressions. Thus:
```ruby
def f(a,(b,c),d=b)
p [a,b,c,d]
end
f(1,[2,3])
```
CRuby gives `[1,2,3,nil]`. mruby raises `NoMethodError` for `b`.
## `nil?` redefinition in conditional expressions
Redefinition of `nil?` is ignored in conditional expressions.
```ruby
a = "a"
def a.nil?
true
end
puts(a.nil? ? "truthy" : "falsy")
```
Ruby outputs `falsy`. mruby outputs `truthy`.
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

+140
View File
@@ -0,0 +1,140 @@
# The new bytecode
We will reimplement VM to use 8bit instruction code. By
bytecode, we mean real byte code. The whole purpose is
reducing the memory consumption of mruby VM.
# Instructions
Instructions are bytes. There can be 256 instructions. Currently we
have 94 instructions. Instructions can take 0 to 3 operands.
## operands
The size of operands can be either 8bits, 16bits or 24bits.
In the table.1 below, the second field describes the size (and
sign) of operands.
* B: 8bit
* S: 16bit
* sS: signed 16bit
* W: 24bit
First two byte operands may be extended to 16bit. When those byte
operands are bigger than 256, the instruction will be prefixed by
`OP_EXT1` (means 1st operand is 16bit) or `OP_EXT2` (means 2nd operand
is 16bit) or `OP_EXT3` (means 1st and 2nd operands are 16bit).
For instructions marked by `'`, `OP_EXT1` can be prefixed. For those
with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
## table.1 Instruction Table
| Instruction Name | Operand type | Semantics |
|------------------|--------------|--------------------------------------------------------|
| OP_NOP | - | no operation |
| OP_MOVE" | BB | R(a) = R(b) |
| OP_LOADL" | BB | R(a) = Pool(b) |
| OP_LOADI" | BB | R(a) = mrb_int(b) |
| OP_LOADINEG" | BB | R(a) = mrb_int(-b) |
| OP_LOADI__1' | B | R(a) = mrb_int(-1) |
| OP_LOADI_0' | B | R(a) = mrb_int(0) |
| OP_LOADI_1' | B | R(a) = mrb_int(1) |
| OP_LOADI_2' | B | R(a) = mrb_int(2) |
| OP_LOADI_3' | B | R(a) = mrb_int(3) |
| OP_LOADI_4' | B | R(a) = mrb_int(4) |
| OP_LOADI_5' | B | R(a) = mrb_int(5) |
| OP_LOADI_6' | B | R(a) = mrb_int(6) |
| OP_LOADI_7' | B | R(a) = mrb_int(7) |
| OP_LOADI16' | BsS | R(a) = mrb_int(b) |
| OP_LOADSYM" | BB | R(a) = Syms(b) |
| OP_LOADNIL' | B | R(a) = nil |
| OP_LOADSELF' | B | R(a) = self |
| OP_LOADT' | B | R(a) = true |
| OP_LOADF' | B | R(a) = false |
| OP_GETGV" | BB | R(a) = getglobal(Syms(b)) |
| OP_SETGV" | BB | setglobal(Syms(b), R(a)) |
| OP_GETSV" | BB | R(a) = Special[Syms(b)] |
| OP_SETSV" | BB | Special[Syms(b)] = R(a) |
| OP_GETIV" | BB | R(a) = ivget(Syms(b)) |
| OP_SETIV" | BB | ivset(Syms(b),R(a)) |
| OP_GETCV" | BB | R(a) = cvget(Syms(b)) |
| OP_SETCV" | BB | cvset(Syms(b),R(a)) |
| OP_GETCONST" | BB | R(a) = constget(Syms(b)) |
| OP_SETCONST" | BB | constset(Syms(b),R(a)) |
| OP_GETMCNST" | BB | R(a) = R(a)::Syms(b) |
| OP_SETMCNST" | BB | R(a+1)::Syms(b) = R(a) |
| OP_GETUPVAR" | BBB | R(a) = uvget(b,c) |
| OP_SETUPVAR" | BBB | uvset(b,c,R(a)) |
| OP_JMP | S | pc=a |
| OP_JMPIF' | BS | if R(a) pc=b |
| OP_JMPNOT' | BS | if !R(a) pc=b |
| OP_JMPNIL' | BS | if R(a)==nil pc=b |
| OP_ONERR | S | rescue_push(a) |
| OP_EXCEPT' | B | R(a) = exc |
| OP_RESCUE" | BB | R(b) = R(a).isa?(R(b)) |
| OP_POPERR' | B | a.times{rescue_pop()} |
| OP_RAISE' | B | raise(R(a)) |
| OP_EPUSH' | B | ensure_push(SEQ[a]) |
| OP_EPOP' | B | A.times{ensure_pop().call} |
| OP_SENDV" | BB | R(a) = call(R(a),Syms(b),*R(a+1)) |
| OP_SENDVB" | BB | R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2)) |
| OP_SEND" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) |
| OP_SENDB" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c),&R(a+c+1)) |
| OP_CALL | - | R(0) = self.call(frame.argc, frame.argv) |
| OP_SUPER" | BB | R(a) = super(R(a+1),... ,R(a+b+1)) |
| OP_ARGARY' | BS | R(a) = argument array (16=5:1:5:1:4) |
| OP_ENTER | W | arg setup according to flags (23=5:5:1:5:5:1:1) |
| OP_KEY_P" | BB | R(a) = kdict.key?(Syms(b)) |
| OP_KEYEND | - | raise unless kdict.empty? |
| OP_KARG" | BB | R(a) = kdict[Syms(b)]; kdict.delete(Syms(b)) |
| OP_RETURN' | B | return R(a) (normal) |
| OP_RETURN_BLK' | B | return R(a) (in-block return) |
| OP_BREAK' | B | break R(a) |
| OP_BLKPUSH' | BS | R(a) = block (16=5:1:5:1:4) |
| OP_ADD' | B | R(a) = R(a)+R(a+1) |
| OP_ADDI" | BB | R(a) = R(a)+mrb_int(b) |
| OP_SUB' | B | R(a) = R(a)-R(a+1) |
| OP_SUBI" | BB | R(a) = R(a)-mrb_int(b) |
| OP_MUL' | B | R(a) = R(a)*R(a+1) |
| OP_DIV' | B | R(a) = R(a)/R(a+1) |
| OP_EQ' | B | R(a) = R(a)==R(a+1) |
| OP_LT' | B | R(a) = R(a)<R(a+1) |
| OP_LE' | B | R(a) = R(a)<=R(a+1) |
| OP_GT' | B | R(a) = R(a)>R(a+1) |
| OP_GE' | B | R(a) = R(a)>=R(a+1) |
| OP_ARRAY" | BB | R(a) = ary_new(R(a),R(a+1)..R(a+b)) |
| OP_ARRAY2" | BBB | R(a) = ary_new(R(b),R(b+1)..R(b+c)) |
| OP_ARYCAT' | B | ary_cat(R(a),R(a+1)) |
| OP_ARYPUSH' | B | ary_push(R(a),R(a+1)) |
| OP_ARYDUP' | B | R(a) = ary_dup(R(a)) |
| OP_AREF" | BBB | R(a) = R(b)[c] |
| OP_ASET" | BBB | R(a)[c] = R(b) |
| OP_APOST" | BBB | *R(a),R(a+1)..R(a+c) = R(a)[b..] |
| OP_INTERN' | B | R(a) = intern(R(a)) |
| OP_STRING" | BB | R(a) = str_dup(Lit(b)) |
| OP_STRCAT' | B | str_cat(R(a),R(a+1)) |
| OP_HASH" | BB | R(a) = hash_new(R(a),R(a+1)..R(a+b)) |
| OP_HASHADD" | BB | R(a) = hash_push(R(a),R(a+1)..R(a+b)) |
| OP_HASHCAT' | B | R(a) = hash_cat(R(a),R(a+1)) |
| OP_LAMBDA" | BB | R(a) = lambda(SEQ[b],OP_L_LAMBDA) |
| OP_BLOCK" | BB | R(a) = lambda(SEQ[b],OP_L_BLOCK) |
| OP_METHOD" | BB | R(a) = lambda(SEQ[b],OP_L_METHOD) |
| OP_RANGE_INC' | B | R(a) = range_new(R(a),R(a+1),FALSE) |
| OP_RANGE_EXC' | B | R(a) = range_new(R(a),R(a+1),TRUE) |
| OP_OCLASS' | B | R(a) = ::Object |
| OP_CLASS" | BB | R(a) = newclass(R(a),Syms(b),R(a+1)) |
| OP_MODULE" | BB | R(a) = newmodule(R(a),Syms(b)) |
| OP_EXEC" | BB | R(a) = blockexec(R(a),SEQ[b]) |
| OP_DEF" | BB | R(a).newmethod(Syms(b),R(a+1)) |
| OP_ALIAS" | BB | alias_method(target_class,Syms(a),Syms(b)) |
| OP_UNDEF' | B | undef_method(target_class,Syms(a)) |
| OP_SCLASS' | B | R(a) = R(a).singleton_class |
| OP_TCLASS' | B | R(a) = target_class |
| OP_DEBUG" | BBB | print a,b,c |
| OP_ERR' | B | raise(LocalJumpError, Lit(a)) |
| OP_EXT1 | - | make 1st operand 16bit |
| OP_EXT2 | - | make 2nd operand 16bit |
| OP_EXT3 | - | make 1st and 2nd operands 16bit |
| OP_STOP | - | stop VM |
|------------------|--------------|--------------------------------------------------------|
@@ -0,0 +1,4 @@
C and Ruby Extension Example
=========
This is an example gem which implements a C and Ruby extension.
@@ -0,0 +1,23 @@
MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
# Add compile flags
# spec.cc.flags << ''
# Add cflags to all
# spec.mruby.cc.flags << '-g'
# Add libraries
# spec.linker.libraries << 'external_lib'
# Default build files
# spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb")
# spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
# spec.test_rbfiles = Dir.glob("#{dir}/test/*.rb")
# spec.test_objs = Dir.glob("#{dir}/test/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
# spec.test_preload = 'test/assert.rb'
# Values accessible as TEST_ARGS inside test scripts
# spec.test_args = {'tmp_dir' => Dir::tmpdir}
end
@@ -0,0 +1,5 @@
module CRubyExtension
def CRubyExtension.ruby_method
puts "A Ruby Extension"
end
end
@@ -0,0 +1,20 @@
#include <mruby.h>
#include <stdio.h>
static mrb_value
mrb_c_method(mrb_state *mrb, mrb_value self)
{
puts("A C Extension");
return self;
}
void
mrb_c_and_ruby_extension_example_gem_init(mrb_state* mrb) {
struct RClass *class_cextension = mrb_define_module(mrb, "CRubyExtension");
mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE());
}
void
mrb_c_and_ruby_extension_example_gem_final(mrb_state* mrb) {
/* finalizer */
}
@@ -0,0 +1,7 @@
assert('C and Ruby Extension Example 1') do
CRubyExtension.respond_to? :c_method
end
assert('C and Ruby Extension Example 2') do
CRubyExtension.respond_to? :ruby_method
end
@@ -0,0 +1,4 @@
C Extension Example
=========
This is an example gem which implements a C extension.
@@ -0,0 +1,23 @@
MRuby::Gem::Specification.new('c_extension_example') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
# Add compile flags
# spec.cc.flags << '-g'
# Add cflags to all
# spec.mruby.cc.flags << '-g'
# Add libraries
# spec.linker.libraries << 'external_lib'
# Default build files
# spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb")
# spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
# spec.test_rbfiles = Dir.glob("#{dir}/test/*.rb")
# spec.test_objs = Dir.glob("#{dir}/test/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
# spec.test_preload = 'test/assert.rb'
# Values accessible as TEST_ARGS inside test scripts
# spec.test_args = {'tmp_dir' => Dir::tmpdir}
end
@@ -0,0 +1,20 @@
#include <mruby.h>
#include <stdio.h>
static mrb_value
mrb_c_method(mrb_state *mrb, mrb_value self)
{
puts("A C Extension");
return self;
}
void
mrb_c_extension_example_gem_init(mrb_state* mrb) {
struct RClass *class_cextension = mrb_define_module(mrb, "CExtension");
mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE());
}
void
mrb_c_extension_example_gem_final(mrb_state* mrb) {
/* finalizer */
}
@@ -0,0 +1,7 @@
#include <mruby.h>
void
mrb_c_extension_example_gem_test(mrb_state *mrb)
{
/* test initializer in C */
}
@@ -0,0 +1,3 @@
assert('C Extension Example') do
CExtension.respond_to? :c_method
end
@@ -0,0 +1,4 @@
Pure Ruby Extension Example
=========
This is an example gem which implements a pure Ruby extension.
@@ -0,0 +1,25 @@
MRuby::Gem::Specification.new('ruby_extension_example') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
# Add compile flags
# spec.cc.flags << ''
# Add cflags to all
# spec.mruby.cc.flags << '-g'
# Add libraries
# spec.linker.libraries << 'external_lib'
spec.add_dependency('mruby-print', :core => 'mruby-print')
# Default build files
# spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb")
# spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
# spec.test_rbfiles = Dir.glob("#{dir}/test/*.rb")
# spec.test_objs = Dir.glob("#{dir}/test/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
# spec.test_preload = 'test/assert.rb'
# Values accessible as TEST_ARGS inside test scripts
# spec.test_args = {'tmp_dir' => Dir::tmpdir}
end
@@ -0,0 +1,5 @@
class RubyExtension
def RubyExtension.ruby_method
puts "A Ruby Extension"
end
end
@@ -0,0 +1,3 @@
assert('Ruby Extension Example') do
RubyExtension.respond_to? :ruby_method
end
@@ -0,0 +1,90 @@
MRuby::Build.new do |conf|
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
# include the default GEMs
conf.gembox 'default'
end
# Cross Compiling configuration for Arduino Due
# http://arduino.cc/en/Main/ArduinoBoardDue
#
# Requires Arduino IDE >= 1.5
MRuby::CrossBuild.new("ArduinoDue") do |conf|
toolchain :gcc
# Mac OS X, Arduino IDE <= 1.5.6
# ARDUINO_PATH = '/Applications/Arduino.app/Contents/Resources/Java'
# Mac OS X, Arduino IDE >= 1.5.7
# ARDUINO_PATH = '/Applications/Arduino.app/Contents/Java'
# GNU Linux
ARDUINO_PATH = '/opt/arduino'
# Arduino IDE <= 1.5.6
BIN_PATH = "#{ARDUINO_PATH}/hardware/tools/g++_arm_none_eabi/bin"
# Arduino IDE >= 1.5.7
# BIN_PATH = "#{ARDUINO_PATH}/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin"
SAM_PATH = "#{ARDUINO_PATH}/hardware/arduino/sam"
TARGET_PATH = "#{SAM_PATH}/variants/arduino_due_x"
conf.cc do |cc|
cc.command = "#{BIN_PATH}/arm-none-eabi-gcc"
cc.include_paths << ["#{SAM_PATH}/system/libsam", "#{SAM_PATH}/system/CMSIS/CMSIS/Include/",
"#{SAM_PATH}/system/CMSIS/Device/ATMEL/",
"#{SAM_PATH}/cores/arduino", "#{SAM_PATH}/libraries","#{TARGET_PATH}"]
cc.flags = %w(-g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500
-Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=156 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM
-D__SAM3X8E__ -mthumb -DUSB_PID=0x003e -DUSB_VID=0x2341 -DUSBCON -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Due")
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
#configuration for low memory environment
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
cc.defines << %w(MRB_GC_STRESS)
#cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio.
#cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
end
conf.cxx do |cxx|
cxx.command = conf.cc.command.dup
cxx.include_paths = conf.cc.include_paths.dup
cxx.flags = conf.cc.flags.dup
cxx.flags << %w(-fno-rtti -fno-exceptions)
cxx.defines = conf.cc.defines.dup
cxx.compile_options = conf.cc.compile_options.dup
end
conf.archiver do |archiver|
archiver.command = "#{BIN_PATH}/arm-none-eabi-ar"
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
#no executables
conf.bins = []
#do not build executable test
conf.build_mrbtest_lib_only
#disable C++ exception
conf.disable_cxx_exception
#gems from core
conf.gem :core => "mruby-print"
conf.gem :core => "mruby-math"
conf.gem :core => "mruby-enum-ext"
#light-weight regular expression
conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master"
#Arduino API
#conf.gem :github =>"kyab/mruby-arduino", :branch => "master"
end
@@ -0,0 +1,69 @@
# Cross-compiling setup for Intel Edison (poky linux) platform
# Get SDK from here: https://software.intel.com/en-us/iot/hardware/edison/downloads
# REMEMBER to check and update the SDK root in the constant POKY_EDISON_PATH
MRuby::Build.new do |conf|
toolchain :gcc
conf.gembox 'default'
conf.cc.defines = %w(ENABLE_READLINE)
conf.gembox 'default'
#lightweight regular expression
conf.gem :github => "pbosetti/mruby-hs-regexp", :branch => "master"
end
# Define cross build settings
MRuby::CrossBuild.new('core2-32-poky-linux') do |conf|
toolchain :gcc
# Mac OS X
#
POKY_EDISON_PATH = '/opt/poky-edison/1.7.2'
POKY_EDISON_SYSROOT = "#{POKY_EDISON_PATH}/sysroots/core2-32-poky-linux"
POKY_EDISON_X86_PATH = "#{POKY_EDISON_PATH}/sysroots/i386-pokysdk-darwin"
POKY_EDISON_BIN_PATH = "#{POKY_EDISON_X86_PATH}/usr/bin/i586-poky-linux"
conf.cc do |cc|
cc.command = "#{POKY_EDISON_BIN_PATH}/i586-poky-linux-gcc"
cc.include_paths << ["#{POKY_EDISON_SYSROOT}/usr/include", "#{POKY_EDISON_X86_PATH}/usr/include"]
cc.flags = %w(-m32 -march=core2 -mtune=core2 -msse3 -mfpmath=sse -mstackrealign -fno-omit-frame-pointer)
cc.flags << %w(-O2 -pipe -g -feliminate-unused-debug-types)
cc.flags << "--sysroot=#{POKY_EDISON_SYSROOT}"
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
cc.defines = %w(ENABLE_READLINE)
end
conf.cxx do |cxx|
cxx.command = "#{POKY_EDISON_BIN_PATH}/i586-poky-linux-g++"
cxx.include_paths = conf.cc.include_paths.dup
cxx.include_paths << ["#{POKY_EDISON_SYSROOT}/usr/include/c++/4.9.1"]
cxx.flags = conf.cc.flags.dup
cxx.defines = conf.cc.defines.dup
cxx.compile_options = conf.cc.compile_options.dup
end
conf.archiver do |archiver|
archiver.command = "#{POKY_EDISON_BIN_PATH}/i586-poky-linux-ar"
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
conf.linker do |linker|
linker.command = "#{POKY_EDISON_BIN_PATH}/i586-poky-linux-g++"
linker.flags = %w(-m32 -march=i586)
linker.flags << "--sysroot=#{POKY_EDISON_SYSROOT}"
linker.flags << %w(-O1)
linker.libraries = %w(m pthread)
end
#do not build executable test
conf.build_mrbtest_lib_only
conf.gembox 'default'
#lightweight regular expression
conf.gem :github => "pbosetti/mruby-hs-regexp", :branch => "master"
end
@@ -0,0 +1,106 @@
MRuby::Build.new do |conf|
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
# include the default GEMs
conf.gembox 'default'
end
# Cross Compiling configuration for Intel Galileo on Arduino environment
# http://arduino.cc/en/ArduinoCertified/IntelGalileo
#
# Requires Arduino IDE for Intel Galileo
MRuby::CrossBuild.new("Galileo") do |conf|
toolchain :gcc
# Mac OS X
# Assume you renamed Arduino.app to Arduino_Galileo.app
GALILEO_ARDUINO_PATH = '/Applications/Arduino_Galileo.app/Contents/Resources/Java'
# GNU Linux
#ARDUINO_GALILEO_PATH = '/opt/arduino'
GALILEO_BIN_PATH = "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i386-pokysdk-darwin/usr/bin/i586-poky-linux-uclibc"
GALILEO_SYSROOT = "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i586-poky-linux-uclibc"
GALILEO_X86_PATH = "#{GALILEO_ARDUINO_PATH}/hardware/arduino/x86"
conf.cc do |cc|
cc.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-gcc"
cc.include_paths << ["#{GALILEO_X86_PATH}/cores/arduino", "#{GALILEO_X86_PATH}/variants/galileo_fab_d"]
cc.flags = %w(-m32 -march=i586 -c -g -Os -w
-ffunction-sections -fdata-sections -MMD -DARDUINO=153)
cc.flags << "--sysroot=#{GALILEO_SYSROOT}"
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
end
conf.cxx do |cxx|
cxx.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-g++"
cxx.include_paths = conf.cc.include_paths.dup
cxx.include_paths << "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i586-poky-linux-uclibc/usr/include/c++"
cxx.include_paths << "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i586-poky-linux-uclibc/usr/include/c++/i586-poky-linux-uclibc"
cxx.flags = conf.cc.flags.dup
cxx.defines = conf.cc.defines.dup
cxx.compile_options = conf.cc.compile_options.dup
end
conf.archiver do |archiver|
archiver.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-ar"
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
conf.linker do |linker|
linker.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-g++"
linker.flags = %w(-m32 -march=i586)
linker.flags << "--sysroot=#{GALILEO_SYSROOT}"
linker.flags << %w(-Os -Wl,--gc-sections)
linker.libraries = %w(m pthread)
end
#no executables
conf.bins = []
#do not build executable test
conf.build_mrbtest_lib_only
#official mrbgems
conf.gem :core => "mruby-sprintf"
conf.gem :core => "mruby-print"
conf.gem :core => "mruby-math"
conf.gem :core => "mruby-time"
conf.gem :core => "mruby-struct"
conf.gem :core => "mruby-enum-ext"
conf.gem :core => "mruby-string-ext"
conf.gem :core => "mruby-numeric-ext"
conf.gem :core => "mruby-array-ext"
conf.gem :core => "mruby-hash-ext"
conf.gem :core => "mruby-range-ext"
conf.gem :core => "mruby-proc-ext"
conf.gem :core => "mruby-symbol-ext"
conf.gem :core => "mruby-random"
conf.gem :core => "mruby-object-ext"
conf.gem :core => "mruby-objectspace"
conf.gem :core => "mruby-fiber"
conf.gem :core => "mruby-toplevel-ext"
#lightweigh regular expression
conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master"
#Arduino API
#conf.gem :github =>"kyab/mruby-arduino", :branch => "master" do |g|
# g.cxx.include_paths << "#{GALILEO_X86_PATH}/libraries/Wire"
# g.cxx.include_paths << "#{GALILEO_X86_PATH}/libraries/Servo"
#enable unsupported Servo class
# g.cxx.defines << "MRUBY_ARDUINO_GALILEO_ENABLE_SERVO"
#end
end
@@ -0,0 +1,81 @@
MRuby::Build.new do |conf|
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
# include the default GEMs
conf.gembox 'default'
end
# Cross Compiling configuration for RX630
# http://gadget.renesas.com/
#
# Requires gnurx_v14.03
MRuby::CrossBuild.new("RX630") do |conf|
toolchain :gcc
# Linux
BIN_PATH = "/usr/share/gnurx_v14.03_elf-1/bin"
conf.cc do |cc|
cc.command = "#{BIN_PATH}/rx-elf-gcc"
cc.flags = "-Wall -g -O2 -flto -mcpu=rx600 -m64bit-doubles"
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
#configuration for low memory environment
cc.defines << %w(MRB_USE_FLOAT)
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
cc.defines << %w(MRB_GC_STRESS)
cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio.
#cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
end
conf.cxx do |cxx|
cxx.command = conf.cc.command.dup
cxx.include_paths = conf.cc.include_paths.dup
cxx.flags = conf.cc.flags.dup
cxx.defines = conf.cc.defines.dup
cxx.compile_options = conf.cc.compile_options.dup
end
conf.linker do |linker|
linker.command="#{BIN_PATH}/rx-elf-ld"
end
conf.archiver do |archiver|
archiver.command = "#{BIN_PATH}/rx-elf-ar"
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
#no executables
conf.bins = []
#do not build executable test
conf.build_mrbtest_lib_only
#disable C++ exception
conf.disable_cxx_exception
#gems from core
conf.gem :core => "mruby-sprintf"
conf.gem :core => "mruby-print"
conf.gem :core => "mruby-math"
conf.gem :core => "mruby-enum-ext"
conf.gem :core => "mruby-numeric-ext"
#light-weight regular expression
#conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master"
#Arduino API
#conf.gem :github =>"kyab/mruby-arduino", :branch => "master"
end
@@ -0,0 +1,26 @@
MRuby::Build.new do |conf|
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
# include the default GEMs
conf.gembox 'default'
end
# Requires Android NDK r13 or later.
MRuby::CrossBuild.new('android-arm64-v8a') do |conf|
params = {
:arch => 'arm64-v8a',
:platform => 'android-24',
:toolchain => :clang,
}
toolchain :android, params
conf.gembox 'default'
end
@@ -0,0 +1,26 @@
MRuby::Build.new do |conf|
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
# include the default GEMs
conf.gembox 'default'
end
# Requires Android NDK r13 or later.
MRuby::CrossBuild.new('android-armeabi') do |conf|
params = {
:arch => 'armeabi',
:platform => 'android-24',
:toolchain => :clang,
}
toolchain :android, params
conf.gembox 'default'
end
@@ -0,0 +1,28 @@
MRuby::Build.new do |conf|
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
# include the default GEMs
conf.gembox 'default'
end
# Requires Android NDK r13 or later.
MRuby::CrossBuild.new('android-armeabi-v7a-neon-hard') do |conf|
params = {
:arch => 'armeabi-v7a',
:mfpu => 'neon',
:mfloat_abi => 'hard',
:platform => 'android-24',
:toolchain => :clang,
}
toolchain :android, params
conf.gembox 'default'
end
@@ -0,0 +1,86 @@
MRuby::Build.new do |conf|
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
# include the default GEMs
conf.gembox 'default'
end
# Cross Compiling configuration for Digilent chipKIT Max32
# http://www.digilentinc.com/Products/Detail.cfm?Prod=CHIPKIT-MAX32
#
# Requires MPIDE (https://github.com/chipKIT32/chipKIT32-MAX)
#
# This configuration is based on @kyab's version
# http://d.hatena.ne.jp/kyab/20130201
MRuby::CrossBuild.new("chipKITMax32") do |conf|
toolchain :gcc
# Mac OS X
# MPIDE_PATH = '/Applications/Mpide.app/Contents/Resources/Java'
# GNU Linux
MPIDE_PATH = '/opt/mpide-0023-linux-20120903'
PIC32_PATH = "#{MPIDE_PATH}/hardware/pic32"
conf.cc do |cc|
cc.command = "#{PIC32_PATH}/compiler/pic32-tools/bin/pic32-gcc"
cc.include_paths << ["#{PIC32_PATH}/cores/pic32",
"#{PIC32_PATH}/variants/Max32",
"#{PIC32_PATH}/libraries"]
cc.flags = %w(-O2 -mno-smart-io -w -ffunction-sections -fdata-sections -g -mdebugger -Wcast-align
-fno-short-double -mprocessor=32MX795F512L -DF_CPU=80000000L -DARDUINO=23 -D_BOARD_MEGA_
-DMPIDEVER=0x01000202 -DMPIDE=23)
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
#configuration for low memory environment
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
cc.defines << %w(MRB_GC_STRESS)
#cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio.
#cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
end
conf.cxx do |cxx|
cxx.command = conf.cc.command.dup
cxx.include_paths = conf.cc.include_paths.dup
cxx.flags = conf.cc.flags.dup
cxx.defines = conf.cc.defines.dup
cxx.compile_options = conf.cc.compile_options.dup
end
conf.archiver do |archiver|
archiver.command = "#{PIC32_PATH}/compiler/pic32-tools/bin/pic32-ar"
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
#no executables
conf.bins = []
#do not build test executable
conf.build_mrbtest_lib_only
#disable C++ exception
conf.disable_cxx_exception
#gems from core
conf.gem :core => "mruby-print"
conf.gem :core => "mruby-math"
conf.gem :core => "mruby-enum-ext"
#light-weight regular expression
conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master"
#Arduino API
#conf.gem :github =>"kyab/mruby-arduino", :branch => "master"
end
@@ -0,0 +1,108 @@
MRuby::Build.new do |conf|
# Gets set by the VS command prompts
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end
enable_debug
# Include the default GEMs
conf.gembox 'default'
end
# Cross Compiling configuration for the Sega Dreamcast
# This configuration requires KallistiOS (KOS)
# https://dreamcast.wiki
#
# Tested on GNU/Linux, MinGW-w64/MSYS2, Cygwin, macOS and MinGW/MSYS (see below)
#
MRuby::CrossBuild.new("dreamcast") do |conf|
toolchain :gcc
# Support for DreamSDK (based on MinGW/MSYS)
# To compile mruby with DreamSDK, RubyInstaller for Windows should be installed
DREAMSDK_HOME = ENV["DREAMSDK_HOME"]
MSYS_ROOT = !(DREAMSDK_HOME.nil? || DREAMSDK_HOME.empty?) ? "#{DREAMSDK_HOME}/msys/1.0" : ""
# Setting paths
DREAMCAST_PATH = "#{MSYS_ROOT}/opt/toolchains/dc"
KOS_PATH = "#{DREAMCAST_PATH}/kos"
BIN_PATH = "#{DREAMCAST_PATH}/sh-elf/bin"
# C compiler
# Flags were extracted from KallistiOS environment files
conf.cc do |cc|
cc.command = "#{BIN_PATH}/sh-elf-gcc"
cc.include_paths << ["#{KOS_PATH}/include", "#{KOS_PATH}/kernel/arch/dreamcast/include", "#{KOS_PATH}/addons/include", "#{KOS_PATH}/../kos-ports/include"]
cc.flags << ["-O2", "-fomit-frame-pointer", "-ml", "-m4-single-only", "-ffunction-sections", "-fdata-sections", "-Wall", "-g", "-fno-builtin", "-ml", "-m4-single-only", "-Wl,-Ttext=0x8c010000", "-Wl,--gc-sections", "-T#{KOS_PATH}/utils/ldscripts/shlelf.xc", "-nodefaultlibs"]
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
cc.defines << %w(_arch_dreamcast)
cc.defines << %w(_arch_sub_pristine)
end
# C++ compiler
conf.cxx do |cxx|
cxx.command = conf.cc.command.dup
cxx.include_paths = conf.cc.include_paths.dup
cxx.flags = conf.cc.flags.dup
cxx.flags << %w(-fno-rtti -fno-exceptions)
cxx.defines = conf.cc.defines.dup
cxx.compile_options = conf.cc.compile_options.dup
end
# Linker
# There is an issue when making the mruby library with KallistiOS:
# 'newlib_kill.o' and 'newlib_getpid.o' aren't found so they are explicitly
# specified here at least for now.
conf.linker do |linker|
linker.command="#{BIN_PATH}/sh-elf-gcc"
linker.flags << ["#{MSYS_ROOT}/opt/toolchains/dc/kos/kernel/build/newlib_kill.o", "#{MSYS_ROOT}/opt/toolchains/dc/kos/kernel/build/newlib_getpid.o", "-Wl,--start-group -lkallisti -lc -lgcc -Wl,--end-group"]
linker.library_paths << ["#{KOS_PATH}/lib/dreamcast", "#{KOS_PATH}/addons/lib/dreamcast", "#{KOS_PATH}/../kos-ports/lib"]
end
# Archiver
conf.archiver do |archiver|
archiver.command = "#{BIN_PATH}/sh-elf-ar"
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
end
# No executables
conf.bins = []
# Do not build executable test
conf.build_mrbtest_lib_only
# Disable C++ exception
conf.disable_cxx_exception
# Gems from core
# removing mruby-io
conf.gem :core => "mruby-metaprog"
conf.gem :core => "mruby-pack"
conf.gem :core => "mruby-sprintf"
conf.gem :core => "mruby-print"
conf.gem :core => "mruby-math"
conf.gem :core => "mruby-time"
conf.gem :core => "mruby-struct"
conf.gem :core => "mruby-compar-ext"
conf.gem :core => "mruby-enum-ext"
conf.gem :core => "mruby-string-ext"
conf.gem :core => "mruby-numeric-ext"
conf.gem :core => "mruby-array-ext"
conf.gem :core => "mruby-hash-ext"
conf.gem :core => "mruby-range-ext"
conf.gem :core => "mruby-proc-ext"
conf.gem :core => "mruby-symbol-ext"
conf.gem :core => "mruby-random"
conf.gem :core => "mruby-object-ext"
conf.gem :core => "mruby-objectspace"
conf.gem :core => "mruby-fiber"
conf.gem :core => "mruby-enumerator"
conf.gem :core => "mruby-enum-lazy"
conf.gem :core => "mruby-toplevel-ext"
conf.gem :core => "mruby-kernel-ext"
conf.gem :core => "mruby-class-ext"
conf.gem :core => "mruby-compiler"
end
+215
View File
@@ -0,0 +1,215 @@
/*
** mrbconf.h - mruby core configuration
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBYCONF_H
#define MRUBYCONF_H
#include <limits.h>
#include <stdint.h>
/* architecture selection: */
/* specify -DMRB_32BIT or -DMRB_64BIT to override */
#if !defined(MRB_32BIT) && !defined(MRB_64BIT)
#if UINT64_MAX == SIZE_MAX
#define MRB_64BIT
#else
#define MRB_32BIT
#endif
#endif
#if defined(MRB_32BIT) && defined(MRB_64BIT)
#error Cannot build for 32 and 64 bit architecture at the same time
#endif
/* configuration options: */
/* add -DMRB_USE_FLOAT to use float instead of double for floating point numbers */
//#define MRB_USE_FLOAT
/* exclude floating point numbers */
//#define MRB_WITHOUT_FLOAT
/* add -DMRB_METHOD_CACHE to use method cache to improve performance */
//#define MRB_METHOD_CACHE
/* size of the method cache (need to be the power of 2) */
//#define MRB_METHOD_CACHE_SIZE (1<<7)
/* add -DMRB_METHOD_T_STRUCT on machines that use higher bits of pointers */
/* no MRB_METHOD_T_STRUCT requires highest 2 bits of function pointers to be zero */
#ifndef MRB_METHOD_T_STRUCT
// can't use highest 2 bits of function pointers at least on 32bit
// Windows and 32bit Linux.
# ifdef MRB_32BIT
# define MRB_METHOD_T_STRUCT
# endif
#endif
/* add -DMRB_INT32 to use 32bit integer for mrb_int; conflict with MRB_INT64;
Default for 32-bit CPU mode. */
//#define MRB_INT32
/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT32;
Default for 64-bit CPU mode. */
//#define MRB_INT64
/* if no specific integer type is chosen */
#if !defined(MRB_INT32) && !defined(MRB_INT64)
# if defined(MRB_64BIT) && !defined(MRB_NAN_BOXING)
/* Use 64bit integers on 64bit architecture (without MRB_NAN_BOXING) */
# define MRB_INT64
# else
/* Otherwise use 32bit integers */
# define MRB_INT32
# endif
#endif
/* define on big endian machines; used by MRB_NAN_BOXING, etc. */
#ifndef MRB_ENDIAN_BIG
# if (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
# define MRB_ENDIAN_BIG
# endif
#endif
/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT and MRB_WITHOUT_FLOAT */
//#define MRB_NAN_BOXING
/* represent mrb_value as a word (natural unit of data for the processor) */
//#define MRB_WORD_BOXING
/* string class to handle UTF-8 encoding */
//#define MRB_UTF8_STRING
/* argv max size in mrb_funcall */
//#define MRB_FUNCALL_ARGC_MAX 16
/* number of object per heap page */
//#define MRB_HEAP_PAGE_SIZE 1024
/* if __ehdr_start is available, mruby can reduce memory used by symbols */
//#define MRB_USE_LINK_TIME_RO_DATA_P
/* if MRB_USE_LINK_TIME_RO_DATA_P does not work,
you can try mrb_ro_data_p() that you have implemented yourself in any file;
prototype is `mrb_bool mrb_ro_data_p(const char *ptr)` */
//#define MRB_USE_CUSTOM_RO_DATA_P
/* turn off generational GC by default */
//#define MRB_GC_TURN_OFF_GENERATIONAL
/* default size of khash table bucket */
//#define KHASH_DEFAULT_SIZE 32
/* allocated memory address alignment */
//#define POOL_ALIGNMENT 4
/* page size of memory pool */
//#define POOL_PAGE_SIZE 16000
/* initial minimum size for string buffer */
//#define MRB_STR_BUF_MIN_SIZE 128
/* arena size */
//#define MRB_GC_ARENA_SIZE 100
/* fixed size GC arena */
//#define MRB_GC_FIXED_ARENA
/* state atexit stack size */
//#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5
/* fixed size state atexit stack */
//#define MRB_FIXED_STATE_ATEXIT_STACK
/* -DMRB_DISABLE_XXXX to drop following features */
//#define MRB_DISABLE_STDIO /* use of stdio */
/* -DMRB_ENABLE_XXXX to enable following features */
//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */
//#define MRB_ENABLE_ALL_SYMBOLS /* Symbols.all_symbols */
/* end of configuration */
/* define MRB_DISABLE_XXXX from DISABLE_XXX (for compatibility) */
#ifdef DISABLE_STDIO
#define MRB_DISABLE_STDIO
#endif
/* define MRB_ENABLE_XXXX from ENABLE_XXX (for compatibility) */
#ifdef ENABLE_DEBUG
#define MRB_ENABLE_DEBUG_HOOK
#endif
#ifndef MRB_DISABLE_STDIO
# include <stdio.h>
#endif
#ifndef FALSE
# define FALSE 0
#endif
#ifndef TRUE
# define TRUE 1
#endif
/*
** mruby tuning profiles
**/
/* A profile for micro controllers */
#if defined(MRB_CONSTRAINED_BASELINE_PROFILE)
# ifndef KHASH_DEFAULT_SIZE
# define KHASH_DEFAULT_SIZE 16
# endif
# ifndef MRB_STR_BUF_MIN_SIZE
# define MRB_STR_BUF_MIN_SIZE 32
# endif
# ifndef MRB_HEAP_PAGE_SIZE
# define MRB_HEAP_PAGE_SIZE 256
# endif
/* A profile for default mruby */
#elif defined(MRB_BASELINE_PROFILE)
/* A profile for desktop computers or workstations; rich memory! */
#elif defined(MRB_MAIN_PROFILE)
# ifndef MRB_METHOD_CACHE
# define MRB_METHOD_CACHE
# endif
# ifndef MRB_METHOD_CACHE_SIZE
# define MRB_METHOD_CACHE_SIZE (1<<10)
# endif
# ifndef MRB_IV_SEGMENT_SIZE
# define MRB_IV_SEGMENT_SIZE 32
# endif
# ifndef MRB_HEAP_PAGE_SIZE
# define MRB_HEAP_PAGE_SIZE 4096
# endif
/* A profile for server; mruby vm is long life */
#elif defined(MRB_HIGH_PROFILE)
# ifndef MRB_METHOD_CACHE
# define MRB_METHOD_CACHE
# endif
# ifndef MRB_METHOD_CACHE_SIZE
# define MRB_METHOD_CACHE_SIZE (1<<12)
# endif
# ifndef MRB_IV_SEGMENT_SIZE
# define MRB_IV_SEGMENT_SIZE 64
# endif
# ifndef MRB_HEAP_PAGE_SIZE
# define MRB_HEAP_PAGE_SIZE 4096
# endif
#endif
#endif /* MRUBYCONF_H */
File diff suppressed because it is too large Load Diff
+300
View File
@@ -0,0 +1,300 @@
/**
** @file mruby/array.h - Array class
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_ARRAY_H
#define MRUBY_ARRAY_H
#include "common.h"
/*
* Array class
*/
MRB_BEGIN_DECL
typedef struct mrb_shared_array {
int refcnt;
mrb_ssize len;
mrb_value *ptr;
} mrb_shared_array;
#define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value)))
struct RArray {
MRB_OBJECT_HEADER;
union {
struct {
mrb_ssize len;
union {
mrb_ssize capa;
mrb_shared_array *shared;
} aux;
mrb_value *ptr;
} heap;
void *ary[3];
} as;
};
#define mrb_ary_ptr(v) ((struct RArray*)(mrb_ptr(v)))
#define mrb_ary_value(p) mrb_obj_value((void*)(p))
#define RARRAY(v) ((struct RArray*)(mrb_ptr(v)))
#define MRB_ARY_EMBED_MASK 7
#define ARY_EMBED_P(a) ((a)->flags & MRB_ARY_EMBED_MASK)
#define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED_MASK))
#define ARY_EMBED_LEN(a) ((mrb_int)(((a)->flags & MRB_ARY_EMBED_MASK) - 1))
#define ARY_SET_EMBED_LEN(a,len) ((a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | ((uint32_t)(len) + 1))
#define ARY_EMBED_PTR(a) ((mrb_value*)(&(a)->as.ary))
#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len)
#define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr)
#define RARRAY_LEN(a) ARY_LEN(RARRAY(a))
#define RARRAY_PTR(a) ARY_PTR(RARRAY(a))
#define ARY_SET_LEN(a,n) do {\
if (ARY_EMBED_P(a)) {\
mrb_assert((n) <= MRB_ARY_EMBED_LEN_MAX); \
ARY_SET_EMBED_LEN(a,n);\
}\
else\
(a)->as.heap.len = (n);\
} while (0)
#define ARY_CAPA(a) (ARY_EMBED_P(a)?MRB_ARY_EMBED_LEN_MAX:(a)->as.heap.aux.capa)
#define MRB_ARY_SHARED 256
#define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED)
#define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED)
#define ARY_UNSET_SHARED_FLAG(a) ((a)->flags &= ~MRB_ARY_SHARED)
void mrb_ary_decref(mrb_state*, mrb_shared_array*);
MRB_API void mrb_ary_modify(mrb_state*, struct RArray*);
MRB_API mrb_value mrb_ary_new_capa(mrb_state*, mrb_int);
/*
* Initializes a new array.
*
* Equivalent to:
*
* Array.new
*
* @param mrb The mruby state reference.
* @return The initialized array.
*/
MRB_API mrb_value mrb_ary_new(mrb_state *mrb);
/*
* Initializes a new array with initial values
*
* Equivalent to:
*
* Array[value1, value2, ...]
*
* @param mrb The mruby state reference.
* @param size The numer of values.
* @param vals The actual values.
* @return The initialized array.
*/
MRB_API mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals);
/*
* Initializes a new array with two initial values
*
* Equivalent to:
*
* Array[car, cdr]
*
* @param mrb The mruby state reference.
* @param car The first value.
* @param cdr The second value.
* @return The initialized array.
*/
MRB_API mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr);
/*
* Concatenate two arrays. The target array will be modified
*
* Equivalent to:
* ary.concat(other)
*
* @param mrb The mruby state reference.
* @param self The target array.
* @param other The array that will be concatenated to self.
*/
MRB_API void mrb_ary_concat(mrb_state *mrb, mrb_value self, mrb_value other);
/*
* Create an array from the input. It tries calling to_a on the
* value. If value does not respond to that, it creates a new
* array with just this value.
*
* @param mrb The mruby state reference.
* @param value The value to change into an array.
* @return An array representation of value.
*/
MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value value);
/*
* Pushes value into array.
*
* Equivalent to:
*
* ary << value
*
* @param mrb The mruby state reference.
* @param ary The array in which the value will be pushed
* @param value The value to be pushed into array
*/
MRB_API void mrb_ary_push(mrb_state *mrb, mrb_value array, mrb_value value);
/*
* Pops the last element from the array.
*
* Equivalent to:
*
* ary.pop
*
* @param mrb The mruby state reference.
* @param ary The array from which the value will be popped.
* @return The popped value.
*/
MRB_API mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary);
/*
* Returns a reference to an element of the array on the given index.
*
* Equivalent to:
*
* ary[n]
*
* @param mrb The mruby state reference.
* @param ary The target array.
* @param n The array index being referenced
* @return The referenced value.
*/
MRB_API mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n);
/*
* Sets a value on an array at the given index
*
* Equivalent to:
*
* ary[n] = val
*
* @param mrb The mruby state reference.
* @param ary The target array.
* @param n The array index being referenced.
* @param val The value being setted.
*/
MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val);
/*
* Replace the array with another array
*
* Equivalent to:
*
* ary.replace(other)
*
* @param mrb The mruby state reference
* @param self The target array.
* @param other The array to replace it with.
*/
MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other);
MRB_API mrb_value mrb_ensure_array_type(mrb_state *mrb, mrb_value self);
MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
/*
* Unshift an element into the array
*
* Equivalent to:
*
* ary.unshift(item)
*
* @param mrb The mruby state reference.
* @param self The target array.
* @param item The item to unshift.
*/
MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item);
/*
* Get nth element in the array
*
* Equivalent to:
*
* ary[offset]
*
* @param ary The target array.
* @param offset The element position (negative counts from the tail).
*/
MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
/*
* Replace subsequence of an array.
*
* Equivalent to:
*
* ary.shift
*
* @param mrb The mruby state reference.
* @param self The array from which the value will be shifted.
* @param head Beginning position of a replacement subsequence.
* @param len Length of a replacement subsequence.
* @param rpl The array of replacement elements.
* It is possible to pass `mrb_undef_value()` instead of an empty array.
* @return The receiver array.
*/
MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value self, mrb_int head, mrb_int len, mrb_value rpl);
/*
* Shifts the first element from the array.
*
* Equivalent to:
*
* ary.shift
*
* @param mrb The mruby state reference.
* @param self The array from which the value will be shifted.
* @return The shifted value.
*/
MRB_API mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self);
/*
* Removes all elements from the array
*
* Equivalent to:
*
* ary.clear
*
* @param mrb The mruby state reference.
* @param self The target array.
* @return self
*/
MRB_API mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self);
/*
* Join the array elements together in a string
*
* Equivalent to:
*
* ary.join(sep="")
*
* @param mrb The mruby state reference.
* @param ary The target array
* @param sep The separater, can be NULL
*/
MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep);
/*
* Update the capacity of the array
*
* @param mrb The mruby state reference.
* @param ary The target array.
* @param new_len The new capacity of the array
*/
MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len);
/* helper functions */
mrb_value mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len);
MRB_END_DECL
#endif /* MRUBY_ARRAY_H */
+105
View File
@@ -0,0 +1,105 @@
/**
** @file mruby/boxing_nan.h - nan boxing mrb_value definition
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_BOXING_NAN_H
#define MRUBY_BOXING_NAN_H
#ifdef MRB_USE_FLOAT
# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<----
#endif
#ifdef MRB_WITHOUT_FLOAT
# error ---->> MRB_NAN_BOXING and MRB_WITHOUT_FLOAT conflict <<----
#endif
#ifdef MRB_INT64
# error ---->> MRB_NAN_BOXING and MRB_INT64 conflict <<----
#endif
#define MRB_FIXNUM_SHIFT 0
#define MRB_SYMBOL_SHIFT 0
/* value representation by nan-boxing:
* float : FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
* object: 111111111111TTTT TTPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP
* int : 1111111111110001 0000000000000000 IIIIIIIIIIIIIIII IIIIIIIIIIIIIIII
* sym : 1111111111110001 0100000000000000 SSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSS
* In order to get enough bit size to save TT, all pointers are shifted 2 bits
* in the right direction. Also, TTTTTT is the mrb_vtype + 1;
*/
typedef struct mrb_value {
union {
mrb_float f;
union {
void *p;
struct {
MRB_ENDIAN_LOHI(
uint32_t ttt;
,union {
mrb_int i;
mrb_sym sym;
};
)
};
#ifdef MRB_64BIT
struct RCptr *vp;
#endif
} value;
};
} mrb_value;
#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f)
#define mrb_tt(o) ((enum mrb_vtype)(((o).value.ttt & 0xfc000)>>14)-1)
#define mrb_type(o) (enum mrb_vtype)((uint32_t)0xfff00000 < (o).value.ttt ? mrb_tt(o) : MRB_TT_FLOAT)
#define mrb_ptr(o) ((void*)((((uintptr_t)0x3fffffffffff)&((uintptr_t)((o).value.p)))<<2))
#define mrb_float(o) (o).f
#define mrb_fixnum(o) (o).value.i
#define mrb_symbol(o) (o).value.sym
#ifdef MRB_64BIT
MRB_API mrb_value mrb_nan_boxing_cptr_value(struct mrb_state*, void*);
#define mrb_cptr(o) (((struct RCptr*)mrb_ptr(o))->p)
#define BOXNAN_SHIFT_LONG_POINTER(v) (((uintptr_t)(v)>>34)&0x3fff)
#else
#define mrb_cptr(o) ((o).value.p)
#define BOXNAN_SHIFT_LONG_POINTER(v) 0
#endif
#define BOXNAN_SET_VALUE(o, tt, attr, v) do {\
(o).attr = (v);\
(o).value.ttt = 0xfff00000 | (((tt)+1)<<14);\
} while (0)
#define BOXNAN_SET_OBJ_VALUE(o, tt, v) do {\
(o).value.p = (void*)((uintptr_t)(v)>>2);\
(o).value.ttt = (0xfff00000|(((tt)+1)<<14)|BOXNAN_SHIFT_LONG_POINTER(v));\
} while (0)
#define SET_FLOAT_VALUE(mrb,r,v) do { \
if ((v) != (v)) { \
(r).value.ttt = 0x7ff80000; \
(r).value.i = 0; \
} \
else { \
(r).f = v; \
}} while(0)
#define SET_NIL_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_FALSE, value.i, 0)
#define SET_FALSE_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
#define SET_TRUE_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
#define SET_BOOL_VALUE(r,b) BOXNAN_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1)
#define SET_INT_VALUE(r,n) BOXNAN_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
#define SET_SYM_VALUE(r,v) BOXNAN_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
#define SET_OBJ_VALUE(r,v) BOXNAN_SET_OBJ_VALUE(r, (((struct RObject*)(v))->tt), (v))
#ifdef MRB_64BIT
#define SET_CPTR_VALUE(mrb,r,v) ((r) = mrb_nan_boxing_cptr_value(mrb, v))
#else
#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_VALUE(r, MRB_TT_CPTR, value.p, v)
#endif
#define SET_UNDEF_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0)
#endif /* MRUBY_BOXING_NAN_H */
+58
View File
@@ -0,0 +1,58 @@
/**
** @file mruby/boxing_no.h - unboxed mrb_value definition
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_BOXING_NO_H
#define MRUBY_BOXING_NO_H
#define MRB_FIXNUM_SHIFT 0
#define MRB_SYMBOL_SHIFT 0
union mrb_value_union {
#ifndef MRB_WITHOUT_FLOAT
mrb_float f;
#endif
void *p;
mrb_int i;
mrb_sym sym;
};
typedef struct mrb_value {
union mrb_value_union value;
enum mrb_vtype tt;
} mrb_value;
#ifndef MRB_WITHOUT_FLOAT
#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f)
#endif
#define mrb_ptr(o) (o).value.p
#define mrb_cptr(o) mrb_ptr(o)
#ifndef MRB_WITHOUT_FLOAT
#define mrb_float(o) (o).value.f
#endif
#define mrb_fixnum(o) (o).value.i
#define mrb_symbol(o) (o).value.sym
#define mrb_type(o) (o).tt
#define BOXNIX_SET_VALUE(o, ttt, attr, v) do {\
(o).tt = ttt;\
(o).attr = v;\
} while (0)
#define SET_NIL_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_FALSE, value.i, 0)
#define SET_FALSE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
#define SET_TRUE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
#define SET_BOOL_VALUE(r,b) BOXNIX_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1)
#define SET_INT_VALUE(r,n) BOXNIX_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
#ifndef MRB_WITHOUT_FLOAT
#define SET_FLOAT_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v))
#endif
#define SET_SYM_VALUE(r,v) BOXNIX_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
#define SET_OBJ_VALUE(r,v) BOXNIX_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v))
#define SET_CPTR_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_CPTR, value.p, v)
#define SET_UNDEF_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0)
#endif /* MRUBY_BOXING_NO_H */
+174
View File
@@ -0,0 +1,174 @@
/**
** @file mruby/boxing_word.h - word boxing mrb_value definition
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_BOXING_WORD_H
#define MRUBY_BOXING_WORD_H
#if defined(MRB_INT64) && !defined(MRB_64BIT)
#error MRB_INT64 cannot be used with MRB_WORD_BOXING in 32-bit mode.
#endif
#ifndef MRB_WITHOUT_FLOAT
struct RFloat {
MRB_OBJECT_HEADER;
mrb_float f;
};
#endif
enum mrb_special_consts {
MRB_Qnil = 0,
MRB_Qfalse = 4,
MRB_Qtrue = 12,
MRB_Qundef = 20,
};
#if defined(MRB_64BIT) && defined(MRB_INT32)
#define MRB_FIXNUM_SHIFT 0
#else
#define MRB_FIXNUM_SHIFT BOXWORD_FIXNUM_SHIFT
#endif
#define MRB_SYMBOL_SHIFT BOXWORD_SYMBOL_SHIFT
#define BOXWORD_FIXNUM_BIT_POS 1
#define BOXWORD_SYMBOL_BIT_POS 2
#define BOXWORD_FIXNUM_SHIFT BOXWORD_FIXNUM_BIT_POS
#ifdef MRB_64BIT
#define BOXWORD_SYMBOL_SHIFT 0
#else
#define BOXWORD_SYMBOL_SHIFT BOXWORD_SYMBOL_BIT_POS
#endif
#define BOXWORD_FIXNUM_FLAG (1 << (BOXWORD_FIXNUM_BIT_POS - 1))
#define BOXWORD_SYMBOL_FLAG (1 << (BOXWORD_SYMBOL_BIT_POS - 1))
#define BOXWORD_FIXNUM_MASK ((1 << BOXWORD_FIXNUM_BIT_POS) - 1)
#define BOXWORD_SYMBOL_MASK ((1 << BOXWORD_SYMBOL_BIT_POS) - 1)
#define BOXWORD_IMMEDIATE_MASK 0x07
#define BOXWORD_SHIFT_VALUE(o,n,t) \
(t)(((long)(o).w) >> BOXWORD_##n##_SHIFT)
#define BOXWORD_SET_SHIFT_VALUE(o,n,v) \
((o).w = (((unsigned long)(v)) << BOXWORD_##n##_SHIFT) | BOXWORD_##n##_FLAG)
#define BOXWORD_SHIFT_VALUE_P(o,n) \
(((o).w & BOXWORD_##n##_MASK) == BOXWORD_##n##_FLAG)
#define BOXWORD_OBJ_TYPE_P(o,n) \
(!mrb_immediate_p(o) && (o).value.bp->tt == MRB_TT_##n)
/*
* mrb_value representation:
*
* nil : ...0000 0000 (all bits are 0)
* false : ...0000 0100 (mrb_fixnum(v) != 0)
* true : ...0000 1100
* undef : ...0001 0100
* fixnum: ...IIII III1
* symbol: ...SSSS SS10 (use only upper 32-bit as symbol value on 64-bit CPU)
* object: ...PPPP P000 (any bits are 1)
*/
typedef union mrb_value {
union {
void *p;
#ifdef MRB_64BIT
/* use struct to avoid bit shift. */
struct {
MRB_ENDIAN_LOHI(
mrb_sym sym;
,uint32_t sym_flag;
)
};
#endif
struct RBasic *bp;
#ifndef MRB_WITHOUT_FLOAT
struct RFloat *fp;
#endif
struct RCptr *vp;
} value;
unsigned long w;
} mrb_value;
MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*);
#ifndef MRB_WITHOUT_FLOAT
MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float);
MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
#endif
#ifndef MRB_WITHOUT_FLOAT
#define mrb_float_pool(mrb,f) mrb_word_boxing_float_pool(mrb,f)
#endif
#define mrb_ptr(o) (o).value.p
#define mrb_cptr(o) (o).value.vp->p
#ifndef MRB_WITHOUT_FLOAT
#define mrb_float(o) (o).value.fp->f
#endif
#define mrb_fixnum(o) BOXWORD_SHIFT_VALUE(o, FIXNUM, mrb_int)
#ifdef MRB_64BIT
#define mrb_symbol(o) (o).value.sym
#else
#define mrb_symbol(o) BOXWORD_SHIFT_VALUE(o, SYMBOL, mrb_sym)
#endif
#define mrb_bool(o) (((o).w & ~(unsigned long)MRB_Qfalse) != 0)
#define mrb_immediate_p(o) ((o).w & BOXWORD_IMMEDIATE_MASK || (o).w == MRB_Qnil)
#define mrb_fixnum_p(o) BOXWORD_SHIFT_VALUE_P(o, FIXNUM)
#ifdef MRB_64BIT
#define mrb_symbol_p(o) ((o).value.sym_flag == BOXWORD_SYMBOL_FLAG)
#else
#define mrb_symbol_p(o) BOXWORD_SHIFT_VALUE_P(o, SYMBOL)
#endif
#define mrb_undef_p(o) ((o).w == MRB_Qundef)
#define mrb_nil_p(o) ((o).w == MRB_Qnil)
#define mrb_false_p(o) ((o).w == MRB_Qfalse)
#define mrb_true_p(o) ((o).w == MRB_Qtrue)
#ifndef MRB_WITHOUT_FLOAT
#define mrb_float_p(o) BOXWORD_OBJ_TYPE_P(o, FLOAT)
#endif
#define mrb_array_p(o) BOXWORD_OBJ_TYPE_P(o, ARRAY)
#define mrb_string_p(o) BOXWORD_OBJ_TYPE_P(o, STRING)
#define mrb_hash_p(o) BOXWORD_OBJ_TYPE_P(o, HASH)
#define mrb_cptr_p(o) BOXWORD_OBJ_TYPE_P(o, CPTR)
#define mrb_exception_p(o) BOXWORD_OBJ_TYPE_P(o, EXCEPTION)
#define mrb_free_p(o) BOXWORD_OBJ_TYPE_P(o, FREE)
#define mrb_object_p(o) BOXWORD_OBJ_TYPE_P(o, OBJECT)
#define mrb_class_p(o) BOXWORD_OBJ_TYPE_P(o, CLASS)
#define mrb_module_p(o) BOXWORD_OBJ_TYPE_P(o, MODULE)
#define mrb_iclass_p(o) BOXWORD_OBJ_TYPE_P(o, ICLASS)
#define mrb_sclass_p(o) BOXWORD_OBJ_TYPE_P(o, SCLASS)
#define mrb_proc_p(o) BOXWORD_OBJ_TYPE_P(o, PROC)
#define mrb_range_p(o) BOXWORD_OBJ_TYPE_P(o, RANGE)
#define mrb_env_p(o) BOXWORD_OBJ_TYPE_P(o, ENV)
#define mrb_data_p(o) BOXWORD_OBJ_TYPE_P(o, DATA)
#define mrb_fiber_p(o) BOXWORD_OBJ_TYPE_P(o, FIBER)
#define mrb_istruct_p(o) BOXWORD_OBJ_TYPE_P(o, ISTRUCT)
#define mrb_break_p(o) BOXWORD_OBJ_TYPE_P(o, BREAK)
#ifndef MRB_WITHOUT_FLOAT
#define SET_FLOAT_VALUE(mrb,r,v) ((r) = mrb_word_boxing_float_value(mrb, v))
#endif
#define SET_CPTR_VALUE(mrb,r,v) ((r) = mrb_word_boxing_cptr_value(mrb, v))
#define SET_UNDEF_VALUE(r) ((r).w = MRB_Qundef)
#define SET_NIL_VALUE(r) ((r).w = MRB_Qnil)
#define SET_FALSE_VALUE(r) ((r).w = MRB_Qfalse)
#define SET_TRUE_VALUE(r) ((r).w = MRB_Qtrue)
#define SET_BOOL_VALUE(r,b) ((b) ? SET_TRUE_VALUE(r) : SET_FALSE_VALUE(r))
#define SET_INT_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, FIXNUM, n)
#ifdef MRB_64BIT
#define SET_SYM_VALUE(r,v) ((r).value.sym = v, (r).value.sym_flag = BOXWORD_SYMBOL_FLAG)
#else
#define SET_SYM_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, SYMBOL, n)
#endif
#define SET_OBJ_VALUE(r,v) ((r).value.p = v)
MRB_INLINE enum mrb_vtype
mrb_type(mrb_value o)
{
return !mrb_bool(o) ? MRB_TT_FALSE :
mrb_true_p(o) ? MRB_TT_TRUE :
mrb_fixnum_p(o) ? MRB_TT_FIXNUM :
mrb_symbol_p(o) ? MRB_TT_SYMBOL :
mrb_undef_p(o) ? MRB_TT_UNDEF :
o.value.bp->tt;
}
#endif /* MRUBY_BOXING_WORD_H */
+106
View File
@@ -0,0 +1,106 @@
/**
** @file mruby/class.h - Class class
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_CLASS_H
#define MRUBY_CLASS_H
#include "common.h"
/**
* Class class
*/
MRB_BEGIN_DECL
struct RClass {
MRB_OBJECT_HEADER;
struct iv_tbl *iv;
struct kh_mt *mt;
struct RClass *super;
};
#define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v)))
MRB_INLINE struct RClass*
mrb_class(mrb_state *mrb, mrb_value v)
{
switch (mrb_type(v)) {
case MRB_TT_FALSE:
if (mrb_fixnum(v))
return mrb->false_class;
return mrb->nil_class;
case MRB_TT_TRUE:
return mrb->true_class;
case MRB_TT_SYMBOL:
return mrb->symbol_class;
case MRB_TT_FIXNUM:
return mrb->fixnum_class;
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
return mrb->float_class;
#endif
case MRB_TT_CPTR:
return mrb->object_class;
case MRB_TT_ENV:
return NULL;
default:
return mrb_obj_ptr(v)->c;
}
}
/* flags:
20: frozen
19: is_prepended
18: is_origin
17: is_inherited (used by method cache)
16: unused
0-15: instance type
*/
#define MRB_FL_CLASS_IS_PREPENDED (1 << 19)
#define MRB_FL_CLASS_IS_ORIGIN (1 << 18)
#define MRB_CLASS_ORIGIN(c) do {\
if ((c)->flags & MRB_FL_CLASS_IS_PREPENDED) {\
(c) = (c)->super;\
while (!((c)->flags & MRB_FL_CLASS_IS_ORIGIN)) {\
(c) = (c)->super;\
}\
}\
} while (0)
#define MRB_FL_CLASS_IS_INHERITED (1 << 17)
#define MRB_INSTANCE_TT_MASK (0xFF)
#define MRB_SET_INSTANCE_TT(c, tt) ((c)->flags = (((c)->flags & ~MRB_INSTANCE_TT_MASK) | (char)(tt)))
#define MRB_INSTANCE_TT(c) (enum mrb_vtype)((c)->flags & MRB_INSTANCE_TT_MASK)
MRB_API struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*);
MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym);
struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t);
MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b);
MRB_API mrb_method_t mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
MRB_API mrb_method_t mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
MRB_API struct RClass* mrb_class_real(struct RClass* cl);
mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv);
void mrb_class_name_class(mrb_state*, struct RClass*, struct RClass*, mrb_sym);
mrb_bool mrb_const_name_p(mrb_state*, const char*, mrb_int);
mrb_value mrb_class_find_path(mrb_state*, struct RClass*);
mrb_value mrb_mod_to_s(mrb_state*, mrb_value);
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
void mrb_gc_free_mt(mrb_state*, struct RClass*);
#ifdef MRB_METHOD_CACHE
void mrb_mc_clear_by_class(mrb_state *mrb, struct RClass* c);
#else
#define mrb_mc_clear_by_class(mrb,c)
#endif
MRB_END_DECL
#endif /* MRUBY_CLASS_H */
+89
View File
@@ -0,0 +1,89 @@
/**
** @file common.h - mruby common platform definition"
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_COMMON_H
#define MRUBY_COMMON_H
#ifdef __APPLE__
#ifndef __TARGETCONDITIONALS__
#include "TargetConditionals.h"
#endif
#endif
#ifdef __cplusplus
#ifdef MRB_ENABLE_CXX_ABI
#define MRB_BEGIN_DECL
#define MRB_END_DECL
#else
# define MRB_BEGIN_DECL extern "C" {
# define MRB_END_DECL }
#endif
#else
/** Start declarations in C mode */
# define MRB_BEGIN_DECL
/** End declarations in C mode */
# define MRB_END_DECL
#endif
/**
* Shared compiler macros
*/
MRB_BEGIN_DECL
/** Declare a function that never returns. */
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L
# define mrb_noreturn _Noreturn
#elif defined __GNUC__ && !defined __STRICT_ANSI__
# define mrb_noreturn __attribute__((noreturn))
#elif defined _MSC_VER
# define mrb_noreturn __declspec(noreturn)
#else
# define mrb_noreturn
#endif
/** Mark a function as deprecated. */
#if defined __GNUC__ && !defined __STRICT_ANSI__
# define mrb_deprecated __attribute__((deprecated))
#elif defined _MSC_VER
# define mrb_deprecated __declspec(deprecated)
#else
# define mrb_deprecated
#endif
/** Declare a function as always inlined. */
#if defined _MSC_VER && _MSC_VER < 1900
# ifndef __cplusplus
# define inline __inline
# endif
#endif
#define MRB_INLINE static inline
/** Declare a public MRuby API function. */
#ifndef MRB_API
#if defined(MRB_BUILD_AS_DLL)
#if defined(MRB_CORE) || defined(MRB_LIB)
# define MRB_API __declspec(dllexport)
#else
# define MRB_API __declspec(dllimport)
#endif
#else
# define MRB_API extern
#endif
#endif
/** Declare mingw versions */
#if defined(__MINGW32__) || defined(__MINGW64__)
# include <_mingw.h>
# if defined(__MINGW64_VERSION_MAJOR)
# define MRB_MINGW64_VERSION (__MINGW64_VERSION_MAJOR * 1000 + __MINGW64_VERSION_MINOR)
# elif defined(__MINGW32_MAJOR_VERSION)
# define MRB_MINGW32_VERSION (__MINGW32_MAJOR_VERSION * 1000 + __MINGW32_MINOR_VERSION)
# endif
#endif
MRB_END_DECL
#endif /* MRUBY_COMMON_H */
+204
View File
@@ -0,0 +1,204 @@
/**
** @file mruby/compile.h - mruby parser
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_COMPILE_H
#define MRUBY_COMPILE_H
#include "common.h"
/**
* MRuby Compiler
*/
MRB_BEGIN_DECL
#include <mruby.h>
struct mrb_jmpbuf;
struct mrb_parser_state;
/* load context */
typedef struct mrbc_context {
mrb_sym *syms;
int slen;
char *filename;
uint16_t lineno;
int (*partial_hook)(struct mrb_parser_state*);
void *partial_data;
struct RClass *target_class;
mrb_bool capture_errors:1;
mrb_bool dump_result:1;
mrb_bool no_exec:1;
mrb_bool keep_lv:1;
mrb_bool no_optimize:1;
struct RProc *upper;
size_t parser_nerr;
} mrbc_context;
MRB_API mrbc_context* mrbc_context_new(mrb_state *mrb);
MRB_API void mrbc_context_free(mrb_state *mrb, mrbc_context *cxt);
MRB_API const char *mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s);
MRB_API void mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*partial_hook)(struct mrb_parser_state*), void*data);
/* AST node structure */
typedef struct mrb_ast_node {
struct mrb_ast_node *car, *cdr;
uint16_t lineno, filename_index;
} mrb_ast_node;
/* lexer states */
enum mrb_lex_state_enum {
EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_END, /* newline significant, +/- is an operator. */
EXPR_ENDARG, /* ditto, and unbound braces. */
EXPR_ENDFN, /* ditto, and unbound braces. */
EXPR_ARG, /* newline significant, +/- is an operator. */
EXPR_CMDARG, /* newline significant, +/- is an operator. */
EXPR_MID, /* newline significant, +/- is an operator. */
EXPR_FNAME, /* ignore newline, no reserved words. */
EXPR_DOT, /* right after '.' or '::', no reserved words. */
EXPR_CLASS, /* immediate after 'class', no here document. */
EXPR_VALUE, /* alike EXPR_BEG but label is disallowed. */
EXPR_MAX_STATE
};
/* saved error message */
struct mrb_parser_message {
uint16_t lineno;
int column;
char* message;
};
#define STR_FUNC_PARSING 0x01
#define STR_FUNC_EXPAND 0x02
#define STR_FUNC_REGEXP 0x04
#define STR_FUNC_WORD 0x08
#define STR_FUNC_SYMBOL 0x10
#define STR_FUNC_ARRAY 0x20
#define STR_FUNC_HEREDOC 0x40
#define STR_FUNC_XQUOTE 0x80
enum mrb_string_type {
str_not_parsing = (0),
str_squote = (STR_FUNC_PARSING),
str_dquote = (STR_FUNC_PARSING|STR_FUNC_EXPAND),
str_regexp = (STR_FUNC_PARSING|STR_FUNC_REGEXP|STR_FUNC_EXPAND),
str_sword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY),
str_dword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY|STR_FUNC_EXPAND),
str_ssym = (STR_FUNC_PARSING|STR_FUNC_SYMBOL),
str_ssymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY),
str_dsymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY|STR_FUNC_EXPAND),
str_heredoc = (STR_FUNC_PARSING|STR_FUNC_HEREDOC),
str_xquote = (STR_FUNC_PARSING|STR_FUNC_XQUOTE|STR_FUNC_EXPAND),
};
/* heredoc structure */
struct mrb_parser_heredoc_info {
mrb_bool allow_indent:1;
mrb_bool line_head:1;
enum mrb_string_type type;
const char *term;
int term_len;
mrb_ast_node *doc;
};
#define MRB_PARSER_TOKBUF_MAX (UINT16_MAX-1)
#define MRB_PARSER_TOKBUF_SIZE 256
/* parser structure */
struct mrb_parser_state {
mrb_state *mrb;
struct mrb_pool *pool;
mrb_ast_node *cells;
const char *s, *send;
#ifndef MRB_DISABLE_STDIO
FILE *f;
#endif
mrbc_context *cxt;
mrb_sym filename_sym;
uint16_t lineno;
int column;
enum mrb_lex_state_enum lstate;
mrb_ast_node *lex_strterm; /* (type nest_level beg . end) */
unsigned int cond_stack;
unsigned int cmdarg_stack;
int paren_nest;
int lpar_beg;
int in_def, in_single;
mrb_bool cmd_start:1;
mrb_ast_node *locals;
mrb_ast_node *pb;
char *tokbuf;
char buf[MRB_PARSER_TOKBUF_SIZE];
int tidx;
int tsiz;
mrb_ast_node *all_heredocs; /* list of mrb_parser_heredoc_info* */
mrb_ast_node *heredocs_from_nextline;
mrb_ast_node *parsing_heredoc;
mrb_ast_node *lex_strterm_before_heredoc;
void *ylval;
size_t nerr;
size_t nwarn;
mrb_ast_node *tree;
mrb_bool no_optimize:1;
mrb_bool capture_errors:1;
struct RProc *upper;
struct mrb_parser_message error_buffer[10];
struct mrb_parser_message warn_buffer[10];
mrb_sym* filename_table;
uint16_t filename_table_length;
uint16_t current_filename_index;
struct mrb_jmpbuf* jmp;
mrb_ast_node *nvars;
};
MRB_API struct mrb_parser_state* mrb_parser_new(mrb_state*);
MRB_API void mrb_parser_free(struct mrb_parser_state*);
MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*);
MRB_API mrb_sym mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx);
/* utility functions */
#ifndef MRB_DISABLE_STDIO
MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*);
#endif
MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*);
MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t,mrbc_context*);
MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*);
MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c);
/** program load functions
* Please note! Currently due to interactions with the GC calling these functions will
* leak one RProc object per function call.
* To prevent this save the current memory arena before calling and restore the arena
* right after, like so
* int ai = mrb_gc_arena_save(mrb);
* mrb_value status = mrb_load_string(mrb, buffer);
* mrb_gc_arena_restore(mrb, ai);
*/
#ifndef MRB_DISABLE_STDIO
MRB_API mrb_value mrb_load_file(mrb_state*,FILE*);
MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
#endif
MRB_API mrb_value mrb_load_string(mrb_state *mrb, const char *s);
MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, size_t len);
MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt);
MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *cxt);
/** @} */
MRB_END_DECL
#endif /* MRUBY_COMPILE_H */
+76
View File
@@ -0,0 +1,76 @@
/**
** @file mruby/data.h - Data class
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_DATA_H
#define MRUBY_DATA_H
#include "common.h"
/**
* Custom C wrapped data.
*
* Defining Ruby wrappers around native objects.
*/
MRB_BEGIN_DECL
/**
* Custom data type description.
*/
typedef struct mrb_data_type {
/** data type name */
const char *struct_name;
/** data type release function pointer */
void (*dfree)(mrb_state *mrb, void*);
} mrb_data_type;
struct RData {
MRB_OBJECT_HEADER;
struct iv_tbl *iv;
const mrb_data_type *type;
void *data;
};
MRB_API struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass, void *datap, const mrb_data_type *type);
#define Data_Wrap_Struct(mrb,klass,type,ptr)\
mrb_data_object_alloc(mrb,klass,ptr,type)
#define Data_Make_Struct(mrb,klass,strct,type,sval,data_obj) do { \
(data_obj) = Data_Wrap_Struct(mrb,klass,type,NULL);\
(sval) = (strct *)mrb_malloc(mrb, sizeof(strct)); \
{ static const strct zero = { 0 }; *(sval) = zero; };\
(data_obj)->data = (sval);\
} while (0)
#define RDATA(obj) ((struct RData *)(mrb_ptr(obj)))
#define DATA_PTR(d) (RDATA(d)->data)
#define DATA_TYPE(d) (RDATA(d)->type)
MRB_API void mrb_data_check_type(mrb_state *mrb, mrb_value, const mrb_data_type*);
MRB_API void *mrb_data_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*);
#define DATA_GET_PTR(mrb,obj,dtype,type) (type*)mrb_data_get_ptr(mrb,obj,dtype)
MRB_API void *mrb_data_check_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*);
#define DATA_CHECK_GET_PTR(mrb,obj,dtype,type) (type*)mrb_data_check_get_ptr(mrb,obj,dtype)
/* obsolete functions and macros */
#define mrb_data_check_and_get(mrb,obj,dtype) mrb_data_get_ptr(mrb,obj,dtype)
#define mrb_get_datatype(mrb,val,type) mrb_data_get_ptr(mrb, val, type)
#define mrb_check_datatype(mrb,val,type) mrb_data_get_ptr(mrb, val, type)
#define Data_Get_Struct(mrb,obj,type,sval) do {\
*(void**)&sval = mrb_data_get_ptr(mrb, obj, type); \
} while (0)
MRB_INLINE void
mrb_data_init(mrb_value v, void *ptr, const mrb_data_type *type)
{
mrb_assert(mrb_data_p(v));
DATA_PTR(v) = ptr;
DATA_TYPE(v) = type;
}
MRB_END_DECL
#endif /* MRUBY_DATA_H */
+66
View File
@@ -0,0 +1,66 @@
/**
** @file mruby/debug.h - mruby debug info
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_DEBUG_H
#define MRUBY_DEBUG_H
#include "common.h"
/**
* MRuby Debugging.
*/
MRB_BEGIN_DECL
typedef enum mrb_debug_line_type {
mrb_debug_line_ary = 0,
mrb_debug_line_flat_map = 1
} mrb_debug_line_type;
typedef struct mrb_irep_debug_info_line {
uint32_t start_pos;
uint16_t line;
} mrb_irep_debug_info_line;
typedef struct mrb_irep_debug_info_file {
uint32_t start_pos;
mrb_sym filename_sym;
uint32_t line_entry_count;
mrb_debug_line_type line_type;
union {
void *ptr;
mrb_irep_debug_info_line *flat_map;
uint16_t *ary;
} lines;
} mrb_irep_debug_info_file;
typedef struct mrb_irep_debug_info {
uint32_t pc_count;
uint16_t flen;
mrb_irep_debug_info_file **files;
} mrb_irep_debug_info;
/*
* get line from irep's debug info and program counter
* @return returns NULL if not found
*/
MRB_API const char *mrb_debug_get_filename(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc);
/*
* get line from irep's debug info and program counter
* @return returns -1 if not found
*/
MRB_API int32_t mrb_debug_get_line(mrb_state *mrb, mrb_irep *irep, ptrdiff_t pc);
MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep);
MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file(
mrb_state *mrb, mrb_irep_debug_info *info,
const char *filename, uint16_t *lines,
uint32_t start_pos, uint32_t end_pos);
MRB_API void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d);
MRB_END_DECL
#endif /* MRUBY_DEBUG_H */
+176
View File
@@ -0,0 +1,176 @@
/**
** @file mruby/dump.h - mruby binary dumper (mrbc binary format)
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_DUMP_H
#define MRUBY_DUMP_H
#include <mruby.h>
#include <mruby/irep.h>
#include "common.h"
/**
* Dumping compiled mruby script.
*/
MRB_BEGIN_DECL
#define DUMP_DEBUG_INFO 1
int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
#ifndef MRB_DISABLE_STDIO
int mrb_dump_irep_binary(mrb_state*, mrb_irep*, uint8_t, FILE*);
int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep*, uint8_t flags, FILE *f, const char *initname);
mrb_irep *mrb_read_irep_file(mrb_state*, FILE*);
MRB_API mrb_value mrb_load_irep_file(mrb_state*,FILE*);
MRB_API mrb_value mrb_load_irep_file_cxt(mrb_state*, FILE*, mrbc_context*);
#endif
MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*);
MRB_API mrb_irep *mrb_read_irep_buf(mrb_state*, const void*, size_t);
/* dump/load error code
*
* NOTE: MRB_DUMP_GENERAL_FAILURE is caused by
* unspecified issues like malloc failed.
*/
#define MRB_DUMP_OK 0
#define MRB_DUMP_GENERAL_FAILURE (-1)
#define MRB_DUMP_WRITE_FAULT (-2)
#define MRB_DUMP_READ_FAULT (-3)
#define MRB_DUMP_CRC_ERROR (-4)
#define MRB_DUMP_INVALID_FILE_HEADER (-5)
#define MRB_DUMP_INVALID_IREP (-6)
#define MRB_DUMP_INVALID_ARGUMENT (-7)
/* null symbol length */
#define MRB_DUMP_NULL_SYM_LEN 0xFFFF
/* Rite Binary File header */
#define RITE_BINARY_IDENT "RITE"
#define RITE_BINARY_FORMAT_VER "0007"
#define RITE_COMPILER_NAME "MATZ"
#define RITE_COMPILER_VERSION "0000"
#define RITE_VM_VER "0002"
#define RITE_BINARY_EOF "END\0"
#define RITE_SECTION_IREP_IDENT "IREP"
#define RITE_SECTION_DEBUG_IDENT "DBG\0"
#define RITE_SECTION_LV_IDENT "LVAR"
#define MRB_DUMP_DEFAULT_STR_LEN 128
#define MRB_DUMP_ALIGNMENT sizeof(uint32_t)
/* binary header */
struct rite_binary_header {
uint8_t binary_ident[4]; /* Binary Identifier */
uint8_t binary_version[4]; /* Binary Format Version */
uint8_t binary_crc[2]; /* Binary CRC */
uint8_t binary_size[4]; /* Binary Size */
uint8_t compiler_name[4]; /* Compiler name */
uint8_t compiler_version[4];
};
/* section header */
#define RITE_SECTION_HEADER \
uint8_t section_ident[4]; \
uint8_t section_size[4]
struct rite_section_header {
RITE_SECTION_HEADER;
};
struct rite_section_irep_header {
RITE_SECTION_HEADER;
uint8_t rite_version[4]; /* Rite Instruction Specification Version */
};
struct rite_section_debug_header {
RITE_SECTION_HEADER;
};
struct rite_section_lv_header {
RITE_SECTION_HEADER;
};
#define RITE_LV_NULL_MARK UINT16_MAX
struct rite_binary_footer {
RITE_SECTION_HEADER;
};
static inline size_t
uint8_to_bin(uint8_t s, uint8_t *bin)
{
*bin = s;
return sizeof(uint8_t);
}
static inline size_t
uint16_to_bin(uint16_t s, uint8_t *bin)
{
*bin++ = (s >> 8) & 0xff;
*bin = s & 0xff;
return sizeof(uint16_t);
}
static inline size_t
uint32_to_bin(uint32_t l, uint8_t *bin)
{
*bin++ = (l >> 24) & 0xff;
*bin++ = (l >> 16) & 0xff;
*bin++ = (l >> 8) & 0xff;
*bin = l & 0xff;
return sizeof(uint32_t);
}
static inline size_t
uint32l_to_bin(uint32_t l, uint8_t *bin)
{
bin[3] = (l >> 24) & 0xff;
bin[2] = (l >> 16) & 0xff;
bin[1] = (l >> 8) & 0xff;
bin[0] = l & 0xff;
return sizeof(uint32_t);
}
static inline uint32_t
bin_to_uint32(const uint8_t *bin)
{
return (uint32_t)bin[0] << 24 |
(uint32_t)bin[1] << 16 |
(uint32_t)bin[2] << 8 |
(uint32_t)bin[3];
}
static inline uint32_t
bin_to_uint32l(const uint8_t *bin)
{
return (uint32_t)bin[3] << 24 |
(uint32_t)bin[2] << 16 |
(uint32_t)bin[1] << 8 |
(uint32_t)bin[0];
}
static inline uint16_t
bin_to_uint16(const uint8_t *bin)
{
return (uint16_t)bin[0] << 8 |
(uint16_t)bin[1];
}
static inline uint8_t
bin_to_uint8(const uint8_t *bin)
{
return (uint8_t)bin[0];
}
MRB_END_DECL
/** @internal crc.c */
uint16_t
calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc);
#endif /* MRUBY_DUMP_H */
+103
View File
@@ -0,0 +1,103 @@
/**
** @file mruby/error.h - Exception class
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_ERROR_H
#define MRUBY_ERROR_H
#include "common.h"
/**
* MRuby error handling.
*/
MRB_BEGIN_DECL
struct RException {
MRB_OBJECT_HEADER;
struct iv_tbl *iv;
};
#define mrb_exc_ptr(v) ((struct RException*)mrb_ptr(v))
MRB_API void mrb_sys_fail(mrb_state *mrb, const char *mesg);
MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str);
#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit))
MRB_API mrb_value mrb_make_exception(mrb_state *mrb, mrb_int argc, const mrb_value *argv);
MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb);
MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...);
/* declaration for `fail` method */
MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value);
#if defined(MRB_64BIT) || defined(MRB_USE_FLOAT) || defined(MRB_NAN_BOXING) || defined(MRB_WORD_BOXING)
struct RBreak {
MRB_OBJECT_HEADER;
struct RProc *proc;
mrb_value val;
};
#define mrb_break_value_get(brk) ((brk)->val)
#define mrb_break_value_set(brk, v) ((brk)->val = v)
#else
struct RBreak {
MRB_OBJECT_HEADER;
struct RProc *proc;
union mrb_value_union value;
};
#define RBREAK_VALUE_TT_MASK ((1 << 8) - 1)
static inline mrb_value
mrb_break_value_get(struct RBreak *brk)
{
mrb_value val;
val.value = brk->value;
val.tt = (enum mrb_vtype)(brk->flags & RBREAK_VALUE_TT_MASK);
return val;
}
static inline void
mrb_break_value_set(struct RBreak *brk, mrb_value val)
{
brk->value = val.value;
brk->flags &= ~RBREAK_VALUE_TT_MASK;
brk->flags |= val.tt;
}
#endif /* MRB_64BIT || MRB_USE_FLOAT || MRB_NAN_BOXING || MRB_WORD_BOXING */
#define mrb_break_proc_get(brk) ((brk)->proc)
#define mrb_break_proc_set(brk, p) ((brk)->proc = p)
/**
* Protect
*
* Implemented in the mruby-error mrbgem
*/
MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state);
/**
* Ensure
*
* Implemented in the mruby-error mrbgem
*/
MRB_API mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
mrb_func_t ensure, mrb_value e_data);
/**
* Rescue
*
* Implemented in the mruby-error mrbgem
*/
MRB_API mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
mrb_func_t rescue, mrb_value r_data);
/**
* Rescue exception
*
* Implemented in the mruby-error mrbgem
*/
MRB_API mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
mrb_func_t rescue, mrb_value r_data,
mrb_int len, struct RClass **classes);
MRB_END_DECL
#endif /* MRUBY_ERROR_H */
+91
View File
@@ -0,0 +1,91 @@
/**
** @file mruby/gc.h - garbage collector for mruby
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_GC_H
#define MRUBY_GC_H
#include "common.h"
/**
* Uncommon memory management stuffs.
*/
MRB_BEGIN_DECL
struct mrb_state;
#define MRB_EACH_OBJ_OK 0
#define MRB_EACH_OBJ_BREAK 1
typedef int (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data);
void mrb_objspace_each_objects(struct mrb_state *mrb, mrb_each_object_callback *callback, void *data);
MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c);
#ifndef MRB_GC_ARENA_SIZE
#define MRB_GC_ARENA_SIZE 100
#endif
typedef enum {
MRB_GC_STATE_ROOT = 0,
MRB_GC_STATE_MARK,
MRB_GC_STATE_SWEEP
} mrb_gc_state;
/* Disable MSVC warning "C4200: nonstandard extension used: zero-sized array
* in struct/union" when in C++ mode */
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4200)
#endif
typedef struct mrb_heap_page {
struct RBasic *freelist;
struct mrb_heap_page *prev;
struct mrb_heap_page *next;
struct mrb_heap_page *free_next;
struct mrb_heap_page *free_prev;
mrb_bool old:1;
void *objects[];
} mrb_heap_page;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
typedef struct mrb_gc {
mrb_heap_page *heaps; /* heaps for GC */
mrb_heap_page *sweeps;
mrb_heap_page *free_heaps;
size_t live; /* count of live objects */
#ifdef MRB_GC_FIXED_ARENA
struct RBasic *arena[MRB_GC_ARENA_SIZE]; /* GC protection array */
#else
struct RBasic **arena; /* GC protection array */
int arena_capa;
#endif
int arena_idx;
mrb_gc_state state; /* state of gc */
int current_white_part; /* make white object by white_part */
struct RBasic *gray_list; /* list of gray objects to be traversed incrementally */
struct RBasic *atomic_gray_list; /* list of objects to be traversed atomically */
size_t live_after_mark;
size_t threshold;
int interval_ratio;
int step_ratio;
mrb_bool iterating :1;
mrb_bool disabled :1;
mrb_bool full :1;
mrb_bool generational :1;
mrb_bool out_of_memory :1;
size_t majorgc_old_threshold;
} mrb_gc;
MRB_API mrb_bool
mrb_object_dead_p(struct mrb_state *mrb, struct RBasic *object);
MRB_END_DECL
#endif /* MRUBY_GC_H */
+222
View File
@@ -0,0 +1,222 @@
/**
** @file mruby/hash.h - Hash class
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_HASH_H
#define MRUBY_HASH_H
#include "common.h"
/**
* Hash class
*/
MRB_BEGIN_DECL
struct RHash {
MRB_OBJECT_HEADER;
struct iv_tbl *iv;
struct htable *ht;
};
#define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v)))
#define mrb_hash_value(p) mrb_obj_value((void*)(p))
MRB_API mrb_value mrb_hash_new_capa(mrb_state *mrb, mrb_int capa);
MRB_API mrb_value mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash);
MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
/*
* Initializes a new hash.
*
* Equivalent to:
*
* Hash.new
*
* @param mrb The mruby state reference.
* @return The initialized hash.
*/
MRB_API mrb_value mrb_hash_new(mrb_state *mrb);
/*
* Sets a keys and values to hashes.
*
* Equivalent to:
*
* hash[key] = val
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @param key The key to set.
* @param val The value to set.
* @return The value.
*/
MRB_API void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val);
/*
* Gets a value from a key. If the key is not found, the default of the
* hash is used.
*
* Equivalent to:
*
* hash[key]
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @param key The key to get.
* @return The found value.
*/
MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key);
/*
* Gets a value from a key. If the key is not found, the default parameter is
* used.
*
* Equivalent to:
*
* hash.key?(key) ? hash[key] : def
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @param key The key to get.
* @param def The default value.
* @return The found value.
*/
MRB_API mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def);
/*
* Deletes hash key and value pair.
*
* Equivalent to:
*
* hash.delete(key)
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @param key The key to delete.
* @return The deleted value. This value is not protected from GC. Use `mrb_gc_protect()` if necessary.
*/
MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key);
/*
* Gets an array of keys.
*
* Equivalent to:
*
* hash.keys
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @return An array with the keys of the hash.
*/
MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash);
/*
* Check if the hash has the key.
*
* Equivalent to:
*
* hash.key?(key)
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @param key The key to check existence.
* @return True if the hash has the key
*/
MRB_API mrb_bool mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key);
/*
* Check if the hash is empty
*
* Equivalent to:
*
* hash.empty?
*
* @param mrb The mruby state reference.
* @param self The target hash.
* @return True if the hash is empty, false otherwise.
*/
MRB_API mrb_bool mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
/*
* Gets an array of values.
*
* Equivalent to:
*
* hash.values
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @return An array with the values of the hash.
*/
MRB_API mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash);
/*
* Clears the hash.
*
* Equivalent to:
*
* hash.clear
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @return The hash
*/
MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash);
/*
* Get hash size.
*
* Equivalent to:
*
* hash.size
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @return The hash size.
*/
MRB_API mrb_int mrb_hash_size(mrb_state *mrb, mrb_value hash);
/*
* Copies the hash.
*
*
* @param mrb The mruby state reference.
* @param hash The target hash.
* @return The copy of the hash
*/
MRB_API mrb_value mrb_hash_dup(mrb_state *mrb, mrb_value hash);
/*
* Merges two hashes. The first hash will be modified by the
* second hash.
*
* @param mrb The mruby state reference.
* @param hash1 The target hash.
* @param hash2 Updating hash
*/
MRB_API void mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2);
/* RHASH_TBL allocates st_table if not available. */
#define RHASH(obj) ((struct RHash*)(mrb_ptr(obj)))
#define RHASH_TBL(h) (RHASH(h)->ht)
#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern_lit(mrb, "ifnone"))
#define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h)
#define MRB_HASH_DEFAULT 1
#define MRB_HASH_PROC_DEFAULT 2
#define MRB_RHASH_DEFAULT_P(h) (RHASH(h)->flags & MRB_HASH_DEFAULT)
#define MRB_RHASH_PROCDEFAULT_P(h) (RHASH(h)->flags & MRB_HASH_PROC_DEFAULT)
/* GC functions */
void mrb_gc_mark_hash(mrb_state*, struct RHash*);
size_t mrb_gc_mark_hash_size(mrb_state*, struct RHash*);
void mrb_gc_free_hash(mrb_state*, struct RHash*);
/* return non zero to break the loop */
typedef int (mrb_hash_foreach_func)(mrb_state *mrb, mrb_value key, mrb_value val, void *data);
MRB_API void mrb_hash_foreach(mrb_state *mrb, struct RHash *hash, mrb_hash_foreach_func *func, void *p);
MRB_END_DECL
#endif /* MRUBY_HASH_H */
+97
View File
@@ -0,0 +1,97 @@
/**
** @file mruby/irep.h - mrb_irep structure
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_IREP_H
#define MRUBY_IREP_H
#include "common.h"
#include <mruby/compile.h>
/**
* Compiled mruby scripts.
*/
MRB_BEGIN_DECL
enum irep_pool_type {
IREP_TT_STRING,
IREP_TT_FIXNUM,
IREP_TT_FLOAT,
};
struct mrb_locals {
mrb_sym name;
uint16_t r;
};
/* Program data array struct */
typedef struct mrb_irep {
uint16_t nlocals; /* Number of local variables */
uint16_t nregs; /* Number of register variables */
uint8_t flags;
const mrb_code *iseq;
mrb_value *pool;
mrb_sym *syms;
struct mrb_irep **reps;
struct mrb_locals *lv;
/* debug info */
struct mrb_irep_debug_info* debug_info;
uint16_t ilen, plen, slen, rlen;
uint32_t refcnt;
} mrb_irep;
#define MRB_ISEQ_NO_FREE 1
MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb);
/** load mruby bytecode functions
* Please note! Currently due to interactions with the GC calling these functions will
* leak one RProc object per function call.
* To prevent this save the current memory arena before calling and restore the arena
* right after, like so
* int ai = mrb_gc_arena_save(mrb);
* mrb_value status = mrb_load_irep(mrb, buffer);
* mrb_gc_arena_restore(mrb, ai);
*/
/* @param [const uint8_t*] irep code, expected as a literal */
MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*);
/*
* @param [const void*] irep code
* @param [size_t] size of irep buffer. If -1 is given, it is considered unrestricted.
*/
MRB_API mrb_value mrb_load_irep_buf(mrb_state*, const void*, size_t);
/* @param [const uint8_t*] irep code, expected as a literal */
MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*);
/*
* @param [const void*] irep code
* @param [size_t] size of irep buffer. If -1 is given, it is considered unrestricted.
*/
MRB_API mrb_value mrb_load_irep_buf_cxt(mrb_state*, const void*, size_t, mrbc_context*);
void mrb_irep_free(mrb_state*, struct mrb_irep*);
void mrb_irep_incref(mrb_state*, struct mrb_irep*);
void mrb_irep_decref(mrb_state*, struct mrb_irep*);
void mrb_irep_cutref(mrb_state*, struct mrb_irep*);
void mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep);
struct mrb_insn_data {
uint8_t insn;
uint16_t a;
uint16_t b;
uint8_t c;
};
struct mrb_insn_data mrb_decode_insn(const mrb_code *pc);
MRB_END_DECL
#endif /* MRUBY_IREP_H */
+50
View File
@@ -0,0 +1,50 @@
/**
** @file mruby/istruct.h - Inline structures
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_ISTRUCT_H
#define MRUBY_ISTRUCT_H
#include "common.h"
#include <string.h>
/**
* Inline structures that fit in RVALUE
*
* They cannot have finalizer, and cannot have instance variables.
*/
MRB_BEGIN_DECL
#define ISTRUCT_DATA_SIZE (sizeof(void*) * 3)
struct RIStruct {
MRB_OBJECT_HEADER;
union {
intptr_t inline_alignment[3];
char inline_data[ISTRUCT_DATA_SIZE];
};
};
#define RISTRUCT(obj) ((struct RIStruct*)(mrb_ptr(obj)))
#define ISTRUCT_PTR(obj) (RISTRUCT(obj)->inline_data)
MRB_INLINE mrb_int mrb_istruct_size()
{
return ISTRUCT_DATA_SIZE;
}
MRB_INLINE void* mrb_istruct_ptr(mrb_value object)
{
return ISTRUCT_PTR(object);
}
MRB_INLINE void mrb_istruct_copy(mrb_value dest, mrb_value src)
{
memcpy(ISTRUCT_PTR(dest), ISTRUCT_PTR(src), ISTRUCT_DATA_SIZE);
}
MRB_END_DECL
#endif /* MRUBY_ISTRUCT_H */
+292
View File
@@ -0,0 +1,292 @@
/**
** @file mruby/khash.h - Hash for mruby
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_KHASH_H
#define MRUBY_KHASH_H
#include <string.h>
#include <mruby.h>
#include "common.h"
/**
* khash definitions used in mruby's hash table.
*/
MRB_BEGIN_DECL
typedef uint32_t khint_t;
typedef khint_t khiter_t;
#ifndef KHASH_DEFAULT_SIZE
# define KHASH_DEFAULT_SIZE 32
#endif
#define KHASH_MIN_SIZE 8
#define UPPER_BOUND(x) ((x)>>2|(x)>>1)
/* extern uint8_t __m[]; */
/* mask for flags */
static const uint8_t __m_empty[] = {0x02, 0x08, 0x20, 0x80};
static const uint8_t __m_del[] = {0x01, 0x04, 0x10, 0x40};
static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0};
#define __ac_isempty(ed_flag, i) (ed_flag[(i)/4]&__m_empty[(i)%4])
#define __ac_isdel(ed_flag, i) (ed_flag[(i)/4]&__m_del[(i)%4])
#define __ac_iseither(ed_flag, i) (ed_flag[(i)/4]&__m_either[(i)%4])
#define khash_power2(v) do { \
v--;\
v |= v >> 1;\
v |= v >> 2;\
v |= v >> 4;\
v |= v >> 8;\
v |= v >> 16;\
v++;\
} while (0)
#define khash_mask(h) ((h)->n_buckets-1)
#define khash_upper_bound(h) (UPPER_BOUND((h)->n_buckets))
/* declare struct kh_xxx and kh_xxx_funcs
name: hash name
khkey_t: key data type
khval_t: value data type
kh_is_map: (0: hash set / 1: hash map)
*/
#define KHASH_DECLARE(name, khkey_t, khval_t, kh_is_map) \
typedef struct kh_##name { \
khint_t n_buckets; \
khint_t size; \
khint_t n_occupied; \
uint8_t *ed_flags; \
khkey_t *keys; \
khval_t *vals; \
} kh_##name##_t; \
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h); \
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size); \
kh_##name##_t *kh_init_##name(mrb_state *mrb); \
void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h); \
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h); \
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
static inline void
kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
{
while (len-- > 0) {
*p++ = c;
}
}
/* define kh_xxx_funcs
name: hash name
khkey_t: key data type
khval_t: value data type
kh_is_map: (0: hash set / 1: hash map)
__hash_func: hash function
__hash_equal: hash comparation function
*/
#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb); \
int kh_alloc_simple_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
khint_t sz = h->n_buckets; \
size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \
uint8_t *p = (uint8_t*)mrb_malloc_simple(mrb, sizeof(uint8_t)*sz/4+len*sz); \
if (!p) { return 1; } \
h->size = h->n_occupied = 0; \
h->keys = (khkey_t *)p; \
h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \
h->ed_flags = p+len*sz; \
kh_fill_flags(h->ed_flags, 0xaa, sz/4); \
return 0; \
} \
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
if (kh_alloc_simple_##name(mrb, h)) { \
mrb_raise_nomemory(mrb); \
} \
} \
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \
kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
if (size < KHASH_MIN_SIZE) \
size = KHASH_MIN_SIZE; \
khash_power2(size); \
h->n_buckets = size; \
if (kh_alloc_simple_##name(mrb, h)) { \
mrb_free(mrb, h); \
mrb_raise_nomemory(mrb); \
} \
return h; \
} \
kh_##name##_t *kh_init_##name(mrb_state *mrb) { \
return kh_init_##name##_size(mrb, KHASH_DEFAULT_SIZE); \
} \
void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
if (h) { \
mrb_free(mrb, h->keys); \
mrb_free(mrb, h); \
} \
} \
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
(void)mrb; \
if (h && h->ed_flags) { \
kh_fill_flags(h->ed_flags, 0xaa, h->n_buckets/4); \
h->size = h->n_occupied = 0; \
} \
} \
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key) \
{ \
khint_t k = __hash_func(mrb,key) & khash_mask(h), step = 0; \
(void)mrb; \
while (!__ac_isempty(h->ed_flags, k)) { \
if (!__ac_isdel(h->ed_flags, k)) { \
if (__hash_equal(mrb,h->keys[k], key)) return k; \
} \
k = (k+(++step)) & khash_mask(h); \
} \
return kh_end(h); \
} \
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets) \
{ \
if (new_n_buckets < KHASH_MIN_SIZE) \
new_n_buckets = KHASH_MIN_SIZE; \
khash_power2(new_n_buckets); \
{ \
kh_##name##_t hh; \
uint8_t *old_ed_flags = h->ed_flags; \
khkey_t *old_keys = h->keys; \
khval_t *old_vals = h->vals; \
khint_t old_n_buckets = h->n_buckets; \
khint_t i; \
hh.n_buckets = new_n_buckets; \
kh_alloc_##name(mrb, &hh); \
/* relocate */ \
for (i=0 ; i<old_n_buckets ; i++) { \
if (!__ac_iseither(old_ed_flags, i)) { \
khint_t k = kh_put_##name(mrb, &hh, old_keys[i], NULL); \
if (kh_is_map) kh_value(&hh,k) = old_vals[i]; \
} \
} \
/* copy hh to h */ \
*h = hh; \
mrb_free(mrb, old_keys); \
} \
} \
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
if (h->n_occupied >= khash_upper_bound(h)) { \
kh_resize_##name(mrb, h, h->n_buckets*2); \
} \
} \
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
{ \
khint_t k, del_k, step = 0; \
kh_put_prepare_##name(mrb, h); \
k = __hash_func(mrb,key) & khash_mask(h); \
del_k = kh_end(h); \
while (!__ac_isempty(h->ed_flags, k)) { \
if (!__ac_isdel(h->ed_flags, k)) { \
if (__hash_equal(mrb,h->keys[k], key)) { \
if (ret) *ret = 0; \
return k; \
} \
} \
else if (del_k == kh_end(h)) { \
del_k = k; \
} \
k = (k+(++step)) & khash_mask(h); \
} \
if (del_k != kh_end(h)) { \
/* put at del */ \
h->keys[del_k] = key; \
h->ed_flags[del_k/4] &= ~__m_del[del_k%4]; \
h->size++; \
if (ret) *ret = 2; \
return del_k; \
} \
else { \
/* put at empty */ \
h->keys[k] = key; \
h->ed_flags[k/4] &= ~__m_empty[k%4]; \
h->size++; \
h->n_occupied++; \
if (ret) *ret = 1; \
return k; \
} \
} \
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x) \
{ \
(void)mrb; \
mrb_assert(x != h->n_buckets && !__ac_iseither(h->ed_flags, x)); \
h->ed_flags[x/4] |= __m_del[x%4]; \
h->size--; \
} \
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
kh_##name##_t *h2; \
khiter_t k, k2; \
\
h2 = kh_init_##name(mrb); \
for (k = kh_begin(h); k != kh_end(h); k++) { \
if (kh_exist(h, k)) { \
k2 = kh_put_##name(mrb, h2, kh_key(h, k), NULL); \
if (kh_is_map) kh_value(h2, k2) = kh_value(h, k); \
} \
} \
return h2; \
}
#define khash_t(name) kh_##name##_t
#define kh_init_size(name,mrb,size) kh_init_##name##_size(mrb,size)
#define kh_init(name,mrb) kh_init_##name(mrb)
#define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h)
#define kh_clear(name, mrb, h) kh_clear_##name(mrb, h)
#define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s)
#define kh_put_prepare(name, mrb, h) kh_put_prepare_##name(mrb, h)
#define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL)
#define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r)
#define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k)
#define kh_del(name, mrb, h, k) kh_del_##name(mrb, h, k)
#define kh_copy(name, mrb, h) kh_copy_##name(mrb, h)
#define kh_exist(h, x) (!__ac_iseither((h)->ed_flags, (x)))
#define kh_key(h, x) ((h)->keys[x])
#define kh_val(h, x) ((h)->vals[x])
#define kh_value(h, x) ((h)->vals[x])
#define kh_begin(h) (khint_t)(0)
#define kh_end(h) ((h)->n_buckets)
#define kh_size(h) ((h)->size)
#define kh_n_buckets(h) ((h)->n_buckets)
#define kh_int_hash_func(mrb,key) (khint_t)((key)^((key)<<2)^((key)>>2))
#define kh_int_hash_equal(mrb,a, b) (a == b)
#define kh_int64_hash_func(mrb,key) (khint_t)((key)>>33^(key)^(key)<<11)
#define kh_int64_hash_equal(mrb,a, b) (a == b)
static inline khint_t __ac_X31_hash_string(const char *s)
{
khint_t h = *s;
if (h) for (++s ; *s; ++s) h = (h << 5) - h + *s;
return h;
}
#define kh_str_hash_func(mrb,key) __ac_X31_hash_string(key)
#define kh_str_hash_equal(mrb,a, b) (strcmp(a, b) == 0)
typedef const char *kh_cstr_t;
MRB_END_DECL
#endif /* MRUBY_KHASH_H */
+196
View File
@@ -0,0 +1,196 @@
/**
** @file mruby/numeric.h - Numeric, Integer, Float, Fixnum class
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_NUMERIC_H
#define MRUBY_NUMERIC_H
#include "common.h"
/**
* Numeric class and it's sub-classes.
*
* Integer, Float and Fixnum
*/
MRB_BEGIN_DECL
#define TYPED_POSFIXABLE(f,t) ((f) <= (t)MRB_INT_MAX)
#define TYPED_NEGFIXABLE(f,t) ((f) >= (t)MRB_INT_MIN)
#define TYPED_FIXABLE(f,t) (TYPED_POSFIXABLE(f,t) && TYPED_NEGFIXABLE(f,t))
#define POSFIXABLE(f) TYPED_POSFIXABLE(f,mrb_int)
#define NEGFIXABLE(f) TYPED_NEGFIXABLE(f,mrb_int)
#define FIXABLE(f) TYPED_FIXABLE(f,mrb_int)
#ifndef MRB_WITHOUT_FLOAT
#ifdef MRB_INT64
#define FIXABLE_FLOAT(f) ((f)>=-9223372036854775808.0 && (f)<9223372036854775808.0)
#else
#define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,mrb_float)
#endif
#endif
#ifndef MRB_WITHOUT_FLOAT
MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
#endif
MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base);
/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
#ifndef MRB_WITHOUT_FLOAT
MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
MRB_API int mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float f);
MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
MRB_API mrb_value mrb_int_value(mrb_state *mrb, mrb_float f);
#endif
MRB_API mrb_value mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y);
MRB_API mrb_value mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y);
MRB_API mrb_value mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y);
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#if (defined(__GNUC__) && __GNUC__ >= 5) || \
(__has_builtin(__builtin_add_overflow) && \
__has_builtin(__builtin_sub_overflow) && \
__has_builtin(__builtin_mul_overflow))
# define MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
#endif
/*
// Clang 3.8 and 3.9 have problem compiling mruby in 32-bit mode, when MRB_INT64 is set
// because of missing __mulodi4 and similar functions in its runtime. We need to use custom
// implementation for them.
*/
#ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
#if defined(__clang__) && (__clang_major__ == 3) && (__clang_minor__ >= 8) && \
defined(MRB_32BIT) && defined(MRB_INT64)
#undef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
#endif
#endif
#ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
#ifndef MRB_WORD_BOXING
# define WBCHK(x) 0
#else
# define WBCHK(x) !FIXABLE(x)
#endif
static inline mrb_bool
mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)
{
return __builtin_add_overflow(augend, addend, sum) || WBCHK(*sum);
}
static inline mrb_bool
mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
{
return __builtin_sub_overflow(minuend, subtrahend, difference) || WBCHK(*difference);
}
static inline mrb_bool
mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product)
{
return __builtin_mul_overflow(multiplier, multiplicand, product) || WBCHK(*product);
}
#undef WBCHK
#else
#define MRB_UINT_MAKE2(n) uint ## n ## _t
#define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n)
#define mrb_uint MRB_UINT_MAKE(MRB_INT_BIT)
#define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT))
static inline mrb_bool
mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)
{
mrb_uint x = (mrb_uint)augend;
mrb_uint y = (mrb_uint)addend;
mrb_uint z = (mrb_uint)(x + y);
*sum = (mrb_int)z;
return !!(((x ^ z) & (y ^ z)) & MRB_INT_OVERFLOW_MASK);
}
static inline mrb_bool
mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
{
mrb_uint x = (mrb_uint)minuend;
mrb_uint y = (mrb_uint)subtrahend;
mrb_uint z = (mrb_uint)(x - y);
*difference = (mrb_int)z;
return !!(((x ^ z) & (~y ^ z)) & MRB_INT_OVERFLOW_MASK);
}
static inline mrb_bool
mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product)
{
#if MRB_INT_BIT == 32
int64_t n = (int64_t)multiplier * multiplicand;
*product = (mrb_int)n;
return !FIXABLE(n);
#else
if (multiplier > 0) {
if (multiplicand > 0) {
if (multiplier > MRB_INT_MAX / multiplicand) return TRUE;
}
else {
if (multiplicand < MRB_INT_MAX / multiplier) return TRUE;
}
}
else {
if (multiplicand > 0) {
if (multiplier < MRB_INT_MAX / multiplicand) return TRUE;
}
else {
if (multiplier != 0 && multiplicand < MRB_INT_MAX / multiplier) return TRUE;
}
}
*product = multiplier * multiplicand;
return FALSE;
#endif
}
#undef MRB_INT_OVERFLOW_MASK
#undef mrb_uint
#undef MRB_UINT_MAKE
#undef MRB_UINT_MAKE2
#endif
#ifndef MRB_WITHOUT_FLOAT
# include <stdint.h>
# include <float.h>
# define MRB_FLT_RADIX FLT_RADIX
# ifdef MRB_USE_FLOAT
# define MRB_FLT_MANT_DIG FLT_MANT_DIG
# define MRB_FLT_EPSILON FLT_EPSILON
# define MRB_FLT_DIG FLT_DIG
# define MRB_FLT_MIN_EXP FLT_MIN_EXP
# define MRB_FLT_MIN FLT_MIN
# define MRB_FLT_MIN_10_EXP FLT_MIN_10_EXP
# define MRB_FLT_MAX_EXP FLT_MAX_EXP
# define MRB_FLT_MAX FLT_MAX
# define MRB_FLT_MAX_10_EXP FLT_MAX_10_EXP
# else /* not MRB_USE_FLOAT */
# define MRB_FLT_MANT_DIG DBL_MANT_DIG
# define MRB_FLT_EPSILON DBL_EPSILON
# define MRB_FLT_DIG DBL_DIG
# define MRB_FLT_MIN_EXP DBL_MIN_EXP
# define MRB_FLT_MIN DBL_MIN
# define MRB_FLT_MIN_10_EXP DBL_MIN_10_EXP
# define MRB_FLT_MAX_EXP DBL_MAX_EXP
# define MRB_FLT_MAX DBL_MAX
# define MRB_FLT_MAX_10_EXP DBL_MAX_10_EXP
# endif /* MRB_USE_FLOAT */
#endif /* MRB_WITHOUT_FLOAT */
MRB_END_DECL
#endif /* MRUBY_NUMERIC_H */
+43
View File
@@ -0,0 +1,43 @@
/**
** @file mruby/object.h - mruby object definition
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_OBJECT_H
#define MRUBY_OBJECT_H
#define MRB_OBJECT_HEADER \
struct RClass *c; \
struct RBasic *gcnext; \
enum mrb_vtype tt:8; \
uint32_t color:3; \
uint32_t flags:21
#define MRB_FLAG_TEST(obj, flag) ((obj)->flags & (flag))
struct RBasic {
MRB_OBJECT_HEADER;
};
#define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v)))
#define MRB_FL_OBJ_IS_FROZEN (1 << 20)
#define MRB_FROZEN_P(o) ((o)->flags & MRB_FL_OBJ_IS_FROZEN)
#define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FL_OBJ_IS_FROZEN)
#define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FL_OBJ_IS_FROZEN)
#define mrb_frozen_p(o) MRB_FROZEN_P(o)
struct RObject {
MRB_OBJECT_HEADER;
struct iv_tbl *iv;
};
#define mrb_obj_ptr(v) ((struct RObject*)(mrb_ptr(v)))
#define mrb_special_const_p(x) mrb_immediate_p(x)
struct RFiber {
MRB_OBJECT_HEADER;
struct mrb_context *cxt;
};
#endif /* MRUBY_OBJECT_H */
+69
View File
@@ -0,0 +1,69 @@
/**
** @file mruby/opcode.h - RiteVM operation codes
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_OPCODE_H
#define MRUBY_OPCODE_H
enum mrb_insn {
#define OPCODE(x,_) OP_ ## x,
#include "mruby/ops.h"
#undef OPCODE
};
#define OP_L_STRICT 1
#define OP_L_CAPTURE 2
#define OP_L_METHOD OP_L_STRICT
#define OP_L_LAMBDA (OP_L_STRICT|OP_L_CAPTURE)
#define OP_L_BLOCK OP_L_CAPTURE
#define OP_R_NORMAL 0
#define OP_R_BREAK 1
#define OP_R_RETURN 2
#define PEEK_B(pc) (*(pc))
#define PEEK_S(pc) ((pc)[0]<<8|(pc)[1])
#define PEEK_W(pc) ((pc)[0]<<16|(pc)[1]<<8|(pc)[2])
#define READ_B() PEEK_B(pc++)
#define READ_S() (pc+=2, PEEK_S(pc-2))
#define READ_W() (pc+=3, PEEK_W(pc-3))
#define FETCH_Z() /* nothing */
#define FETCH_B() do {a=READ_B();} while (0)
#define FETCH_BB() do {a=READ_B(); b=READ_B();} while (0)
#define FETCH_BBB() do {a=READ_B(); b=READ_B(); c=READ_B();} while (0)
#define FETCH_BS() do {a=READ_B(); b=READ_S();} while (0)
#define FETCH_S() do {a=READ_S();} while (0)
#define FETCH_W() do {a=READ_W();} while (0)
/* with OP_EXT1 (1st 16bit) */
#define FETCH_Z_1() FETCH_Z()
#define FETCH_B_1() FETCH_S()
#define FETCH_BB_1() do {a=READ_S(); b=READ_B();} while (0)
#define FETCH_BBB_1() do {a=READ_S(); b=READ_B(); c=READ_B();} while (0)
#define FETCH_BS_1() do {a=READ_S(); b=READ_S();} while (0)
#define FETCH_S_1() FETCH_S()
#define FETCH_W_1() FETCH_W()
/* with OP_EXT2 (2nd 16bit) */
#define FETCH_Z_2() FETCH_Z()
#define FETCH_B_2() FETCH_B()
#define FETCH_BB_2() do {a=READ_B(); b=READ_S();} while (0)
#define FETCH_BBB_2() do {a=READ_B(); b=READ_S(); c=READ_B();} while (0)
#define FETCH_BS_2() FETCH_BS()
#define FETCH_S_2() FETCH_S()
#define FETCH_W_2() FETCH_W()
/* with OP_EXT3 (1st & 2nd 16bit) */
#define FETCH_Z_3() FETCH_Z()
#define FETCH_B_3() FETCH_B()
#define FETCH_BB_3() do {a=READ_S(); b=READ_S();} while (0)
#define FETCH_BBB_3() do {a=READ_S(); b=READ_S(); c=READ_B();} while (0)
#define FETCH_BS_3() do {a=READ_S(); b=READ_S();} while (0)
#define FETCH_S_3() FETCH_S()
#define FETCH_W_3() FETCH_W()
#endif /* MRUBY_OPCODE_H */
+118
View File
@@ -0,0 +1,118 @@
/* operand types:
+ Z: no operand (Z,Z,Z,Z)
+ B: 8bit (B,S,B,B)
+ BB: 8+8bit (BB,SB,BS,SS)
+ BBB: 8+8+8bit (BBB,SBB,BSB,SSB)
+ BS: 8+16bit (BS,SS,BS,BS)
+ S: 16bit (S,S,S,S)
+ W: 24bit (W,W,W,W)
*/
/*-----------------------------------------------------------------------
operation code operands semantics
------------------------------------------------------------------------*/
OPCODE(NOP, Z) /* no operation */
OPCODE(MOVE, BB) /* R(a) = R(b) */
OPCODE(LOADL, BB) /* R(a) = Pool(b) */
OPCODE(LOADI, BB) /* R(a) = mrb_int(b) */
OPCODE(LOADINEG, BB) /* R(a) = mrb_int(-b) */
OPCODE(LOADI__1, B) /* R(a) = mrb_int(-1) */
OPCODE(LOADI_0, B) /* R(a) = mrb_int(0) */
OPCODE(LOADI_1, B) /* R(a) = mrb_int(1) */
OPCODE(LOADI_2, B) /* R(a) = mrb_int(2) */
OPCODE(LOADI_3, B) /* R(a) = mrb_int(3) */
OPCODE(LOADI_4, B) /* R(a) = mrb_int(4) */
OPCODE(LOADI_5, B) /* R(a) = mrb_int(5) */
OPCODE(LOADI_6, B) /* R(a) = mrb_int(6) */
OPCODE(LOADI_7, B) /* R(a) = mrb_int(7) */
OPCODE(LOADSYM, BB) /* R(a) = Syms(b) */
OPCODE(LOADNIL, B) /* R(a) = nil */
OPCODE(LOADSELF, B) /* R(a) = self */
OPCODE(LOADT, B) /* R(a) = true */
OPCODE(LOADF, B) /* R(a) = false */
OPCODE(GETGV, BB) /* R(a) = getglobal(Syms(b)) */
OPCODE(SETGV, BB) /* setglobal(Syms(b), R(a)) */
OPCODE(GETSV, BB) /* R(a) = Special[Syms(b)] */
OPCODE(SETSV, BB) /* Special[Syms(b)] = R(a) */
OPCODE(GETIV, BB) /* R(a) = ivget(Syms(b)) */
OPCODE(SETIV, BB) /* ivset(Syms(b),R(a)) */
OPCODE(GETCV, BB) /* R(a) = cvget(Syms(b)) */
OPCODE(SETCV, BB) /* cvset(Syms(b),R(a)) */
OPCODE(GETCONST, BB) /* R(a) = constget(Syms(b)) */
OPCODE(SETCONST, BB) /* constset(Syms(b),R(a)) */
OPCODE(GETMCNST, BB) /* R(a) = R(a)::Syms(b) */
OPCODE(SETMCNST, BB) /* R(a+1)::Syms(b) = R(a) */
OPCODE(GETUPVAR, BBB) /* R(a) = uvget(b,c) */
OPCODE(SETUPVAR, BBB) /* uvset(b,c,R(a)) */
OPCODE(JMP, S) /* pc=a */
OPCODE(JMPIF, BS) /* if R(a) pc=b */
OPCODE(JMPNOT, BS) /* if !R(a) pc=b */
OPCODE(JMPNIL, BS) /* if R(a)==nil pc=b */
OPCODE(ONERR, S) /* rescue_push(a) */
OPCODE(EXCEPT, B) /* R(a) = exc */
OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */
OPCODE(POPERR, B) /* a.times{rescue_pop()} */
OPCODE(RAISE, B) /* raise(R(a)) */
OPCODE(EPUSH, B) /* ensure_push(SEQ[a]) */
OPCODE(EPOP, B) /* A.times{ensure_pop().call} */
OPCODE(SENDV, BB) /* R(a) = call(R(a),Syms(b),*R(a+1)) */
OPCODE(SENDVB, BB) /* R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2)) */
OPCODE(SEND, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) */
OPCODE(SENDB, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c),&R(a+c+1)) */
OPCODE(CALL, Z) /* R(0) = self.call(frame.argc, frame.argv) */
OPCODE(SUPER, BB) /* R(a) = super(R(a+1),... ,R(a+b+1)) */
OPCODE(ARGARY, BS) /* R(a) = argument array (16=m5:r1:m5:d1:lv4) */
OPCODE(ENTER, W) /* arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1) */
OPCODE(KEY_P, BB) /* R(a) = kdict.key?(Syms(b)) # todo */
OPCODE(KEYEND, Z) /* raise unless kdict.empty? # todo */
OPCODE(KARG, BB) /* R(a) = kdict[Syms(b)]; kdict.delete(Syms(b)) # todo */
OPCODE(RETURN, B) /* return R(a) (normal) */
OPCODE(RETURN_BLK, B) /* return R(a) (in-block return) */
OPCODE(BREAK, B) /* break R(a) */
OPCODE(BLKPUSH, BS) /* R(a) = block (16=m5:r1:m5:d1:lv4) */
OPCODE(ADD, B) /* R(a) = R(a)+R(a+1) */
OPCODE(ADDI, BB) /* R(a) = R(a)+mrb_int(b) */
OPCODE(SUB, B) /* R(a) = R(a)-R(a+1) */
OPCODE(SUBI, BB) /* R(a) = R(a)-mrb_int(b) */
OPCODE(MUL, B) /* R(a) = R(a)*R(a+1) */
OPCODE(DIV, B) /* R(a) = R(a)/R(a+1) */
OPCODE(EQ, B) /* R(a) = R(a)==R(a+1) */
OPCODE(LT, B) /* R(a) = R(a)<R(a+1) */
OPCODE(LE, B) /* R(a) = R(a)<=R(a+1) */
OPCODE(GT, B) /* R(a) = R(a)>R(a+1) */
OPCODE(GE, B) /* R(a) = R(a)>=R(a+1) */
OPCODE(ARRAY, BB) /* R(a) = ary_new(R(a),R(a+1)..R(a+b)) */
OPCODE(ARRAY2, BBB) /* R(a) = ary_new(R(b),R(b+1)..R(b+c)) */
OPCODE(ARYCAT, B) /* ary_cat(R(a),R(a+1)) */
OPCODE(ARYPUSH, B) /* ary_push(R(a),R(a+1)) */
OPCODE(ARYDUP, B) /* R(a) = ary_dup(R(a)) */
OPCODE(AREF, BBB) /* R(a) = R(b)[c] */
OPCODE(ASET, BBB) /* R(a)[c] = R(b) */
OPCODE(APOST, BBB) /* *R(a),R(a+1)..R(a+c) = R(a)[b..] */
OPCODE(INTERN, B) /* R(a) = intern(R(a)) */
OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */
OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b*2-1)) */
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b*2)) */
OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */
OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */
OPCODE(RANGE_INC, B) /* R(a) = range_new(R(a),R(a+1),FALSE) */
OPCODE(RANGE_EXC, B) /* R(a) = range_new(R(a),R(a+1),TRUE) */
OPCODE(OCLASS, B) /* R(a) = ::Object */
OPCODE(CLASS, BB) /* R(a) = newclass(R(a),Syms(b),R(a+1)) */
OPCODE(MODULE, BB) /* R(a) = newmodule(R(a),Syms(b)) */
OPCODE(EXEC, BB) /* R(a) = blockexec(R(a),SEQ[b]) */
OPCODE(DEF, BB) /* R(a).newmethod(Syms(b),R(a+1)) */
OPCODE(ALIAS, BB) /* alias_method(target_class,Syms(a),Syms(b)) */
OPCODE(UNDEF, B) /* undef_method(target_class,Syms(a)) */
OPCODE(SCLASS, B) /* R(a) = R(a).singleton_class */
OPCODE(TCLASS, B) /* R(a) = target_class */
OPCODE(DEBUG, BBB) /* print a,b,c */
OPCODE(ERR, B) /* raise(LocalJumpError, Lit(a)) */
OPCODE(EXT1, Z) /* make 1st operand 16bit */
OPCODE(EXT2, Z) /* make 2nd operand 16bit */
OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */
OPCODE(STOP, Z) /* stop VM */
OPCODE(LOADI16, BS) /* R(a) = mrb_int(b) */
+142
View File
@@ -0,0 +1,142 @@
/**
** @file mruby/proc.h - Proc class
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_PROC_H
#define MRUBY_PROC_H
#include "common.h"
#include <mruby/irep.h>
/**
* Proc class
*/
MRB_BEGIN_DECL
struct REnv {
MRB_OBJECT_HEADER;
mrb_value *stack;
struct mrb_context *cxt;
mrb_sym mid;
};
/* flags (21bits): 1(close):1(touched):1(heap):8(cioff/bidx):8(stack_len) */
#define MRB_ENV_SET_LEN(e,len) ((e)->flags = (((e)->flags & ~0xff)|((unsigned int)(len) & 0xff)))
#define MRB_ENV_LEN(e) ((mrb_int)((e)->flags & 0xff))
#define MRB_ENV_CLOSED (1<<20)
#define MRB_ENV_TOUCHED (1<<19)
#define MRB_ENV_HEAPED (1<<18)
#define MRB_ENV_CLOSE(e) ((e)->flags |= MRB_ENV_CLOSED)
#define MRB_ENV_TOUCH(e) ((e)->flags |= MRB_ENV_TOUCHED)
#define MRB_ENV_HEAP(e) ((e)->flags |= MRB_ENV_HEAPED)
#define MRB_ENV_HEAP_P(e) ((e)->flags & MRB_ENV_HEAPED)
#define MRB_ENV_ONSTACK_P(e) (((e)->flags & MRB_ENV_CLOSED) == 0)
#define MRB_ENV_BIDX(e) (((e)->flags >> 8) & 0xff)
#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0xff<<8))|((unsigned int)(idx) & 0xff)<<8))
void mrb_env_unshare(mrb_state*, struct REnv*);
struct RProc {
MRB_OBJECT_HEADER;
union {
mrb_irep *irep;
mrb_func_t func;
} body;
struct RProc *upper;
union {
struct RClass *target_class;
struct REnv *env;
} e;
};
/* aspec access */
#define MRB_ASPEC_REQ(a) (((a) >> 18) & 0x1f)
#define MRB_ASPEC_OPT(a) (((a) >> 13) & 0x1f)
#define MRB_ASPEC_REST(a) (((a) >> 12) & 0x1)
#define MRB_ASPEC_POST(a) (((a) >> 7) & 0x1f)
#define MRB_ASPEC_KEY(a) (((a) >> 2) & 0x1f)
#define MRB_ASPEC_KDICT(a) ((a) & (1<<1))
#define MRB_ASPEC_BLOCK(a) ((a) & 1)
#define MRB_PROC_CFUNC_FL 128
#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC_FL) != 0)
#define MRB_PROC_CFUNC(p) (p)->body.func
#define MRB_PROC_STRICT 256
#define MRB_PROC_STRICT_P(p) (((p)->flags & MRB_PROC_STRICT) != 0)
#define MRB_PROC_ORPHAN 512
#define MRB_PROC_ORPHAN_P(p) (((p)->flags & MRB_PROC_ORPHAN) != 0)
#define MRB_PROC_ENVSET 1024
#define MRB_PROC_ENV_P(p) (((p)->flags & MRB_PROC_ENVSET) != 0)
#define MRB_PROC_ENV(p) (MRB_PROC_ENV_P(p) ? (p)->e.env : NULL)
#define MRB_PROC_TARGET_CLASS(p) (MRB_PROC_ENV_P(p) ? (p)->e.env->c : (p)->e.target_class)
#define MRB_PROC_SET_TARGET_CLASS(p,tc) do {\
if (MRB_PROC_ENV_P(p)) {\
(p)->e.env->c = (tc);\
mrb_field_write_barrier(mrb, (struct RBasic*)(p)->e.env, (struct RBasic*)(tc));\
}\
else {\
(p)->e.target_class = (tc);\
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)(tc));\
}\
} while (0)
#define MRB_PROC_SCOPE 2048
#define MRB_PROC_SCOPE_P(p) (((p)->flags & MRB_PROC_SCOPE) != 0)
#define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v)))
struct RProc *mrb_proc_new(mrb_state*, mrb_irep*);
struct RProc *mrb_closure_new(mrb_state*, mrb_irep*);
MRB_API struct RProc *mrb_proc_new_cfunc(mrb_state*, mrb_func_t);
MRB_API struct RProc *mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals);
void mrb_proc_copy(struct RProc *a, struct RProc *b);
mrb_int mrb_proc_arity(const struct RProc *p);
/* implementation of #send method */
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
/* following functions are defined in mruby-proc-ext so please include it when using */
MRB_API struct RProc *mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv);
MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx);
/* old name */
#define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx)
#define MRB_METHOD_FUNC_FL 1
#define MRB_METHOD_NOARG_FL 2
#ifndef MRB_METHOD_T_STRUCT
#define MRB_METHOD_FUNC_P(m) (((uintptr_t)(m))&MRB_METHOD_FUNC_FL)
#define MRB_METHOD_NOARG_P(m) (((uintptr_t)(m))&MRB_METHOD_NOARG_FL)
#define MRB_METHOD_NOARG_SET(m) ((m)=(mrb_method_t)(((uintptr_t)(m))|MRB_METHOD_NOARG_FL))
#define MRB_METHOD_FUNC(m) ((mrb_func_t)((uintptr_t)(m)>>2))
#define MRB_METHOD_FROM_FUNC(m,fn) ((m)=(mrb_method_t)((((uintptr_t)(fn))<<2)|MRB_METHOD_FUNC_FL))
#define MRB_METHOD_FROM_PROC(m,pr) ((m)=(mrb_method_t)(pr))
#define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
#define MRB_METHOD_PROC(m) ((struct RProc*)(m))
#define MRB_METHOD_UNDEF_P(m) ((m)==0)
#else
#define MRB_METHOD_FUNC_P(m) ((m).flags&MRB_METHOD_FUNC_FL)
#define MRB_METHOD_NOARG_P(m) ((m).flags&MRB_METHOD_NOARG_FL)
#define MRB_METHOD_FUNC(m) ((m).func)
#define MRB_METHOD_NOARG_SET(m) do{(m).flags|=MRB_METHOD_NOARG_FL;}while(0)
#define MRB_METHOD_FROM_FUNC(m,fn) do{(m).flags=MRB_METHOD_FUNC_FL;(m).func=(fn);}while(0)
#define MRB_METHOD_FROM_PROC(m,pr) do{(m).flags=0;(m).proc=(pr);}while(0)
#define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
#define MRB_METHOD_PROC(m) ((m).proc)
#define MRB_METHOD_UNDEF_P(m) ((m).proc==NULL)
#endif /* MRB_METHOD_T_STRUCT */
#define MRB_METHOD_CFUNC_P(m) (MRB_METHOD_FUNC_P(m)?TRUE:(MRB_METHOD_PROC(m)?(MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m))):FALSE))
#define MRB_METHOD_CFUNC(m) (MRB_METHOD_FUNC_P(m)?MRB_METHOD_FUNC(m):((MRB_METHOD_PROC(m)&&MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m)))?MRB_PROC_CFUNC(MRB_METHOD_PROC(m)):NULL))
#include <mruby/khash.h>
KHASH_DECLARE(mt, mrb_sym, mrb_method_t, TRUE)
MRB_END_DECL
#endif /* MRUBY_PROC_H */
+79
View File
@@ -0,0 +1,79 @@
/**
** @file mruby/range.h - Range class
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_RANGE_H
#define MRUBY_RANGE_H
#include "common.h"
/**
* Range class
*/
MRB_BEGIN_DECL
#if defined(MRB_NAN_BOXING) && defined(MRB_64BIT) || defined(MRB_WORD_BOXING)
# define MRB_RANGE_EMBED
#endif
#ifdef MRB_RANGE_EMBED
struct RRange {
MRB_OBJECT_HEADER;
mrb_value beg;
mrb_value end;
mrb_bool excl;
};
# define mrb_gc_free_range(mrb, p) ((void)0)
# define RANGE_BEG(p) ((p)->beg)
# define RANGE_END(p) ((p)->end)
#else
typedef struct mrb_range_edges {
mrb_value beg;
mrb_value end;
} mrb_range_edges;
struct RRange {
MRB_OBJECT_HEADER;
mrb_range_edges *edges;
mrb_bool excl;
};
# define mrb_gc_free_range(mrb, p) mrb_free(mrb, (p)->edges)
# define RANGE_BEG(p) ((p)->edges->beg)
# define RANGE_END(p) ((p)->edges->end)
#endif
#define mrb_range_beg(mrb, r) RANGE_BEG(mrb_range_ptr(mrb, r))
#define mrb_range_end(mrb, r) RANGE_END(mrb_range_ptr(mrb, r))
#define mrb_range_excl_p(mrb, r) RANGE_EXCL(mrb_range_ptr(mrb, r))
#define mrb_range_raw_ptr(r) ((struct RRange*)mrb_ptr(r))
#define mrb_range_value(p) mrb_obj_value((void*)(p))
#define RANGE_EXCL(p) ((p)->excl)
MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value range);
/*
* Initializes a Range.
*
* If the third parameter is FALSE then it includes the last value in the range.
* If the third parameter is TRUE then it excludes the last value in the range.
*
* @param start the beginning value.
* @param end the ending value.
* @param exclude represents the inclusion or exclusion of the last value.
*/
MRB_API mrb_value mrb_range_new(mrb_state *mrb, mrb_value start, mrb_value end, mrb_bool exclude);
enum mrb_range_beg_len {
MRB_RANGE_TYPE_MISMATCH = 0, /* (failure) not range */
MRB_RANGE_OK = 1, /* (success) range */
MRB_RANGE_OUT = 2 /* (failure) out of range */
};
MRB_API enum mrb_range_beg_len mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc);
mrb_value mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int));
void mrb_gc_mark_range(mrb_state *mrb, struct RRange *r);
MRB_END_DECL
#endif /* MRUBY_RANGE_H */
+16
View File
@@ -0,0 +1,16 @@
/**
** @file mruby/re.h - Regexp class
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_RE_H
#define MRUBY_RE_H
MRB_BEGIN_DECL
#define REGEXP_CLASS "Regexp"
MRB_END_DECL
#endif /* RE_H */
+474
View File
@@ -0,0 +1,474 @@
/**
** @file mruby/string.h - String class
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_STRING_H
#define MRUBY_STRING_H
#include "common.h"
/**
* String class
*/
MRB_BEGIN_DECL
extern const char mrb_digitmap[];
#define RSTRING_EMBED_LEN_MAX \
((mrb_int)(sizeof(void*) * 3 + sizeof(void*) - 32 / CHAR_BIT - 1))
struct RString {
MRB_OBJECT_HEADER;
union {
struct {
mrb_ssize len;
union {
mrb_ssize capa;
struct mrb_shared_string *shared;
struct RString *fshared;
} aux;
char *ptr;
} heap;
} as;
};
struct RStringEmbed {
MRB_OBJECT_HEADER;
char ary[];
};
#define RSTR_SET_TYPE_FLAG(s, type) (RSTR_UNSET_TYPE_FLAG(s), (s)->flags |= MRB_STR_##type)
#define RSTR_UNSET_TYPE_FLAG(s) ((s)->flags &= ~(MRB_STR_TYPE_MASK|MRB_STR_EMBED_LEN_MASK))
#define RSTR_EMBED_P(s) ((s)->flags & MRB_STR_EMBED)
#define RSTR_SET_EMBED_FLAG(s) ((s)->flags |= MRB_STR_EMBED)
#define RSTR_UNSET_EMBED_FLAG(s) ((s)->flags &= ~(MRB_STR_EMBED|MRB_STR_EMBED_LEN_MASK))
#define RSTR_SET_EMBED_LEN(s, n) do {\
size_t tmp_n = (n);\
(s)->flags &= ~MRB_STR_EMBED_LEN_MASK;\
(s)->flags |= (tmp_n) << MRB_STR_EMBED_LEN_SHIFT;\
} while (0)
#define RSTR_SET_LEN(s, n) do {\
if (RSTR_EMBED_P(s)) {\
RSTR_SET_EMBED_LEN((s),(n));\
}\
else {\
(s)->as.heap.len = (mrb_ssize)(n);\
}\
} while (0)
#define RSTR_EMBED_PTR(s) (((struct RStringEmbed*)(s))->ary)
#define RSTR_EMBED_LEN(s)\
(mrb_int)(((s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT)
#define RSTR_EMBEDDABLE_P(len) ((len) <= RSTRING_EMBED_LEN_MAX)
#define RSTR_PTR(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_PTR(s) : (s)->as.heap.ptr)
#define RSTR_LEN(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_LEN(s) : (s)->as.heap.len)
#define RSTR_CAPA(s) (RSTR_EMBED_P(s) ? RSTRING_EMBED_LEN_MAX : (s)->as.heap.aux.capa)
#define RSTR_SHARED_P(s) ((s)->flags & MRB_STR_SHARED)
#define RSTR_SET_SHARED_FLAG(s) ((s)->flags |= MRB_STR_SHARED)
#define RSTR_UNSET_SHARED_FLAG(s) ((s)->flags &= ~MRB_STR_SHARED)
#define RSTR_FSHARED_P(s) ((s)->flags & MRB_STR_FSHARED)
#define RSTR_SET_FSHARED_FLAG(s) ((s)->flags |= MRB_STR_FSHARED)
#define RSTR_UNSET_FSHARED_FLAG(s) ((s)->flags &= ~MRB_STR_FSHARED)
#define RSTR_NOFREE_P(s) ((s)->flags & MRB_STR_NOFREE)
#define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE)
#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
#ifdef MRB_UTF8_STRING
# define RSTR_ASCII_P(s) ((s)->flags & MRB_STR_ASCII)
# define RSTR_SET_ASCII_FLAG(s) ((s)->flags |= MRB_STR_ASCII)
# define RSTR_UNSET_ASCII_FLAG(s) ((s)->flags &= ~MRB_STR_ASCII)
# define RSTR_WRITE_ASCII_FLAG(s, v) (RSTR_UNSET_ASCII_FLAG(s), (s)->flags |= v)
# define RSTR_COPY_ASCII_FLAG(dst, src) RSTR_WRITE_ASCII_FLAG(dst, RSTR_ASCII_P(src))
#else
# define RSTR_ASCII_P(s) (void)0
# define RSTR_SET_ASCII_FLAG(s) (void)0
# define RSTR_UNSET_ASCII_FLAG(s) (void)0
# define RSTR_WRITE_ASCII_FLAG(s, v) (void)0
# define RSTR_COPY_ASCII_FLAG(dst, src) (void)0
#endif
#define RSTR_POOL_P(s) ((s)->flags & MRB_STR_POOL)
#define RSTR_SET_POOL_FLAG(s) ((s)->flags |= MRB_STR_POOL)
/**
* Returns a pointer from a Ruby string
*/
#define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s)))
#define RSTRING(s) mrb_str_ptr(s)
#define RSTRING_PTR(s) RSTR_PTR(RSTRING(s))
#define RSTRING_EMBED_LEN(s) RSTR_EMBED_LEN(RSTRING(s))
#define RSTRING_LEN(s) RSTR_LEN(RSTRING(s))
#define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s))
#define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s))
MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
#define RSTRING_CSTR(mrb,s) mrb_string_cstr(mrb, s)
#define MRB_STR_SHARED 1
#define MRB_STR_FSHARED 2
#define MRB_STR_NOFREE 4
#define MRB_STR_EMBED 8 /* type flags up to here */
#define MRB_STR_POOL 16 /* status flags from here */
#define MRB_STR_ASCII 32
#define MRB_STR_EMBED_LEN_SHIFT 6
#define MRB_STR_EMBED_LEN_BIT 5
#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BIT) - 1) << MRB_STR_EMBED_LEN_SHIFT)
#define MRB_STR_TYPE_MASK (MRB_STR_POOL - 1)
void mrb_gc_free_str(mrb_state*, struct RString*);
MRB_API void mrb_str_modify(mrb_state *mrb, struct RString *s);
/* mrb_str_modify() with keeping ASCII flag if set */
MRB_API void mrb_str_modify_keep_ascii(mrb_state *mrb, struct RString *s);
/**
* Finds the index of a substring in a string
*/
MRB_API mrb_int mrb_str_index(mrb_state *mrb, mrb_value str, const char *p, mrb_int len, mrb_int offset);
#define mrb_str_index_lit(mrb, str, lit, off) mrb_str_index(mrb, str, lit, mrb_strlen_lit(lit), off);
/**
* Appends self to other. Returns self as a concatenated string.
*
*
* Example:
*
* int
* main(int argc,
* char **argv)
* {
* // Variable declarations.
* mrb_value str1;
* mrb_value str2;
*
* mrb_state *mrb = mrb_open();
* if (!mrb)
* {
* // handle error
* }
*
* // Creates new Ruby strings.
* str1 = mrb_str_new_lit(mrb, "abc");
* str2 = mrb_str_new_lit(mrb, "def");
*
* // Concatenates str2 to str1.
* mrb_str_concat(mrb, str1, str2);
*
* // Prints new Concatenated Ruby string.
* mrb_p(mrb, str1);
*
* mrb_close(mrb);
* return 0;
* }
*
* Result:
*
* => "abcdef"
*
* @param mrb The current mruby state.
* @param self String to concatenate.
* @param other String to append to self.
* @return [mrb_value] Returns a new String appending other to self.
*/
MRB_API void mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other);
/**
* Adds two strings together.
*
*
* Example:
*
* int
* main(int argc,
* char **argv)
* {
* // Variable declarations.
* mrb_value a;
* mrb_value b;
* mrb_value c;
*
* mrb_state *mrb = mrb_open();
* if (!mrb)
* {
* // handle error
* }
*
* // Creates two Ruby strings from the passed in C strings.
* a = mrb_str_new_lit(mrb, "abc");
* b = mrb_str_new_lit(mrb, "def");
*
* // Prints both C strings.
* mrb_p(mrb, a);
* mrb_p(mrb, b);
*
* // Concatenates both Ruby strings.
* c = mrb_str_plus(mrb, a, b);
*
* // Prints new Concatenated Ruby string.
* mrb_p(mrb, c);
*
* mrb_close(mrb);
* return 0;
* }
*
*
* Result:
*
* => "abc" # First string
* => "def" # Second string
* => "abcdef" # First & Second concatenated.
*
* @param mrb The current mruby state.
* @param a First string to concatenate.
* @param b Second string to concatenate.
* @return [mrb_value] Returns a new String containing a concatenated to b.
*/
MRB_API mrb_value mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b);
/**
* Converts pointer into a Ruby string.
*
* @param mrb The current mruby state.
* @param p The pointer to convert to Ruby string.
* @return [mrb_value] Returns a new Ruby String.
*/
MRB_API mrb_value mrb_ptr_to_str(mrb_state *mrb, void *p);
/**
* Returns an object as a Ruby string.
*
* @param mrb The current mruby state.
* @param obj An object to return as a Ruby string.
* @return [mrb_value] An object as a Ruby string.
*/
MRB_API mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj);
/**
* Resizes the string's length. Returns the amount of characters
* in the specified by len.
*
* Example:
*
* int
* main(int argc,
* char **argv)
* {
* // Variable declaration.
* mrb_value str;
*
* mrb_state *mrb = mrb_open();
* if (!mrb)
* {
* // handle error
* }
* // Creates a new string.
* str = mrb_str_new_lit(mrb, "Hello, world!");
* // Returns 5 characters of
* mrb_str_resize(mrb, str, 5);
* mrb_p(mrb, str);
*
* mrb_close(mrb);
* return 0;
* }
*
* Result:
*
* => "Hello"
*
* @param mrb The current mruby state.
* @param str The Ruby string to resize.
* @param len The length.
* @return [mrb_value] An object as a Ruby string.
*/
MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len);
/**
* Returns a sub string.
*
* Example:
*
* int
* main(int argc,
* char const **argv)
* {
* // Variable declarations.
* mrb_value str1;
* mrb_value str2;
*
* mrb_state *mrb = mrb_open();
* if (!mrb)
* {
* // handle error
* }
* // Creates new string.
* str1 = mrb_str_new_lit(mrb, "Hello, world!");
* // Returns a sub-string within the range of 0..2
* str2 = mrb_str_substr(mrb, str1, 0, 2);
*
* // Prints sub-string.
* mrb_p(mrb, str2);
*
* mrb_close(mrb);
* return 0;
* }
*
* Result:
*
* => "He"
*
* @param mrb The current mruby state.
* @param str Ruby string.
* @param beg The beginning point of the sub-string.
* @param len The end point of the sub-string.
* @return [mrb_value] An object as a Ruby sub-string.
*/
MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
/**
* Returns a Ruby string type.
*
*
* @param mrb The current mruby state.
* @param str Ruby string.
* @return [mrb_value] A Ruby string.
*/
MRB_API mrb_value mrb_ensure_string_type(mrb_state *mrb, mrb_value str);
MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
/* obsolete: use mrb_ensure_string_type() instead */
MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str);
MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, size_t capa);
MRB_API mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa);
/* NULL terminated C string from mrb_value */
MRB_API const char *mrb_string_cstr(mrb_state *mrb, mrb_value str);
/* NULL terminated C string from mrb_value; `str` will be updated */
MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *str);
/* obslete: use RSTRING_PTR() */
MRB_API const char *mrb_string_value_ptr(mrb_state *mrb, mrb_value str);
/* obslete: use RSTRING_LEN() */
MRB_API mrb_int mrb_string_value_len(mrb_state *mrb, mrb_value str);
/**
* Duplicates a string object.
*
*
* @param mrb The current mruby state.
* @param str Ruby string.
* @return [mrb_value] Duplicated Ruby string.
*/
MRB_API mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str);
/**
* Returns a symbol from a passed in Ruby string.
*
* @param mrb The current mruby state.
* @param self Ruby string.
* @return [mrb_value] A symbol.
*/
MRB_API mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self);
MRB_API mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck);
MRB_API mrb_value mrb_cstr_to_inum(mrb_state *mrb, const char *s, mrb_int base, mrb_bool badcheck);
MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck);
MRB_API double mrb_cstr_to_dbl(mrb_state *mrb, const char *s, mrb_bool badcheck);
/**
* Returns a converted string type.
* For type checking, non converting `mrb_to_str` is recommended.
*/
MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str);
/**
* Returns true if the strings match and false if the strings don't match.
*
* @param mrb The current mruby state.
* @param str1 Ruby string to compare.
* @param str2 Ruby string to compare.
* @return [mrb_value] boolean value.
*/
MRB_API mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2);
/**
* Returns a concatenated string comprised of a Ruby string and a C string.
*
* @param mrb The current mruby state.
* @param str Ruby string.
* @param ptr A C string.
* @param len length of C string.
* @return [mrb_value] A Ruby string.
* @see mrb_str_cat_cstr
*/
MRB_API mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len);
/**
* Returns a concatenated string comprised of a Ruby string and a C string.
*
* @param mrb The current mruby state.
* @param str Ruby string.
* @param ptr A C string.
* @return [mrb_value] A Ruby string.
* @see mrb_str_cat
*/
MRB_API mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr);
MRB_API mrb_value mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2);
#define mrb_str_cat_lit(mrb, str, lit) mrb_str_cat(mrb, str, lit, mrb_strlen_lit(lit))
/**
* Adds str2 to the end of str1.
*/
MRB_API mrb_value mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2);
/**
* Returns 0 if both Ruby strings are equal. Returns a value < 0 if Ruby str1 is less than Ruby str2. Returns a value > 0 if Ruby str2 is greater than Ruby str1.
*/
MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
/**
* Returns a newly allocated C string from a Ruby string.
* This is an utility function to pass a Ruby string to C library functions.
*
* - Returned string does not contain any NUL characters (but terminator).
* - It raises an ArgumentError exception if Ruby string contains
* NUL characters.
* - Retured string will be freed automatically on next GC.
* - Caller can modify returned string without affecting Ruby string
* (e.g. it can be used for mkstemp(3)).
*
* @param mrb The current mruby state.
* @param str Ruby string. Must be an instance of String.
* @return [char *] A newly allocated C string.
*/
MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_pool(mrb_state *mrb, const char *s, mrb_int len, mrb_bool nofree);
uint32_t mrb_str_hash(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
/**
* Returns a printable version of str, surrounded by quote marks, with special characters escaped.
*/
mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str);
/* For backward compatibility */
#define mrb_str_cat2(mrb, str, ptr) mrb_str_cat_cstr(mrb, str, ptr)
#define mrb_str_buf_cat(mrb, str, ptr, len) mrb_str_cat(mrb, str, ptr, len)
#define mrb_str_buf_append(mrb, str, str2) mrb_str_cat_str(mrb, str, str2)
mrb_bool mrb_str_beg_len(mrb_int str_len, mrb_int *begp, mrb_int *lenp);
mrb_value mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
#ifdef MRB_UTF8_STRING
mrb_int mrb_utf8len(const char *str, const char *end);
mrb_int mrb_utf8_strlen(const char *str, mrb_int byte_len);
#endif
MRB_END_DECL
#endif /* MRUBY_STRING_H */
+55
View File
@@ -0,0 +1,55 @@
/**
** @file mruby/throw.h - mruby exception throwing handler
**
** See Copyright Notice in mruby.h
*/
#ifndef MRB_THROW_H
#define MRB_THROW_H
#if defined(MRB_ENABLE_CXX_ABI)
# if !defined(__cplusplus)
# error Trying to use C++ exception handling in C code
# endif
#endif
#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus)
#define MRB_TRY(buf) try {
#define MRB_CATCH(buf) } catch(mrb_jmpbuf_impl e) { if (e != (buf)->impl) { throw e; }
#define MRB_END_EXC(buf) }
#define MRB_THROW(buf) throw((buf)->impl)
typedef mrb_int mrb_jmpbuf_impl;
#else
#include <setjmp.h>
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define MRB_SETJMP _setjmp
#define MRB_LONGJMP _longjmp
#else
#define MRB_SETJMP setjmp
#define MRB_LONGJMP longjmp
#endif
#define MRB_TRY(buf) if (MRB_SETJMP((buf)->impl) == 0) {
#define MRB_CATCH(buf) } else {
#define MRB_END_EXC(buf) }
#define MRB_THROW(buf) MRB_LONGJMP((buf)->impl, 1);
#define mrb_jmpbuf_impl jmp_buf
#endif
struct mrb_jmpbuf {
mrb_jmpbuf_impl impl;
#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus)
static mrb_int jmpbuf_id;
mrb_jmpbuf() : impl(jmpbuf_id++) {}
#endif
};
#endif /* MRB_THROW_H */
+390
View File
@@ -0,0 +1,390 @@
/**
** @file mruby/value.h - mruby value definitions
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_VALUE_H
#define MRUBY_VALUE_H
#include "common.h"
/*
* MRuby Value definition functions and macros.
*/
MRB_BEGIN_DECL
/**
* mruby Symbol.
* @class mrb_sym
*
* You can create an mrb_sym by simply using mrb_str_intern() or mrb_intern_cstr()
*/
typedef uint32_t mrb_sym;
/**
* mruby Boolean.
* @class mrb_bool
*
*
* Used internally to represent boolean. Can be TRUE or FALSE.
* Not to be confused with Ruby's boolean classes, which can be
* obtained using mrb_false_value() and mrb_true_value()
*/
typedef uint8_t mrb_bool;
struct mrb_state;
#if defined _MSC_VER && _MSC_VER < 1800
# define PRIo64 "llo"
# define PRId64 "lld"
# define PRIu64 "llu"
# define PRIx64 "llx"
# define PRIo16 "ho"
# define PRId16 "hd"
# define PRIu16 "hu"
# define PRIx16 "hx"
# define PRIo32 "o"
# define PRId32 "d"
# define PRIu32 "u"
# define PRIx32 "x"
#else
# include <inttypes.h>
#endif
#if defined(MRB_INT64)
typedef int64_t mrb_int;
# define MRB_INT_BIT 64
# define MRB_INT_MIN (INT64_MIN>>MRB_FIXNUM_SHIFT)
# define MRB_INT_MAX (INT64_MAX>>MRB_FIXNUM_SHIFT)
# define MRB_PRIo PRIo64
# define MRB_PRId PRId64
# define MRB_PRIx PRIx64
#else
typedef int32_t mrb_int;
# define MRB_INT_BIT 32
# define MRB_INT_MIN (INT32_MIN>>MRB_FIXNUM_SHIFT)
# define MRB_INT_MAX (INT32_MAX>>MRB_FIXNUM_SHIFT)
# define MRB_PRIo PRIo32
# define MRB_PRId PRId32
# define MRB_PRIx PRIx32
#endif
#ifdef MRB_ENDIAN_BIG
# define MRB_ENDIAN_LOHI(a,b) a b
#else
# define MRB_ENDIAN_LOHI(a,b) b a
#endif
#ifndef MRB_WITHOUT_FLOAT
MRB_API double mrb_float_read(const char*, char**);
#ifdef MRB_USE_FLOAT
typedef float mrb_float;
#else
typedef double mrb_float;
#endif
#endif
#if defined _MSC_VER && _MSC_VER < 1900
# include <stdarg.h>
MRB_API int mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg);
MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...);
# define vsnprintf(s, n, format, arg) mrb_msvc_vsnprintf(s, n, format, arg)
# define snprintf(s, n, format, ...) mrb_msvc_snprintf(s, n, format, __VA_ARGS__)
# if _MSC_VER < 1800 && !defined MRB_WITHOUT_FLOAT
# include <float.h>
# define isfinite(n) _finite(n)
# define isnan _isnan
# define isinf(n) (!_finite(n) && !_isnan(n))
# define signbit(n) (_copysign(1.0, (n)) < 0.0)
static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
# define INFINITY (*(float *)&IEEE754_INFINITY_BITS_SINGLE)
# define NAN ((float)(INFINITY - INFINITY))
# endif
#endif
enum mrb_vtype {
MRB_TT_FALSE = 0,
MRB_TT_TRUE,
MRB_TT_FLOAT,
MRB_TT_FIXNUM,
MRB_TT_SYMBOL,
MRB_TT_UNDEF,
MRB_TT_CPTR,
MRB_TT_FREE,
MRB_TT_OBJECT,
MRB_TT_CLASS,
MRB_TT_MODULE,
MRB_TT_ICLASS,
MRB_TT_SCLASS,
MRB_TT_PROC,
MRB_TT_ARRAY,
MRB_TT_HASH,
MRB_TT_STRING,
MRB_TT_RANGE,
MRB_TT_EXCEPTION,
MRB_TT_ENV,
MRB_TT_DATA,
MRB_TT_FIBER,
MRB_TT_ISTRUCT,
MRB_TT_BREAK,
MRB_TT_MAXDEFINE
};
#include <mruby/object.h>
#ifdef MRB_DOCUMENTATION_BLOCK
/**
* @abstract
* MRuby value boxing.
*
* Actual implementation depends on configured boxing type.
*
* @see mruby/boxing_no.h Default boxing representation
* @see mruby/boxing_word.h Word representation
* @see mruby/boxing_nan.h Boxed double representation
*/
typedef void mrb_value;
#endif
#if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT))
struct RCptr {
MRB_OBJECT_HEADER;
void *p;
};
#endif
#if defined(MRB_NAN_BOXING)
#include "boxing_nan.h"
#elif defined(MRB_WORD_BOXING)
#include "boxing_word.h"
#else
#include "boxing_no.h"
#endif
#define MRB_SYMBOL_BIT (sizeof(mrb_sym) * CHAR_BIT - MRB_SYMBOL_SHIFT)
#define MRB_SYMBOL_MAX (UINT32_MAX >> MRB_SYMBOL_SHIFT)
#if INTPTR_MAX < MRB_INT_MAX
typedef intptr_t mrb_ssize;
# define MRB_SSIZE_MAX (INTPTR_MAX>>MRB_FIXNUM_SHIFT)
#else
typedef mrb_int mrb_ssize;
# define MRB_SSIZE_MAX MRB_INT_MAX
#endif
#ifndef mrb_immediate_p
#define mrb_immediate_p(o) (mrb_type(o) < MRB_TT_FREE)
#endif
#ifndef mrb_fixnum_p
#define mrb_fixnum_p(o) (mrb_type(o) == MRB_TT_FIXNUM)
#endif
#ifndef mrb_symbol_p
#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL)
#endif
#ifndef mrb_undef_p
#define mrb_undef_p(o) (mrb_type(o) == MRB_TT_UNDEF)
#endif
#ifndef mrb_nil_p
#define mrb_nil_p(o) (mrb_type(o) == MRB_TT_FALSE && !mrb_fixnum(o))
#endif
#ifndef mrb_false_p
#define mrb_false_p(o) (mrb_type(o) == MRB_TT_FALSE && !!mrb_fixnum(o))
#endif
#ifndef mrb_true_p
#define mrb_true_p(o) (mrb_type(o) == MRB_TT_TRUE)
#endif
#ifndef MRB_WITHOUT_FLOAT
#ifndef mrb_float_p
#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT)
#endif
#endif
#ifndef mrb_array_p
#define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY)
#endif
#ifndef mrb_string_p
#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING)
#endif
#ifndef mrb_hash_p
#define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH)
#endif
#ifndef mrb_cptr_p
#define mrb_cptr_p(o) (mrb_type(o) == MRB_TT_CPTR)
#endif
#ifndef mrb_exception_p
#define mrb_exception_p(o) (mrb_type(o) == MRB_TT_EXCEPTION)
#endif
#ifndef mrb_free_p
#define mrb_free_p(o) (mrb_type(o) == MRB_TT_FREE)
#endif
#ifndef mrb_object_p
#define mrb_object_p(o) (mrb_type(o) == MRB_TT_OBJECT)
#endif
#ifndef mrb_class_p
#define mrb_class_p(o) (mrb_type(o) == MRB_TT_CLASS)
#endif
#ifndef mrb_module_p
#define mrb_module_p(o) (mrb_type(o) == MRB_TT_MODULE)
#endif
#ifndef mrb_iclass_p
#define mrb_iclass_p(o) (mrb_type(o) == MRB_TT_ICLASS)
#endif
#ifndef mrb_sclass_p
#define mrb_sclass_p(o) (mrb_type(o) == MRB_TT_SCLASS)
#endif
#ifndef mrb_proc_p
#define mrb_proc_p(o) (mrb_type(o) == MRB_TT_PROC)
#endif
#ifndef mrb_range_p
#define mrb_range_p(o) (mrb_type(o) == MRB_TT_RANGE)
#endif
#ifndef mrb_env_p
#define mrb_env_p(o) (mrb_type(o) == MRB_TT_ENV)
#endif
#ifndef mrb_data_p
#define mrb_data_p(o) (mrb_type(o) == MRB_TT_DATA)
#endif
#ifndef mrb_fiber_p
#define mrb_fiber_p(o) (mrb_type(o) == MRB_TT_FIBER)
#endif
#ifndef mrb_istruct_p
#define mrb_istruct_p(o) (mrb_type(o) == MRB_TT_ISTRUCT)
#endif
#ifndef mrb_break_p
#define mrb_break_p(o) (mrb_type(o) == MRB_TT_BREAK)
#endif
#ifndef mrb_bool
#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE)
#endif
#define mrb_test(o) mrb_bool(o)
/**
* Returns a float in Ruby.
*
* Takes a float and boxes it into an mrb_value
*/
#ifndef MRB_WITHOUT_FLOAT
MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
{
mrb_value v;
(void) mrb;
SET_FLOAT_VALUE(mrb, v, f);
return v;
}
#endif
MRB_INLINE mrb_value
mrb_cptr_value(struct mrb_state *mrb, void *p)
{
mrb_value v;
(void) mrb;
SET_CPTR_VALUE(mrb,v,p);
return v;
}
/**
* Returns a fixnum in Ruby.
*
* Takes an integer and boxes it into an mrb_value
*/
MRB_INLINE mrb_value mrb_fixnum_value(mrb_int i)
{
mrb_value v;
SET_INT_VALUE(v, i);
return v;
}
MRB_INLINE mrb_value
mrb_symbol_value(mrb_sym i)
{
mrb_value v;
SET_SYM_VALUE(v, i);
return v;
}
MRB_INLINE mrb_value
mrb_obj_value(void *p)
{
mrb_value v;
SET_OBJ_VALUE(v, (struct RBasic*)p);
mrb_assert(p == mrb_ptr(v));
mrb_assert(((struct RBasic*)p)->tt == mrb_type(v));
return v;
}
/**
* Get a nil mrb_value object.
*
* @return
* nil mrb_value object reference.
*/
MRB_INLINE mrb_value mrb_nil_value(void)
{
mrb_value v;
SET_NIL_VALUE(v);
return v;
}
/**
* Returns false in Ruby.
*/
MRB_INLINE mrb_value mrb_false_value(void)
{
mrb_value v;
SET_FALSE_VALUE(v);
return v;
}
/**
* Returns true in Ruby.
*/
MRB_INLINE mrb_value mrb_true_value(void)
{
mrb_value v;
SET_TRUE_VALUE(v);
return v;
}
MRB_INLINE mrb_value
mrb_bool_value(mrb_bool boolean)
{
mrb_value v;
SET_BOOL_VALUE(v, boolean);
return v;
}
MRB_INLINE mrb_value
mrb_undef_value(void)
{
mrb_value v;
SET_UNDEF_VALUE(v);
return v;
}
#if defined(MRB_USE_ETEXT_EDATA) && !defined(MRB_USE_LINK_TIME_RO_DATA_P)
# ifdef __GNUC__
# warning MRB_USE_ETEXT_EDATA is deprecated. Define MRB_USE_LINK_TIME_RO_DATA_P instead.
# endif
# define MRB_USE_LINK_TIME_RO_DATA_P
#endif
#if defined(MRB_USE_CUSTOM_RO_DATA_P)
/* If you define `MRB_USE_CUSTOM_RO_DATA_P`, you must implement `mrb_ro_data_p()`. */
mrb_bool mrb_ro_data_p(const char *p);
#elif defined(MRB_USE_LINK_TIME_RO_DATA_P)
extern char __ehdr_start[];
extern char __init_array_start[];
static inline mrb_bool
mrb_ro_data_p(const char *p)
{
return __ehdr_start < p && p < __init_array_start;
}
#else
# define mrb_ro_data_p(p) FALSE
#endif
MRB_END_DECL
#endif /* MRUBY_VALUE_H */
+139
View File
@@ -0,0 +1,139 @@
/**
** @file mruby/variable.h - mruby variables
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_VARIABLE_H
#define MRUBY_VARIABLE_H
#include "common.h"
/**
* Functions to access mruby variables.
*/
MRB_BEGIN_DECL
typedef struct global_variable {
int counter;
mrb_value *data;
mrb_value (*getter)(void);
void (*setter)(void);
/* void (*marker)(); */
/* int block_trace; */
/* struct trace_var *trace; */
} global_variable;
struct global_entry {
global_variable *var;
mrb_sym id;
};
mrb_value mrb_vm_special_get(mrb_state*, mrb_sym);
void mrb_vm_special_set(mrb_state*, mrb_sym, mrb_value);
mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym);
void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value);
mrb_value mrb_vm_const_get(mrb_state*, mrb_sym);
void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value);
MRB_API mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym);
MRB_API void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value);
MRB_API mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym);
MRB_API void mrb_const_remove(mrb_state*, mrb_value, mrb_sym);
MRB_API mrb_bool mrb_iv_name_sym_p(mrb_state *mrb, mrb_sym sym);
MRB_API void mrb_iv_name_sym_check(mrb_state *mrb, mrb_sym sym);
MRB_API mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
MRB_API void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
MRB_API mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
MRB_API mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym);
MRB_API void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v);
MRB_API mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym);
MRB_API mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym);
MRB_API void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src);
MRB_API mrb_bool mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id);
/**
* Get a global variable. Will return nil if the var does not exist
*
* Example:
*
* !!!ruby
* # Ruby style
* var = $value
*
* !!!c
* // C style
* mrb_sym sym = mrb_intern_lit(mrb, "$value");
* mrb_value var = mrb_gv_get(mrb, sym);
*
* @param mrb The mruby state reference
* @param sym The name of the global variable
* @return The value of that global variable. May be nil
*/
MRB_API mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym);
/**
* Set a global variable
*
* Example:
*
* !!!ruby
* # Ruby style
* $value = "foo"
*
* !!!c
* // C style
* mrb_sym sym = mrb_intern_lit(mrb, "$value");
* mrb_gv_set(mrb, sym, mrb_str_new_lit("foo"));
*
* @param mrb The mruby state reference
* @param sym The name of the global variable
* @param val The value of the global variable
*/
MRB_API void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val);
/**
* Remove a global variable.
*
* Example:
*
* # Ruby style
* $value = nil
*
* // C style
* mrb_sym sym = mrb_intern_lit(mrb, "$value");
* mrb_gv_remove(mrb, sym);
*
* @param mrb The mruby state reference
* @param sym The name of the global variable
*/
MRB_API void mrb_gv_remove(mrb_state *mrb, mrb_sym sym);
MRB_API mrb_value mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym);
MRB_API void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v);
MRB_API void mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v);
MRB_API mrb_bool mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym);
mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*);
void mrb_obj_iv_set_force(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod);
mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self);
mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
mrb_value mrb_mod_class_variables(mrb_state*, mrb_value);
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
mrb_bool mrb_ident_p(const char *s, mrb_int len);
/* GC functions */
void mrb_gc_mark_gv(mrb_state*);
void mrb_gc_free_gv(mrb_state*);
void mrb_gc_mark_iv(mrb_state*, struct RObject*);
size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*);
void mrb_gc_free_iv(mrb_state*, struct RObject*);
/* return non zero to break the loop */
typedef int (mrb_iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
MRB_API void mrb_iv_foreach(mrb_state *mrb, mrb_value obj, mrb_iv_foreach_func *func, void *p);
MRB_END_DECL
#endif /* MRUBY_VARIABLE_H */
+124
View File
@@ -0,0 +1,124 @@
/**
** @file mruby/version.h - mruby version definition
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_VERSION_H
#define MRUBY_VERSION_H
#include "common.h"
/**
* mruby version definition macros
*/
MRB_BEGIN_DECL
/*
* A passed in expression.
*/
#define MRB_STRINGIZE0(expr) #expr
/*
* Passes in an expression to MRB_STRINGIZE0.
*/
#define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr)
/*
* The version of Ruby used by mruby.
*/
#define MRUBY_RUBY_VERSION "2.0"
/*
* Ruby engine.
*/
#define MRUBY_RUBY_ENGINE "mruby"
/*
* Major release version number.
*/
#define MRUBY_RELEASE_MAJOR 2
/*
* Minor release version number.
*/
#define MRUBY_RELEASE_MINOR 1
/*
* Tiny release version number.
*/
#define MRUBY_RELEASE_TEENY 2
/*
* The mruby version.
*/
#define MRUBY_VERSION MRB_STRINGIZE(MRUBY_RELEASE_MAJOR) "." MRB_STRINGIZE(MRUBY_RELEASE_MINOR) "." MRB_STRINGIZE(MRUBY_RELEASE_TEENY)
/*
* Release number.
*/
#define MRUBY_RELEASE_NO (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY)
/*
* Release year.
*/
#define MRUBY_RELEASE_YEAR 2020
/*
* Release month.
*/
#define MRUBY_RELEASE_MONTH 8
/*
* Release day.
*/
#define MRUBY_RELEASE_DAY 6
/*
* Release date as a string.
*/
#define MRUBY_RELEASE_DATE \
MRUBY_RELEASE_YEAR_STR "-" \
MRUBY_RELEASE_MONTH_STR "-" \
MRUBY_RELEASE_DAY_STR
#define MRUBY_RELEASE_YEAR_STR MRB_STRINGIZE(MRUBY_RELEASE_YEAR)
#if MRUBY_RELEASE_MONTH < 10
#define MRUBY_RELEASE_MONTH_STR "0" MRB_STRINGIZE(MRUBY_RELEASE_MONTH)
#else
#define MRUBY_RELEASE_MONTH_STR MRB_STRINGIZE(MRUBY_RELEASE_MONTH)
#endif
#if MRUBY_RELEASE_DAY < 10
#define MRUBY_RELEASE_DAY_STR "0" MRB_STRINGIZE(MRUBY_RELEASE_DAY)
#else
#define MRUBY_RELEASE_DAY_STR MRB_STRINGIZE(MRUBY_RELEASE_DAY)
#endif
/*
* The year mruby was first created.
*/
#define MRUBY_BIRTH_YEAR 2010
/*
* MRuby's authors.
*/
#define MRUBY_AUTHOR "mruby developers"
/*
* mruby's version, and release date.
*/
#define MRUBY_DESCRIPTION \
"mruby " MRUBY_VERSION \
" (" MRUBY_RELEASE_DATE ")" \
/*
* mruby's copyright information.
*/
#define MRUBY_COPYRIGHT \
"mruby - Copyright (c) " \
MRB_STRINGIZE(MRUBY_BIRTH_YEAR)"-" \
MRB_STRINGIZE(MRUBY_RELEASE_YEAR)" " \
MRUBY_AUTHOR \
MRB_END_DECL
#endif /* MRUBY_VERSION_H */
+29
View File
@@ -0,0 +1,29 @@
autoload :Pathname, 'pathname'
class Object
class << self
def attr_block(*syms)
syms.flatten.each do |sym|
class_eval "def #{sym}(&block);block.call(@#{sym}) if block_given?;@#{sym};end"
end
end
end
end
class String
def relative_path_from(dir)
Pathname.new(File.expand_path(self)).relative_path_from(Pathname.new(File.expand_path(dir))).to_s
end
def relative_path
relative_path_from(Dir.pwd)
end
end
def _pp(cmd, src, tgt=nil, options={})
return if Rake.verbose
width = 5
template = options[:indent] ? "%#{width*options[:indent]}s %s %s" : "%-#{width}s %s %s"
puts template % [cmd, src, tgt ? "-> #{tgt}" : nil]
end
+392
View File
@@ -0,0 +1,392 @@
require "mruby-core-ext"
require "mruby/build/load_gems"
require "mruby/build/command"
module MRuby
autoload :Gem, "mruby/gem"
autoload :Lockfile, "mruby/lockfile"
class << self
def targets
@targets ||= {}
end
def each_target(&block)
return to_enum(:each_target) if block.nil?
@targets.each do |key, target|
target.instance_eval(&block)
end
end
end
class Toolchain
class << self
attr_accessor :toolchains
end
def initialize(name, &block)
@name, @initializer = name.to_s, block
MRuby::Toolchain.toolchains[@name] = self
end
def setup(conf,params={})
conf.instance_exec(conf, params, &@initializer)
end
self.toolchains = {}
end
class Build
class << self
attr_accessor :current
end
include Rake::DSL
include LoadGems
attr_accessor :name, :bins, :exts, :file_separator, :build_dir, :gem_clone_dir
attr_reader :libmruby_objs, :gems, :toolchains, :gem_dir_to_repo_url
attr_writer :enable_bintest, :enable_test
alias libmruby libmruby_objs
COMPILERS = %w(cc cxx objc asm)
COMMANDS = COMPILERS + %w(linker archiver yacc gperf git exts mrbc)
attr_block MRuby::Build::COMMANDS
Exts = Struct.new(:object, :executable, :library)
def initialize(name='host', build_dir=nil, &block)
@name = name.to_s
unless MRuby.targets[@name]
if ENV['OS'] == 'Windows_NT'
@exts = Exts.new('.o', '.exe', '.a')
else
@exts = Exts.new('.o', '', '.a')
end
build_dir = build_dir || ENV['MRUBY_BUILD_DIR'] || "#{MRUBY_ROOT}/build"
@file_separator = '/'
@build_dir = "#{build_dir}/#{@name}"
@gem_clone_dir = "#{build_dir}/repos/#{@name}"
@cc = Command::Compiler.new(self, %w(.c))
@cxx = Command::Compiler.new(self, %w(.cc .cxx .cpp))
@objc = Command::Compiler.new(self, %w(.m))
@asm = Command::Compiler.new(self, %w(.S .asm))
@linker = Command::Linker.new(self)
@archiver = Command::Archiver.new(self)
@yacc = Command::Yacc.new(self)
@gperf = Command::Gperf.new(self)
@git = Command::Git.new(self)
@mrbc = Command::Mrbc.new(self)
@bins = []
@gems, @libmruby_objs = MRuby::Gem::List.new, []
@build_mrbtest_lib_only = false
@cxx_exception_enabled = false
@cxx_exception_disabled = false
@cxx_abi_enabled = false
@enable_bintest = false
@enable_test = false
@enable_lock = true
@toolchains = []
@gem_dir_to_repo_url = {}
MRuby.targets[@name] = self
end
MRuby::Build.current = MRuby.targets[@name]
MRuby.targets[@name].instance_eval(&block)
build_mrbc_exec if name == 'host'
build_mrbtest if test_enabled?
end
def debug_enabled?
@enable_debug
end
def enable_debug
compilers.each do |c|
c.defines += %w(MRB_DEBUG)
if toolchains.any? { |toolchain| toolchain == "gcc" }
c.flags += %w(-g3 -O0)
end
end
@mrbc.compile_options += ' -g'
@enable_debug = true
end
def disable_lock
@enable_lock = false
end
def lock_enabled?
Lockfile.enabled? && @enable_lock
end
def disable_cxx_exception
if @cxx_exception_enabled or @cxx_abi_enabled
raise "cxx_exception already enabled"
end
@cxx_exception_disabled = true
end
def enable_cxx_exception
return if @cxx_exception_enabled
return if @cxx_abi_enabled
if @cxx_exception_disabled
raise "cxx_exception disabled"
end
@cxx_exception_enabled = true
compilers.each { |c|
c.defines += %w(MRB_ENABLE_CXX_EXCEPTION)
c.flags << c.cxx_exception_flag
}
linker.command = cxx.command if toolchains.find { |v| v == 'gcc' }
end
def cxx_exception_enabled?
@cxx_exception_enabled
end
def cxx_abi_enabled?
@cxx_abi_enabled
end
def enable_cxx_abi
return if @cxx_abi_enabled
if @cxx_exception_enabled
raise "cxx_exception already enabled"
end
compilers.each { |c|
c.defines += %w(MRB_ENABLE_CXX_EXCEPTION MRB_ENABLE_CXX_ABI)
c.flags << c.cxx_compile_flag
c.flags = c.flags.flatten - c.cxx_invalid_flags.flatten
}
linker.command = cxx.command if toolchains.find { |v| v == 'gcc' }
@cxx_abi_enabled = true
end
def compile_as_cxx src, cxx_src, obj = nil, includes = []
obj = objfile(cxx_src) if obj.nil?
file cxx_src => [src, __FILE__] do |t|
mkdir_p File.dirname t.name
IO.write t.name, <<EOS
#define __STDC_CONSTANT_MACROS
#define __STDC_LIMIT_MACROS
#ifndef MRB_ENABLE_CXX_ABI
extern "C" {
#endif
#include "#{File.absolute_path src}"
#ifndef MRB_ENABLE_CXX_ABI
}
#endif
EOS
end
file obj => cxx_src do |t|
cxx.run t.name, t.prerequisites.first, [], ["#{MRUBY_ROOT}/src"] + includes
end
obj
end
def enable_bintest
@enable_bintest = true
end
def bintest_enabled?
@enable_bintest
end
def toolchain(name, params={})
name = name.to_s
tc = Toolchain.toolchains[name] || begin
path = "#{MRUBY_ROOT}/tasks/toolchains/#{name}.rake"
fail "Unknown #{name} toolchain" unless File.exist?(path)
load path
Toolchain.toolchains[name]
end
tc.setup(self, params)
@toolchains.unshift name
end
def primary_toolchain
@toolchains.first
end
def root
MRUBY_ROOT
end
def enable_test
@enable_test = true
end
def test_enabled?
@enable_test
end
def build_mrbtest
gem :core => 'mruby-test'
end
def build_mrbc_exec
gem :core => 'mruby-bin-mrbc'
end
def locks
Lockfile.build(@name)
end
def mrbcfile
return @mrbcfile if @mrbcfile
mrbc_build = MRuby.targets['host']
gems.each { |v| mrbc_build = self if v.name == 'mruby-bin-mrbc' }
@mrbcfile = mrbc_build.exefile("#{mrbc_build.build_dir}/bin/mrbc")
end
def compilers
COMPILERS.map do |c|
instance_variable_get("@#{c}")
end
end
def define_rules
compilers.each do |compiler|
if respond_to?(:enable_gems?) && enable_gems?
compiler.defines -= %w(DISABLE_GEMS)
else
compiler.defines += %w(DISABLE_GEMS)
end
compiler.define_rules build_dir, File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
end
end
def filename(name)
if name.is_a?(Array)
name.flatten.map { |n| filename(n) }
else
name.gsub('/', file_separator)
end
end
def exefile(name)
if name.is_a?(Array)
name.flatten.map { |n| exefile(n) }
elsif File.extname(name).empty?
"#{name}#{exts.executable}"
else
# `name` sometimes have (non-standard) extension (e.g. `.bat`).
name
end
end
def objfile(name)
if name.is_a?(Array)
name.flatten.map { |n| objfile(n) }
else
"#{name}#{exts.object}"
end
end
def libfile(name)
if name.is_a?(Array)
name.flatten.map { |n| libfile(n) }
else
"#{name}#{exts.library}"
end
end
def build_mrbtest_lib_only
@build_mrbtest_lib_only = true
end
def build_mrbtest_lib_only?
@build_mrbtest_lib_only
end
def verbose_flag
Rake.verbose ? ' -v' : ''
end
def run_test
puts ">>> Test #{name} <<<"
mrbtest = exefile("#{build_dir}/bin/mrbtest")
sh "#{filename mrbtest.relative_path}#{verbose_flag}"
puts
end
def run_bintest
puts ">>> Bintest #{name} <<<"
targets = @gems.select { |v| File.directory? "#{v.dir}/bintest" }.map { |v| filename v.dir }
targets << filename(".") if File.directory? "./bintest"
sh "ruby test/bintest.rb#{verbose_flag} #{targets.join ' '}"
end
def print_build_summary
puts "================================================"
puts " Config Name: #{@name}"
puts " Output Directory: #{self.build_dir.relative_path}"
puts " Binaries: #{@bins.join(', ')}" unless @bins.empty?
unless @gems.empty?
puts " Included Gems:"
gems = @gems.sort_by { |gem| gem.name }
gems.each do |gem|
gem_version = " - #{gem.version}" if gem.version != '0.0.0'
gem_summary = " - #{gem.summary}" if gem.summary
puts " #{gem.name}#{gem_version}#{gem_summary}"
puts " - Binaries: #{gem.bins.join(', ')}" unless gem.bins.empty?
end
end
puts "================================================"
puts
end
def libmruby_static
libfile("#{build_dir}/lib/libmruby")
end
def libmruby_core_static
libfile("#{build_dir}/lib/libmruby_core")
end
def libraries
[libmruby_static]
end
end # Build
class CrossBuild < Build
attr_block %w(test_runner)
# cross compiling targets for building native extensions.
# host - arch of where the built binary will run
# build - arch of the machine building the binary
attr_accessor :host_target, :build_target
def initialize(name, build_dir=nil, &block)
@endian = nil
@test_runner = Command::CrossTestRunner.new(self)
super
end
def mrbcfile
MRuby.targets['host'].exefile("#{MRuby.targets['host'].build_dir}/bin/mrbc")
end
def run_test
@test_runner.runner_options << verbose_flag
mrbtest = exefile("#{build_dir}/bin/mrbtest")
if (@test_runner.command == nil)
puts "You should run #{mrbtest} on target device."
puts
else
@test_runner.run(mrbtest)
end
end
end # CrossBuild
end # MRuby
+471
View File
@@ -0,0 +1,471 @@
require 'forwardable'
autoload :TSort, 'tsort'
autoload :Shellwords, 'shellwords'
module MRuby
module Gem
class << self
attr_accessor :current
end
LinkerConfig = Struct.new(:libraries, :library_paths, :flags, :flags_before_libraries, :flags_after_libraries)
class Specification
include Rake::DSL
extend Forwardable
def_delegators :@build, :filename, :objfile, :libfile, :exefile
attr_accessor :name, :dir, :build
alias mruby build
attr_accessor :build_config_initializer
attr_accessor :mrblib_dir, :objs_dir
attr_accessor :version
attr_accessor :description, :summary
attr_accessor :homepage
attr_accessor :licenses, :authors
alias :license= :licenses=
alias :author= :authors=
attr_accessor :rbfiles, :objs
attr_accessor :test_objs, :test_rbfiles, :test_args
attr_accessor :test_preload
attr_accessor :bins
attr_accessor :requirements
attr_reader :dependencies, :conflicts
attr_accessor :export_include_paths
attr_reader :generate_functions
attr_block MRuby::Build::COMMANDS
def initialize(name, &block)
@name = name
@initializer = block
@version = "0.0.0"
@mrblib_dir = "mrblib"
@objs_dir = "src"
MRuby::Gem.current = self
end
def setup
return if defined?(@linker) # return if already set up
MRuby::Gem.current = self
MRuby::Build::COMMANDS.each do |command|
instance_variable_set("@#{command}", @build.send(command).clone)
end
@linker = LinkerConfig.new([], [], [], [], [])
@rbfiles = Dir.glob("#{@dir}/#{@mrblib_dir}/**/*.rb").sort
@objs = Dir.glob("#{@dir}/#{@objs_dir}/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
objfile(f.relative_path_from(@dir).to_s.pathmap("#{build_dir}/%X"))
end
@test_rbfiles = Dir.glob("#{dir}/test/**/*.rb").sort
@test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X"))
end
@custom_test_init = !@test_objs.empty?
@test_preload = nil # 'test/assert.rb'
@test_args = {}
@bins = []
@requirements = []
@dependencies, @conflicts = [], []
@export_include_paths = []
@export_include_paths << "#{dir}/include" if File.directory? "#{dir}/include"
instance_eval(&@initializer)
@generate_functions = !(@rbfiles.empty? && @objs.empty?)
@objs << objfile("#{build_dir}/gem_init") if @generate_functions
if !name || !licenses || !authors
fail "#{name || dir} required to set name, license(s) and author(s)"
end
build.libmruby_objs << @objs
instance_eval(&@build_config_initializer) if @build_config_initializer
repo_url = build.gem_dir_to_repo_url[dir]
build.locks[repo_url]['version'] = version if repo_url
end
def setup_compilers
compilers.each do |compiler|
compiler.define_rules build_dir, "#{dir}"
compiler.defines << %Q[MRBGEM_#{funcname.upcase}_VERSION=#{version}]
compiler.include_paths << "#{dir}/include" if File.directory? "#{dir}/include"
end
define_gem_init_builder if @generate_functions
end
def for_windows?
if build.kind_of?(MRuby::CrossBuild)
return %w(x86_64-w64-mingw32 i686-w64-mingw32).include?(build.host_target)
elsif build.kind_of?(MRuby::Build)
return ('A'..'Z').to_a.any? { |vol| Dir.exist?("#{vol}:") }
end
return false
end
def add_dependency(name, *requirements)
default_gem = requirements.last.kind_of?(Hash) ? requirements.pop : nil
requirements = ['>= 0.0.0'] if requirements.empty?
requirements.flatten!
@dependencies << {:gem => name, :requirements => requirements, :default => default_gem}
end
def add_test_dependency(*args)
add_dependency(*args) if build.test_enabled? || build.bintest_enabled?
end
def add_conflict(name, *req)
@conflicts << {:gem => name, :requirements => req.empty? ? nil : req}
end
def build_dir
"#{build.build_dir}/mrbgems/#{name}"
end
def test_rbireps
"#{build_dir}/gem_test.c"
end
def search_package(name, version_query=nil)
package_query = name
package_query += " #{version_query}" if version_query
_pp "PKG-CONFIG", package_query
escaped_package_query = Shellwords.escape(package_query)
if system("pkg-config --exists #{escaped_package_query}")
cc.flags += [`pkg-config --cflags #{escaped_package_query}`.strip]
cxx.flags += [`pkg-config --cflags #{escaped_package_query}`.strip]
linker.flags_before_libraries += [`pkg-config --libs #{escaped_package_query}`.strip]
true
else
false
end
end
def funcname
@funcname ||= @name.gsub('-', '_')
end
def compilers
MRuby::Build::COMPILERS.map do |c|
instance_variable_get("@#{c}")
end
end
def define_gem_init_builder
file objfile("#{build_dir}/gem_init") => [ "#{build_dir}/gem_init.c", File.join(dir, "mrbgem.rake") ]
file "#{build_dir}/gem_init.c" => [build.mrbcfile, __FILE__] + [rbfiles].flatten do |t|
mkdir_p build_dir
generate_gem_init("#{build_dir}/gem_init.c")
end
end
def generate_gem_init(fname)
open(fname, 'w') do |f|
print_gem_init_header f
build.mrbc.run f, rbfiles, "gem_mrblib_irep_#{funcname}" unless rbfiles.empty?
f.puts %Q[void mrb_#{funcname}_gem_init(mrb_state *mrb);]
f.puts %Q[void mrb_#{funcname}_gem_final(mrb_state *mrb);]
f.puts %Q[]
f.puts %Q[void GENERATED_TMP_mrb_#{funcname}_gem_init(mrb_state *mrb) {]
f.puts %Q[ int ai = mrb_gc_arena_save(mrb);]
f.puts %Q[ mrb_#{funcname}_gem_init(mrb);] if objs != [objfile("#{build_dir}/gem_init")]
unless rbfiles.empty?
f.puts %Q[ mrb_load_irep(mrb, gem_mrblib_irep_#{funcname});]
f.puts %Q[ if (mrb->exc) {]
f.puts %Q[ mrb_print_error(mrb);]
f.puts %Q[ mrb_close(mrb);]
f.puts %Q[ exit(EXIT_FAILURE);]
f.puts %Q[ }]
end
f.puts %Q[ mrb_gc_arena_restore(mrb, ai);]
f.puts %Q[}]
f.puts %Q[]
f.puts %Q[void GENERATED_TMP_mrb_#{funcname}_gem_final(mrb_state *mrb) {]
f.puts %Q[ mrb_#{funcname}_gem_final(mrb);] if objs != [objfile("#{build_dir}/gem_init")]
f.puts %Q[}]
end
end # generate_gem_init
def print_gem_comment(f)
f.puts %Q[/*]
f.puts %Q[ * This file is loading the irep]
f.puts %Q[ * Ruby GEM code.]
f.puts %Q[ *]
f.puts %Q[ * IMPORTANT:]
f.puts %Q[ * This file was generated!]
f.puts %Q[ * All manual changes will get lost.]
f.puts %Q[ */]
end
def print_gem_init_header(f)
print_gem_comment(f)
f.puts %Q[#include <stdlib.h>] unless rbfiles.empty?
f.puts %Q[#include <mruby.h>]
f.puts %Q[#include <mruby/irep.h>] unless rbfiles.empty?
end
def print_gem_test_header(f)
print_gem_comment(f)
f.puts %Q[#include <stdio.h>]
f.puts %Q[#include <stdlib.h>]
f.puts %Q[#include <mruby.h>]
f.puts %Q[#include <mruby/irep.h>]
f.puts %Q[#include <mruby/variable.h>]
f.puts %Q[#include <mruby/hash.h>] unless test_args.empty?
end
def test_dependencies
[@name]
end
def custom_test_init?
@custom_test_init
end
def version_ok?(req_versions)
req_versions.map do |req|
cmp, ver = req.split
cmp_result = Version.new(version) <=> Version.new(ver)
case cmp
when '=' then cmp_result == 0
when '!=' then cmp_result != 0
when '>' then cmp_result == 1
when '<' then cmp_result == -1
when '>=' then cmp_result >= 0
when '<=' then cmp_result <= 0
when '~>'
Version.new(version).twiddle_wakka_ok?(Version.new(ver))
else
fail "Comparison not possible with '#{cmp}'"
end
end.all?
end
end # Specification
class Version
include Comparable
include Enumerable
def <=>(other)
ret = 0
own = to_enum
other.each do |oth|
begin
ret = own.next <=> oth
rescue StopIteration
ret = 0 <=> oth
end
break unless ret == 0
end
ret
end
# ~> compare algorithm
#
# Example:
# ~> 2 means >= 2.0.0 and < 3.0.0
# ~> 2.2 means >= 2.2.0 and < 3.0.0
# ~> 2.2.2 means >= 2.2.2 and < 2.3.0
def twiddle_wakka_ok?(other)
gr_or_eql = (self <=> other) >= 0
still_major_or_minor = (self <=> other.skip_major_or_minor) < 0
gr_or_eql and still_major_or_minor
end
def skip_major_or_minor
a = @ary.dup
a << 0 if a.size == 1 # ~> 2 can also be represented as ~> 2.0
a.slice!(-1)
a[-1] = a[-1].succ
a
end
def initialize(str)
@str = str
@ary = @str.split('.').map(&:to_i)
end
def each(&block); @ary.each(&block); end
def [](index); @ary[index]; end
def []=(index, value)
@ary[index] = value
@str = @ary.join('.')
end
def slice!(index)
@ary.slice!(index)
@str = @ary.join('.')
end
end # Version
class List
include Enumerable
def initialize
@ary = []
end
def each(&b)
@ary.each(&b)
end
def <<(gem)
unless @ary.detect {|g| g.dir == gem.dir }
@ary << gem
else
# GEM was already added to this list
end
end
def empty?
@ary.empty?
end
def default_gem_params dep
if dep[:default]; dep
elsif File.exist? "#{MRUBY_ROOT}/mrbgems/#{dep[:gem]}" # check core
{ :gem => dep[:gem], :default => { :core => dep[:gem] } }
else # fallback to mgem-list
{ :gem => dep[:gem], :default => { :mgem => dep[:gem] } }
end
end
def generate_gem_table build
gem_table = each_with_object({}) { |spec, h| h[spec.name] = spec }
default_gems = {}
each do |g|
g.dependencies.each do |dep|
default_gems[dep[:gem]] ||= default_gem_params(dep)
end
end
until default_gems.empty?
def_name, def_gem = default_gems.shift
next if gem_table[def_name]
spec = gem_table[def_name] = build.gem(def_gem[:default])
fail "Invalid gem name: #{spec.name} (Expected: #{def_name})" if spec.name != def_name
spec.setup
spec.dependencies.each do |dep|
default_gems[dep[:gem]] ||= default_gem_params(dep)
end
end
each do |g|
g.dependencies.each do |dep|
name = dep[:gem]
req_versions = dep[:requirements]
dep_g = gem_table[name]
# check each GEM dependency against all available GEMs
if dep_g.nil?
fail "The GEM '#{g.name}' depends on the GEM '#{name}' but it could not be found"
end
unless dep_g.version_ok? req_versions
fail "#{name} version should be #{req_versions.join(' and ')} but was '#{dep_g.version}'"
end
end
cfls = g.conflicts.select { |c|
cfl_g = gem_table[c[:gem]]
cfl_g and cfl_g.version_ok?(c[:requirements] || ['>= 0.0.0'])
}.map { |c| "#{c[:gem]}(#{gem_table[c[:gem]].version})" }
fail "Conflicts of gem `#{g.name}` found: #{cfls.join ', '}" unless cfls.empty?
end
gem_table
end
def tsort_dependencies ary, table, all_dependency_listed = false
unless all_dependency_listed
left = ary.dup
until left.empty?
v = left.pop
table[v].dependencies.each do |dep|
left.push dep[:gem]
ary.push dep[:gem]
end
end
end
ary.uniq!
table.instance_variable_set :@root_gems, ary
class << table
include TSort
def tsort_each_node &b
@root_gems.each &b
end
def tsort_each_child(n, &b)
fetch(n).dependencies.each do |v|
b.call v[:gem]
end
end
end
begin
table.tsort.map { |v| table[v] }
rescue TSort::Cyclic => e
fail "Circular mrbgem dependency found: #{e.message}"
end
end
def check(build)
gem_table = generate_gem_table build
@ary = tsort_dependencies gem_table.keys, gem_table, true
each(&:setup_compilers)
each do |g|
import_include_paths(g)
end
end
def import_include_paths(g)
gem_table = each_with_object({}) { |spec, h| h[spec.name] = spec }
g.dependencies.each do |dep|
dep_g = gem_table[dep[:gem]]
# We can do recursive call safely
# as circular dependency has already detected in the caller.
import_include_paths(dep_g)
dep_g.export_include_paths.uniq!
g.compilers.each do |compiler|
compiler.include_paths += dep_g.export_include_paths
g.export_include_paths += dep_g.export_include_paths
compiler.include_paths.uniq!
g.export_include_paths.uniq!
end
end
end
end # List
end # Gem
GemBox = Object.new
class << GemBox
attr_accessor :path
def new(&block); block.call(self); end
def config=(obj); @config = obj; end
def gem(gemdir, &block); @config.gem(gemdir, &block); end
def gembox(gemfile); @config.gembox(gemfile); end
end # GemBox
end # MRuby
+81
View File
@@ -0,0 +1,81 @@
autoload :YAML, 'yaml'
module MRuby
autoload :Source, 'mruby/source'
class Lockfile
class << self
def enable
@enabled = true
end
def disable
@enabled = false
end
def enabled?
@enabled
end
def build(target_name)
instance.build(target_name)
end
def write
instance.write if enabled?
end
def instance
@instance ||= new("#{MRUBY_CONFIG}.lock")
end
end
def initialize(filename)
@filename = filename
end
def build(target_name)
read[target_name] ||= {}
end
def write
locks = {"mruby_version" => mruby}
locks["builds"] = @builds if @builds
File.write(@filename, YAML.dump(locks))
end
private
def read
@builds ||= if File.exist?(@filename)
YAML.load_file(@filename)["builds"] || {}
else
{}
end
end
def shellquote(s)
if ENV['OS'] == 'Windows_NT'
"\"#{s}\""
else
"'#{s}'"
end
end
def mruby
mruby = {
'version' => MRuby::Source::MRUBY_VERSION,
'release_no' => MRuby::Source::MRUBY_RELEASE_NO,
}
git_dir = "#{MRUBY_ROOT}/.git"
if File.directory?(git_dir)
mruby['git_commit'] = `git --git-dir #{shellquote(git_dir)} --work-tree #{shellquote(MRUBY_ROOT)} rev-parse --verify HEAD`.strip
end
mruby
end
enable
end
end
+32
View File
@@ -0,0 +1,32 @@
require "pathname"
module MRuby
module Source
# MRuby's source root directory
ROOT = Pathname.new(File.expand_path('../../../',__FILE__))
# Reads a constant defined at version.h
MRUBY_READ_VERSION_CONSTANT = Proc.new do |name|
ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?\r?$/)[1]
end
MRUBY_RUBY_VERSION = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_VERSION']
MRUBY_RUBY_ENGINE = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_ENGINE']
MRUBY_RELEASE_MAJOR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MAJOR'])
MRUBY_RELEASE_MINOR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MINOR'])
MRUBY_RELEASE_TEENY = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_TEENY'])
MRUBY_VERSION = [MRUBY_RELEASE_MAJOR,MRUBY_RELEASE_MINOR,MRUBY_RELEASE_TEENY].join('.')
MRUBY_RELEASE_NO = (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY)
MRUBY_RELEASE_YEAR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_YEAR'])
MRUBY_RELEASE_MONTH = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MONTH'])
MRUBY_RELEASE_DAY = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_DAY'])
MRUBY_RELEASE_DATE = [MRUBY_RELEASE_YEAR,MRUBY_RELEASE_MONTH,MRUBY_RELEASE_DAY].join('.')
MRUBY_BIRTH_YEAR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_BIRTH_YEAR'])
MRUBY_AUTHOR = MRUBY_READ_VERSION_CONSTANT['MRUBY_AUTHOR']
end
end
+2
View File
@@ -0,0 +1,2 @@
#! /usr/bin/env ruby
exec "rake", *ARGV
+101
View File
@@ -0,0 +1,101 @@
MRuby::GemBox.new do |conf|
# Meta-programming features
conf.gem :core => "mruby-metaprog"
# Use standard IO/File class
conf.gem :core => "mruby-io"
# Use standard Array#pack, String#unpack methods
conf.gem :core => "mruby-pack"
# Use standard Kernel#sprintf method
conf.gem :core => "mruby-sprintf"
# Use standard print/puts/p
conf.gem :core => "mruby-print"
# Use standard Math module
conf.gem :core => "mruby-math"
# Use standard Time class
conf.gem :core => "mruby-time"
# Use standard Struct class
conf.gem :core => "mruby-struct"
# Use Comparable module extension
conf.gem :core => "mruby-compar-ext"
# Use Enumerable module extension
conf.gem :core => "mruby-enum-ext"
# Use String class extension
conf.gem :core => "mruby-string-ext"
# Use Numeric class extension
conf.gem :core => "mruby-numeric-ext"
# Use Array class extension
conf.gem :core => "mruby-array-ext"
# Use Hash class extension
conf.gem :core => "mruby-hash-ext"
# Use Range class extension
conf.gem :core => "mruby-range-ext"
# Use Proc class extension
conf.gem :core => "mruby-proc-ext"
# Use Symbol class extension
conf.gem :core => "mruby-symbol-ext"
# Use Random class
conf.gem :core => "mruby-random"
# Use Object class extension
conf.gem :core => "mruby-object-ext"
# Use ObjectSpace class
conf.gem :core => "mruby-objectspace"
# Use Fiber class
conf.gem :core => "mruby-fiber"
# Use Enumerator class (require mruby-fiber)
conf.gem :core => "mruby-enumerator"
# Use Enumerator::Lazy class (require mruby-enumerator)
conf.gem :core => "mruby-enum-lazy"
# Use toplevel object (main) methods extension
conf.gem :core => "mruby-toplevel-ext"
# Use Rational/Complex numbers
conf.gem :core => "mruby-rational"
conf.gem :core => "mruby-complex"
# Generate mirb command
conf.gem :core => "mruby-bin-mirb"
# Generate mruby command
conf.gem :core => "mruby-bin-mruby"
# Generate mruby-strip command
conf.gem :core => "mruby-bin-strip"
# Use Kernel module extension
conf.gem :core => "mruby-kernel-ext"
# Use class/module extension
conf.gem :core => "mruby-class-ext"
# Use Method/UnboundMethod class
conf.gem :core => "mruby-method"
# Use eval()
conf.gem :core => "mruby-eval"
# Use mruby-compiler to build other mrbgems
conf.gem :core => "mruby-compiler"
end
+9
View File
@@ -0,0 +1,9 @@
MRuby::GemBox.new do |conf|
conf.gem :core => "mruby-sprintf"
conf.gem :core => "mruby-print"
Dir.glob("#{root}/mrbgems/mruby-*/mrbgem.rake") do |x|
g = File.basename File.dirname x
conf.gem :core => g unless g =~ /^mruby-(print|sprintf|bin-debugger|test)$/
end
end
@@ -0,0 +1,5 @@
MRuby::Gem::Specification.new('mruby-array-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'Array class extension'
end
@@ -0,0 +1,946 @@
class Array
##
# call-seq:
# ary.uniq! -> ary or nil
# ary.uniq! { |item| ... } -> ary or nil
#
# Removes duplicate elements from +self+.
# Returns <code>nil</code> if no changes are made (that is, no
# duplicates are found).
#
# a = [ "a", "a", "b", "b", "c" ]
# a.uniq! #=> ["a", "b", "c"]
# b = [ "a", "b", "c" ]
# b.uniq! #=> nil
# c = [["student","sam"], ["student","george"], ["teacher","matz"]]
# c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
#
def uniq!(&block)
hash = {}
if block
self.each do |val|
key = block.call(val)
hash[key] = val unless hash.key?(key)
end
result = hash.values
else
hash = {}
self.each do |val|
hash[val] = val
end
result = hash.keys
end
if result.size == self.size
nil
else
self.replace(result)
end
end
##
# call-seq:
# ary.uniq -> new_ary
# ary.uniq { |item| ... } -> new_ary
#
# Returns a new array by removing duplicate values in +self+.
#
# a = [ "a", "a", "b", "b", "c" ]
# a.uniq #=> ["a", "b", "c"]
#
# b = [["student","sam"], ["student","george"], ["teacher","matz"]]
# b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
#
def uniq(&block)
ary = self.dup
ary.uniq!(&block)
ary
end
##
# call-seq:
# ary - other_ary -> new_ary
#
# Array Difference---Returns a new array that is a copy of
# the original array, removing any items that also appear in
# <i>other_ary</i>. (If you need set-like behavior, see the
# library class Set.)
#
# [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
#
def -(elem)
raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
hash = {}
array = []
idx = 0
len = elem.size
while idx < len
hash[elem[idx]] = true
idx += 1
end
idx = 0
len = size
while idx < len
v = self[idx]
array << v unless hash[v]
idx += 1
end
array
end
##
# call-seq:
# ary.difference(other_ary1, other_ary2, ...) -> new_ary
#
# Returns a new array that is a copy of the original array, removing all
# occurrences of any item that also appear in +other_ary+. The order is
# preserved from the original array.
#
def difference(*args)
ary = self
args.each do |x|
ary = ary - x
end
ary
end
##
# call-seq:
# ary | other_ary -> new_ary
#
# Set Union---Returns a new array by joining this array with
# <i>other_ary</i>, removing duplicates.
#
# [ "a", "b", "c" ] | [ "c", "d", "a" ]
# #=> [ "a", "b", "c", "d" ]
#
def |(elem)
raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
ary = self + elem
ary.uniq! or ary
end
##
# call-seq:
# ary.union(other_ary,...) -> new_ary
#
# Set Union---Returns a new array by joining this array with
# <i>other_ary</i>, removing duplicates.
#
# ["a", "b", "c"].union(["c", "d", "a"], ["a", "c", "e"])
# #=> ["a", "b", "c", "d", "e"]
#
def union(*args)
ary = self.dup
args.each do |x|
ary.concat(x)
ary.uniq!
end
ary
end
##
# call-seq:
# ary & other_ary -> new_ary
#
# Set Intersection---Returns a new array
# containing elements common to the two arrays, with no duplicates.
#
# [ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ]
#
def &(elem)
raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
hash = {}
array = []
idx = 0
len = elem.size
while idx < len
hash[elem[idx]] = true
idx += 1
end
idx = 0
len = size
while idx < len
v = self[idx]
if hash[v]
array << v
hash.delete v
end
idx += 1
end
array
end
##
# call-seq:
# ary.intersection(other_ary,...) -> new_ary
#
# Set Intersection---Returns a new array containing elements common to
# this array and <i>other_ary</i>s, removing duplicates. The order is
# preserved from the original array.
#
# [1, 2, 3].intersection([3, 4, 1], [1, 3, 5]) #=> [1, 3]
#
def intersection(*args)
ary = self
args.each do |x|
ary = ary & x
end
ary
end
##
# call-seq:
# ary.flatten -> new_ary
# ary.flatten(level) -> new_ary
#
# Returns a new array that is a one-dimensional flattening of this
# array (recursively). That is, for every element that is an array,
# extract its elements into the new array. If the optional
# <i>level</i> argument determines the level of recursion to flatten.
#
# s = [ 1, 2, 3 ] #=> [1, 2, 3]
# t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
# a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
# a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# a = [ 1, 2, [3, [4, 5] ] ]
# a.flatten(1) #=> [1, 2, 3, [4, 5]]
#
def flatten(depth=nil)
res = dup
res.flatten! depth
res
end
##
# call-seq:
# ary.flatten! -> ary or nil
# ary.flatten!(level) -> array or nil
#
# Flattens +self+ in place.
# Returns <code>nil</code> if no modifications were made (i.e.,
# <i>ary</i> contains no subarrays.) If the optional <i>level</i>
# argument determines the level of recursion to flatten.
#
# a = [ 1, 2, [3, [4, 5] ] ]
# a.flatten! #=> [1, 2, 3, 4, 5]
# a.flatten! #=> nil
# a #=> [1, 2, 3, 4, 5]
# a = [ 1, 2, [3, [4, 5] ] ]
# a.flatten!(1) #=> [1, 2, 3, [4, 5]]
#
def flatten!(depth=nil)
modified = false
ar = []
idx = 0
len = size
while idx < len
e = self[idx]
if e.is_a?(Array) && (depth.nil? || depth > 0)
ar += e.flatten(depth.nil? ? nil : depth - 1)
modified = true
else
ar << e
end
idx += 1
end
if modified
self.replace(ar)
else
nil
end
end
##
# call-seq:
# ary.compact -> new_ary
#
# Returns a copy of +self+ with all +nil+ elements removed.
#
# [ "a", nil, "b", nil, "c", nil ].compact
# #=> [ "a", "b", "c" ]
#
def compact
result = self.dup
result.compact!
result
end
##
# call-seq:
# ary.compact! -> ary or nil
#
# Removes +nil+ elements from the array.
# Returns +nil+ if no changes were made, otherwise returns
# <i>ary</i>.
#
# [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
# [ "a", "b", "c" ].compact! #=> nil
#
def compact!
result = self.select { |e| !e.nil? }
if result.size == self.size
nil
else
self.replace(result)
end
end
# for efficiency
def reverse_each(&block)
return to_enum :reverse_each unless block
i = self.size - 1
while i>=0
block.call(self[i])
i -= 1
end
self
end
##
# call-seq:
# ary.fetch(index) -> obj
# ary.fetch(index, default) -> obj
# ary.fetch(index) { |index| block } -> obj
#
# Tries to return the element at position +index+, but throws an IndexError
# exception if the referenced +index+ lies outside of the array bounds. This
# error can be prevented by supplying a second argument, which will act as a
# +default+ value.
#
# Alternatively, if a block is given it will only be executed when an
# invalid +index+ is referenced.
#
# Negative values of +index+ count from the end of the array.
#
# a = [ 11, 22, 33, 44 ]
# a.fetch(1) #=> 22
# a.fetch(-1) #=> 44
# a.fetch(4, 'cat') #=> "cat"
# a.fetch(100) { |i| puts "#{i} is out of bounds" }
# #=> "100 is out of bounds"
#
def fetch(n, ifnone=NONE, &block)
warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block
idx = n
if idx < 0
idx += size
end
if idx < 0 || size <= idx
return block.call(n) if block
if ifnone == NONE
raise IndexError, "index #{n} outside of array bounds: #{-size}...#{size}"
end
return ifnone
end
self[idx]
end
##
# call-seq:
# ary.fill(obj) -> ary
# ary.fill(obj, start [, length]) -> ary
# ary.fill(obj, range ) -> ary
# ary.fill { |index| block } -> ary
# ary.fill(start [, length] ) { |index| block } -> ary
# ary.fill(range) { |index| block } -> ary
#
# The first three forms set the selected elements of +self+ (which
# may be the entire array) to +obj+.
#
# A +start+ of +nil+ is equivalent to zero.
#
# A +length+ of +nil+ is equivalent to the length of the array.
#
# The last three forms fill the array with the value of the given block,
# which is passed the absolute index of each element to be filled.
#
# Negative values of +start+ count from the end of the array, where +-1+ is
# the last element.
#
# a = [ "a", "b", "c", "d" ]
# a.fill("x") #=> ["x", "x", "x", "x"]
# a.fill("w", -1) #=> ["x", "x", "x", "w"]
# a.fill("z", 2, 2) #=> ["x", "x", "z", "z"]
# a.fill("y", 0..1) #=> ["y", "y", "z", "z"]
# a.fill { |i| i*i } #=> [0, 1, 4, 9]
# a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27]
# a.fill(1, 2) { |i| i+1 } #=> [0, 2, 3, 27]
# a.fill(0..1) { |i| i+1 } #=> [1, 2, 3, 27]
#
def fill(arg0=nil, arg1=nil, arg2=nil, &block)
if arg0.nil? && arg1.nil? && arg2.nil? && !block
raise ArgumentError, "wrong number of arguments (0 for 1..3)"
end
beg = len = 0
ary = []
if block
if arg0.nil? && arg1.nil? && arg2.nil?
# ary.fill { |index| block } -> ary
beg = 0
len = self.size
elsif !arg0.nil? && arg0.kind_of?(Range)
# ary.fill(range) { |index| block } -> ary
beg = arg0.begin
beg += self.size if beg < 0
len = arg0.end
len += self.size if len < 0
len += 1 unless arg0.exclude_end?
elsif !arg0.nil?
# ary.fill(start [, length] ) { |index| block } -> ary
beg = arg0
beg += self.size if beg < 0
if arg1.nil?
len = self.size
else
len = arg0 + arg1
end
end
else
if !arg0.nil? && arg1.nil? && arg2.nil?
# ary.fill(obj) -> ary
beg = 0
len = self.size
elsif !arg0.nil? && !arg1.nil? && arg1.kind_of?(Range)
# ary.fill(obj, range ) -> ary
beg = arg1.begin
beg += self.size if beg < 0
len = arg1.end
len += self.size if len < 0
len += 1 unless arg1.exclude_end?
elsif !arg0.nil? && !arg1.nil?
# ary.fill(obj, start [, length]) -> ary
beg = arg1
beg += self.size if beg < 0
if arg2.nil?
len = self.size
else
len = beg + arg2
end
end
end
i = beg
if block
while i < len
self[i] = block.call(i)
i += 1
end
else
while i < len
self[i] = arg0
i += 1
end
end
self
end
##
# call-seq:
# ary.rotate(count=1) -> new_ary
#
# Returns a new array by rotating +self+ so that the element at +count+ is
# the first element of the new array.
#
# If +count+ is negative then it rotates in the opposite direction, starting
# from the end of +self+ where +-1+ is the last element.
#
# a = [ "a", "b", "c", "d" ]
# a.rotate #=> ["b", "c", "d", "a"]
# a #=> ["a", "b", "c", "d"]
# a.rotate(2) #=> ["c", "d", "a", "b"]
# a.rotate(-3) #=> ["b", "c", "d", "a"]
def rotate(count=1)
ary = []
len = self.length
if len > 0
idx = (count < 0) ? (len - (~count % len) - 1) : (count % len) # rotate count
len.times do
ary << self[idx]
idx += 1
idx = 0 if idx > len-1
end
end
ary
end
##
# call-seq:
# ary.rotate!(count=1) -> ary
#
# Rotates +self+ in place so that the element at +count+ comes first, and
# returns +self+.
#
# If +count+ is negative then it rotates in the opposite direction, starting
# from the end of the array where +-1+ is the last element.
#
# a = [ "a", "b", "c", "d" ]
# a.rotate! #=> ["b", "c", "d", "a"]
# a #=> ["b", "c", "d", "a"]
# a.rotate!(2) #=> ["d", "a", "b", "c"]
# a.rotate!(-3) #=> ["a", "b", "c", "d"]
def rotate!(count=1)
self.replace(self.rotate(count))
end
##
# call-seq:
# ary.delete_if { |item| block } -> ary
# ary.delete_if -> Enumerator
#
# Deletes every element of +self+ for which block evaluates to +true+.
#
# The array is changed instantly every time the block is called, not after
# the iteration is over.
#
# See also Array#reject!
#
# If no block is given, an Enumerator is returned instead.
#
# scores = [ 97, 42, 75 ]
# scores.delete_if {|score| score < 80 } #=> [97]
def delete_if(&block)
return to_enum :delete_if unless block
idx = 0
while idx < self.size do
if block.call(self[idx])
self.delete_at(idx)
else
idx += 1
end
end
self
end
##
# call-seq:
# ary.reject! { |item| block } -> ary or nil
# ary.reject! -> Enumerator
#
# Equivalent to Array#delete_if, deleting elements from +self+ for which the
# block evaluates to +true+, but returns +nil+ if no changes were made.
#
# The array is changed instantly every time the block is called, not after
# the iteration is over.
#
# See also Enumerable#reject and Array#delete_if.
#
# If no block is given, an Enumerator is returned instead.
def reject!(&block)
return to_enum :reject! unless block
len = self.size
idx = 0
while idx < self.size do
if block.call(self[idx])
self.delete_at(idx)
else
idx += 1
end
end
if self.size == len
nil
else
self
end
end
##
# call-seq:
# ary.insert(index, obj...) -> ary
#
# Inserts the given values before the element with the given +index+.
#
# Negative indices count backwards from the end of the array, where +-1+ is
# the last element.
#
# a = %w{ a b c d }
# a.insert(2, 99) #=> ["a", "b", 99, "c", "d"]
# a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
def insert(idx, *args)
idx += self.size + 1 if idx < 0
self[idx, 0] = args
self
end
##
# call-seq:
# ary.bsearch {|x| block } -> elem
#
# By using binary search, finds a value from this array which meets
# the given condition in O(log n) where n is the size of the array.
#
# You can use this method in two use cases: a find-minimum mode and
# a find-any mode. In either case, the elements of the array must be
# monotone (or sorted) with respect to the block.
#
# In find-minimum mode (this is a good choice for typical use case),
# the block must return true or false, and there must be an index i
# (0 <= i <= ary.size) so that:
#
# - the block returns false for any element whose index is less than
# i, and
# - the block returns true for any element whose index is greater
# than or equal to i.
#
# This method returns the i-th element. If i is equal to ary.size,
# it returns nil.
#
# ary = [0, 4, 7, 10, 12]
# ary.bsearch {|x| x >= 4 } #=> 4
# ary.bsearch {|x| x >= 6 } #=> 7
# ary.bsearch {|x| x >= -1 } #=> 0
# ary.bsearch {|x| x >= 100 } #=> nil
#
# In find-any mode (this behaves like libc's bsearch(3)), the block
# must return a number, and there must be two indices i and j
# (0 <= i <= j <= ary.size) so that:
#
# - the block returns a positive number for ary[k] if 0 <= k < i,
# - the block returns zero for ary[k] if i <= k < j, and
# - the block returns a negative number for ary[k] if
# j <= k < ary.size.
#
# Under this condition, this method returns any element whose index
# is within i...j. If i is equal to j (i.e., there is no element
# that satisfies the block), this method returns nil.
#
# ary = [0, 4, 7, 10, 12]
# # try to find v such that 4 <= v < 8
# ary.bsearch {|x| 1 - (x / 4).truncate } #=> 4 or 7
# # try to find v such that 8 <= v < 10
# ary.bsearch {|x| 4 - (x / 2).truncate } #=> nil
#
# You must not mix the two modes at a time; the block must always
# return either true/false, or always return a number. It is
# undefined which value is actually picked up at each iteration.
def bsearch(&block)
return to_enum :bsearch unless block
if idx = bsearch_index(&block)
self[idx]
else
nil
end
end
##
# call-seq:
# ary.bsearch_index {|x| block } -> int or nil
#
# By using binary search, finds an index of a value from this array which
# meets the given condition in O(log n) where n is the size of the array.
#
# It supports two modes, depending on the nature of the block and they are
# exactly the same as in the case of #bsearch method with the only difference
# being that this method returns the index of the element instead of the
# element itself. For more details consult the documentation for #bsearch.
def bsearch_index(&block)
return to_enum :bsearch_index unless block
low = 0
high = size
satisfied = false
while low < high
mid = ((low+high)/2).truncate
res = block.call self[mid]
case res
when 0 # find-any mode: Found!
return mid
when Numeric # find-any mode: Continue...
in_lower_half = res < 0
when true # find-min mode
in_lower_half = true
satisfied = true
when false, nil # find-min mode
in_lower_half = false
else
raise TypeError, 'invalid block result (must be numeric, true, false or nil)'
end
if in_lower_half
high = mid
else
low = mid + 1
end
end
satisfied ? low : nil
end
##
# call-seq:
# ary.keep_if { |item| block } -> ary
# ary.keep_if -> Enumerator
#
# Deletes every element of +self+ for which the given block evaluates to
# +false+.
#
# See also Array#select!
#
# If no block is given, an Enumerator is returned instead.
#
# a = [1, 2, 3, 4, 5]
# a.keep_if { |val| val > 3 } #=> [4, 5]
def keep_if(&block)
return to_enum :keep_if unless block
idx = 0
len = self.size
while idx < self.size do
if block.call(self[idx])
idx += 1
else
self.delete_at(idx)
end
end
self
end
##
# call-seq:
# ary.select! {|item| block } -> ary or nil
# ary.select! -> Enumerator
#
# Invokes the given block passing in successive elements from +self+,
# deleting elements for which the block returns a +false+ value.
#
# If changes were made, it will return +self+, otherwise it returns +nil+.
#
# See also Array#keep_if
#
# If no block is given, an Enumerator is returned instead.
def select!(&block)
return to_enum :select! unless block
result = []
idx = 0
len = size
while idx < len
elem = self[idx]
result << elem if block.call(elem)
idx += 1
end
return nil if len == result.size
self.replace(result)
end
##
# call-seq:
# ary.index(val) -> int or nil
# ary.index {|item| block } -> int or nil
#
# Returns the _index_ of the first object in +ary+ such that the object is
# <code>==</code> to +obj+.
#
# If a block is given instead of an argument, returns the _index_ of the
# first object for which the block returns +true+. Returns +nil+ if no
# match is found.
#
# ISO 15.2.12.5.14
def index(val=NONE, &block)
return to_enum(:find_index, val) if !block && val == NONE
if block
idx = 0
len = size
while idx < len
return idx if block.call self[idx]
idx += 1
end
else
return self.__ary_index(val)
end
nil
end
##
# call-seq:
# ary.dig(idx, ...) -> object
#
# Extracts the nested value specified by the sequence of <i>idx</i>
# objects by calling +dig+ at each step, returning +nil+ if any
# intermediate step is +nil+.
#
def dig(idx,*args)
n = self[idx]
if args.size > 0
n&.dig(*args)
else
n
end
end
##
# call-seq:
# ary.permutation { |p| block } -> ary
# ary.permutation -> Enumerator
# ary.permutation(n) { |p| block } -> ary
# ary.permutation(n) -> Enumerator
#
# When invoked with a block, yield all permutations of length +n+ of the
# elements of the array, then return the array itself.
#
# If +n+ is not specified, yield all permutations of all elements.
#
# The implementation makes no guarantees about the order in which the
# permutations are yielded.
#
# If no block is given, an Enumerator is returned instead.
#
# Examples:
#
# a = [1, 2, 3]
# a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
# a.permutation(1).to_a #=> [[1],[2],[3]]
# a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
# a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
# a.permutation(0).to_a #=> [[]] # one permutation of length 0
# a.permutation(4).to_a #=> [] # no permutations of length 4
def permutation(n=self.size, &block)
return to_enum(:permutation, n) unless block
size = self.size
if n == 0
yield []
elsif 0 < n && n <= size
i = 0
while i<size
result = [self[i]]
if n-1 > 0
ary = self[0...i] + self[i+1..-1]
ary.permutation(n-1) do |c|
yield result + c
end
else
yield result
end
i += 1
end
end
self
end
##
# call-seq:
# ary.combination(n) { |c| block } -> ary
# ary.combination(n) -> Enumerator
#
# When invoked with a block, yields all combinations of length +n+ of elements
# from the array and then returns the array itself.
#
# The implementation makes no guarantees about the order in which the
# combinations are yielded.
#
# If no block is given, an Enumerator is returned instead.
#
# Examples:
#
# a = [1, 2, 3, 4]
# a.combination(1).to_a #=> [[1],[2],[3],[4]]
# a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
# a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
# a.combination(4).to_a #=> [[1,2,3,4]]
# a.combination(0).to_a #=> [[]] # one combination of length 0
# a.combination(5).to_a #=> [] # no combinations of length 5
def combination(n, &block)
return to_enum(:combination, n) unless block
size = self.size
if n == 0
yield []
elsif n == 1
i = 0
while i<size
yield [self[i]]
i += 1
end
elsif n <= size
i = 0
while i<size
result = [self[i]]
self[i+1..-1].combination(n-1) do |c|
yield result + c
end
i += 1
end
end
self
end
##
# call-seq:
# ary.transpose -> new_ary
#
# Assumes that self is an array of arrays and transposes the rows and columns.
#
# If the length of the subarrays don't match, an IndexError is raised.
#
# Examples:
#
# a = [[1,2], [3,4], [5,6]]
# a.transpose #=> [[1, 3, 5], [2, 4, 6]]
def transpose
return [] if empty?
column_count = nil
self.each do |row|
raise TypeError unless row.is_a?(Array)
column_count ||= row.size
raise IndexError, 'element size differs' unless column_count == row.size
end
Array.new(column_count) do |column_index|
self.map { |row| row[column_index] }
end
end
##
# call-seq:
# ary.to_h -> Hash
# ary.to_h{|item| ... } -> Hash
#
# Returns the result of interpreting <i>aray</i> as an array of
# <tt>[key, value]</tt> pairs. If a block is given, it should
# return <tt>[key, value]</tt> pairs to construct a hash.
#
# [[:foo, :bar], [1, 2]].to_h
# # => {:foo => :bar, 1 => 2}
# [1, 2].to_h{|x| [x, x*2]}
# # => {1 => 2, 2 => 4}
#
def to_h(&blk)
h = {}
self.each do |v|
v = blk.call(v) if blk
raise TypeError, "wrong element type #{v.class}" unless Array === v
raise ArgumentError, "wrong array length (expected 2, was #{v.length})" unless v.length == 2
h[v[0]] = v[1]
end
h
end
alias append push
alias prepend unshift
alias filter! select!
end
@@ -0,0 +1,200 @@
#include <mruby.h>
#include <mruby/value.h>
#include <mruby/array.h>
#include <mruby/range.h>
#include <mruby/hash.h>
/*
* call-seq:
* ary.assoc(obj) -> new_ary or nil
*
* Searches through an array whose elements are also arrays
* comparing _obj_ with the first element of each contained array
* using obj.==.
* Returns the first contained array that matches (that
* is, the first associated array),
* or +nil+ if no match is found.
* See also <code>Array#rassoc</code>.
*
* s1 = [ "colors", "red", "blue", "green" ]
* s2 = [ "letters", "a", "b", "c" ]
* s3 = "foo"
* a = [ s1, s2, s3 ]
* a.assoc("letters") #=> [ "letters", "a", "b", "c" ]
* a.assoc("foo") #=> nil
*/
static mrb_value
mrb_ary_assoc(mrb_state *mrb, mrb_value ary)
{
mrb_int i;
mrb_value v;
mrb_value k = mrb_get_arg1(mrb);
for (i = 0; i < RARRAY_LEN(ary); ++i) {
v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
if (!mrb_nil_p(v) && RARRAY_LEN(v) > 0 &&
mrb_equal(mrb, RARRAY_PTR(v)[0], k))
return v;
}
return mrb_nil_value();
}
/*
* call-seq:
* ary.rassoc(obj) -> new_ary or nil
*
* Searches through the array whose elements are also arrays. Compares
* _obj_ with the second element of each contained array using
* <code>==</code>. Returns the first contained array that matches. See
* also <code>Array#assoc</code>.
*
* a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
* a.rassoc("two") #=> [2, "two"]
* a.rassoc("four") #=> nil
*/
static mrb_value
mrb_ary_rassoc(mrb_state *mrb, mrb_value ary)
{
mrb_int i;
mrb_value v;
mrb_value value = mrb_get_arg1(mrb);
for (i = 0; i < RARRAY_LEN(ary); ++i) {
v = RARRAY_PTR(ary)[i];
if (mrb_array_p(v) &&
RARRAY_LEN(v) > 1 &&
mrb_equal(mrb, RARRAY_PTR(v)[1], value))
return v;
}
return mrb_nil_value();
}
/*
* call-seq:
* ary.at(index) -> obj or nil
*
* Returns the element at _index_. A
* negative index counts from the end of +self+. Returns +nil+
* if the index is out of range. See also <code>Array#[]</code>.
*
* a = [ "a", "b", "c", "d", "e" ]
* a.at(0) #=> "a"
* a.at(-1) #=> "e"
*/
static mrb_value
mrb_ary_at(mrb_state *mrb, mrb_value ary)
{
mrb_int pos;
mrb_get_args(mrb, "i", &pos);
return mrb_ary_entry(ary, pos);
}
static mrb_value
mrb_ary_values_at(mrb_state *mrb, mrb_value self)
{
mrb_int argc;
mrb_value *argv;
mrb_get_args(mrb, "*", &argv, &argc);
return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref);
}
/*
* call-seq:
* ary.slice!(index) -> obj or nil
* ary.slice!(start, length) -> new_ary or nil
* ary.slice!(range) -> new_ary or nil
*
* Deletes the element(s) given by an +index+ (optionally up to +length+
* elements) or by a +range+.
*
* Returns the deleted object (or objects), or +nil+ if the +index+ is out of
* range.
*
* a = [ "a", "b", "c" ]
* a.slice!(1) #=> "b"
* a #=> ["a", "c"]
* a.slice!(-1) #=> "c"
* a #=> ["a"]
* a.slice!(100) #=> nil
* a #=> ["a"]
*/
static mrb_value
mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
mrb_int i, j, k, len, alen;
mrb_value val;
mrb_value *ptr;
mrb_value ary;
mrb_ary_modify(mrb, a);
if (mrb_get_argc(mrb) == 1) {
mrb_value index = mrb_get_arg1(mrb);
switch (mrb_type(index)) {
case MRB_TT_RANGE:
if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
goto delete_pos_len;
}
else {
return mrb_nil_value();
}
case MRB_TT_FIXNUM:
val = mrb_funcall(mrb, self, "delete_at", 1, index);
return val;
default:
val = mrb_funcall(mrb, self, "delete_at", 1, index);
return val;
}
}
mrb_get_args(mrb, "ii", &i, &len);
delete_pos_len:
alen = ARY_LEN(a);
if (i < 0) i += alen;
if (i < 0 || alen < i) return mrb_nil_value();
if (len < 0) return mrb_nil_value();
if (alen == i) return mrb_ary_new(mrb);
if (len > alen - i) len = alen - i;
ary = mrb_ary_new_capa(mrb, len);
ptr = ARY_PTR(a);
for (j = i, k = 0; k < len; ++j, ++k) {
mrb_ary_push(mrb, ary, ptr[j]);
}
ptr += i;
for (j = i; j < alen - len; ++j) {
*ptr = *(ptr+len);
++ptr;
}
mrb_ary_resize(mrb, self, alen - len);
return ary;
}
void
mrb_mruby_array_ext_gem_init(mrb_state* mrb)
{
struct RClass * a = mrb->array_class;
mrb_define_method(mrb, a, "assoc", mrb_ary_assoc, MRB_ARGS_REQ(1));
mrb_define_method(mrb, a, "at", mrb_ary_at, MRB_ARGS_REQ(1));
mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1));
mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY());
mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang, MRB_ARGS_ARG(1,1));
}
void
mrb_mruby_array_ext_gem_final(mrb_state* mrb)
{
}

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