first commit
This commit is contained in:
Vendored
+81
@@ -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()
|
||||
Vendored
+80
@@ -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
|
||||
Vendored
+852
@@ -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:
|
||||
Vendored
+14
@@ -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
@@ -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_ */
|
||||
Vendored
+224
@@ -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
@@ -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);
|
||||
}
|
||||
+14645
File diff suppressed because it is too large
Load Diff
Vendored
+45
@@ -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
@@ -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).
|
||||
Vendored
+2408
File diff suppressed because it is too large
Load Diff
Vendored
+6
@@ -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:
|
||||
|
||||
Vendored
+20
@@ -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.
|
||||
|
||||
Vendored
+15
@@ -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
|
||||
Vendored
+13
@@ -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
|
||||
|
||||
|
||||
Vendored
+105
@@ -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
|
||||
Vendored
+160
@@ -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
|
||||
Vendored
+8
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,7 @@
|
||||
|
||||
def fib n
|
||||
return n if n < 2
|
||||
fib(n-2) + fib(n-1)
|
||||
end
|
||||
|
||||
puts fib(37)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 |
|
||||
|------------------|--------------|--------------------------------------------------------|
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
C and Ruby Extension Example
|
||||
=========
|
||||
|
||||
This is an example gem which implements a C and Ruby extension.
|
||||
+23
@@ -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
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
module CRubyExtension
|
||||
def CRubyExtension.ruby_method
|
||||
puts "A Ruby Extension"
|
||||
end
|
||||
end
|
||||
+20
@@ -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 */
|
||||
}
|
||||
+7
@@ -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 */
|
||||
}
|
||||
+3
@@ -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.
|
||||
+25
@@ -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
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class RubyExtension
|
||||
def RubyExtension.ruby_method
|
||||
puts "A Ruby Extension"
|
||||
end
|
||||
end
|
||||
+3
@@ -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
|
||||
+28
@@ -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
@@ -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 */
|
||||
+1403
File diff suppressed because it is too large
Load Diff
+300
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,2 @@
|
||||
#! /usr/bin/env ruby
|
||||
exec "rake", *ARGV
|
||||
+101
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user