├── .gitignore ├── .travis.yml ├── AUTHORS ├── COPYING ├── Doxyfile.in ├── INSTALL.md ├── Kyuafile ├── Makefile.am ├── NEWS ├── README.md ├── admin ├── .gitignore ├── clean-all.sh ├── make-release.sh ├── travis-build.sh └── travis-install-deps.sh ├── c_gate.cpp ├── c_gate.hpp ├── c_gate_test.cpp ├── configure.ac ├── debug.cpp ├── debug.hpp ├── debug_test.cpp ├── examples ├── Makefile ├── bindings.cpp ├── hello.cpp ├── interpreter.cpp └── raii.cpp ├── examples_test.sh ├── exceptions.cpp ├── exceptions.hpp ├── exceptions_test.cpp ├── include └── lutok │ ├── README │ ├── c_gate.hpp │ ├── debug.hpp │ ├── exceptions.hpp │ ├── operations.hpp │ ├── stack_cleaner.hpp │ ├── state.hpp │ └── state.ipp ├── lutok.pc.in ├── m4 ├── .gitignore ├── ac_cxx_compile_stdcxx.m4 ├── atf-c++.m4 ├── atf-c.m4 ├── atf-common.m4 ├── atf-sh.m4 ├── compiler-features.m4 ├── compiler-flags.m4 ├── developer-mode.m4 ├── doxygen.m4 └── lua.m4 ├── operations.cpp ├── operations.hpp ├── operations_test.cpp ├── stack_cleaner.cpp ├── stack_cleaner.hpp ├── stack_cleaner_test.cpp ├── state.cpp ├── state.hpp ├── state.ipp ├── state_test.cpp └── test_utils.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.la 2 | *.lo 3 | *.o 4 | *_test 5 | *~ 6 | 7 | .deps 8 | .libs 9 | 10 | Doxyfile 11 | Makefile 12 | Makefile.in 13 | aclocal.m4 14 | api-docs 15 | autom4te.cache 16 | build 17 | config.h 18 | config.h.in 19 | config.log 20 | config.status 21 | configure 22 | libtool 23 | lutok.pc 24 | releases 25 | stamp-h1 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | compiler: 4 | - gcc 5 | - clang 6 | 7 | before_install: 8 | - ./admin/travis-install-deps.sh 9 | 10 | env: 11 | - ARCH=amd64 AS_ROOT=no 12 | - ARCH=amd64 AS_ROOT=yes 13 | - ARCH=i386 AS_ROOT=no 14 | 15 | matrix: 16 | exclude: 17 | - compiler: clang 18 | env: ARCH=i386 AS_ROOT=no 19 | 20 | script: 21 | - ./admin/travis-build.sh 22 | 23 | notifications: 24 | email: 25 | - lutok-log@googlegroups.com 26 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | * Julio Merino 2 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright 2011, 2012 Google Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | * Neither the name of Google Inc. nor the names of its contributors 14 | may be used to endorse or promote products derived from this software 15 | without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /Doxyfile.in: -------------------------------------------------------------------------------- 1 | # Copyright 2010 Google Inc. 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are 6 | # met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of Google Inc. nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | BUILTIN_STL_SUPPORT = YES 30 | ENABLE_PREPROCESSING = YES 31 | EXTRACT_ANON_NSPACES = YES 32 | EXTRACT_LOCAL_CLASSES = YES 33 | EXTRACT_PRIVATE = YES 34 | EXTRACT_STATIC = YES 35 | EXPAND_ONLY_PREDEF = YES 36 | FILE_PATTERNS = *.cpp *.hpp *.ipp 37 | GENERATE_LATEX = NO 38 | GENERATE_TAGFILE = @top_builddir@/api-docs/api-docs.tag 39 | INPUT = @top_srcdir@ 40 | INPUT_ENCODING = ISO-8859-1 41 | JAVADOC_AUTOBRIEF = YES 42 | MACRO_EXPANSION = YES 43 | OUTPUT_DIRECTORY = @top_builddir@/api-docs 44 | OUTPUT_LANGUAGE = English 45 | PREDEFINED = "UTILS_UNUSED_PARAM(name)=unused_ ## name" 46 | PROJECT_NAME = "@PACKAGE_NAME@" 47 | PROJECT_NUMBER = @VERSION@ 48 | QUIET = YES 49 | RECURSIVE = NO 50 | SHORT_NAMES = YES # Cope with gnutar limitations during 'make dist'. 51 | SORT_BY_SCOPE_NAME = YES 52 | SORT_MEMBERS_CTORS_1ST = YES 53 | WARN_NO_PARAMDOC = YES 54 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Lutok uses the GNU Automake, GNU Autoconf and GNU Libtool utilities as 4 | its build system. These are used only when compiling the library from 5 | the source code package. If you want to install Lutok from a binary 6 | package, you do not need to read this document. 7 | 8 | For the impatient: 9 | 10 | ```shell 11 | $ ./configure 12 | $ make 13 | $ make check 14 | $ sudo make install # or `make install` with root privileges 15 | $ make installcheck 16 | ``` 17 | 18 | Or alternatively, install as a regular user into your home directory: 19 | 20 | ```shell 21 | $ ./configure --prefix ~/local 22 | $ make 23 | $ make check 24 | $ make install 25 | $ make installcheck 26 | ``` 27 | 28 | # Dependencies 29 | 30 | To build and use Lutok successfully you need: 31 | 32 | * A C++-11 standards-compliant compiler. 33 | * Lua 5.1 or greater. 34 | * pkg-config or an equivalent tool, e.g., pkgconf. 35 | 36 | Optionally, if you want to build and run the tests (recommended), you 37 | need: 38 | 39 | * Kyua 0.5 or greater. 40 | * ATF 0.15 or greater. 41 | 42 | If you are building Lutok from the code on the repository, you will also 43 | need the following tools: 44 | 45 | * GNU Autoconf 2.68 (or later). 46 | * GNU Automake 1.9 (or later). 47 | * GNU Libtool. 48 | 49 | 50 | # Regenerating the build system 51 | 52 | This is not necessary if you are building from a formal release 53 | distribution file. 54 | 55 | On the other hand, if you are building Lutok from code extracted from 56 | the repository, you must first regenerate the files used by the build 57 | system. You will also need to do this if you modify `configure.ac`, 58 | `Makefile.am`, or any of the other build system files. To do this, simply 59 | run: 60 | 61 | ```shell 62 | $ autoreconf -i -s 63 | ``` 64 | 65 | If ATF is installed in a different prefix than `autoconf`, you will also 66 | need to tell `autoreconf` where the ATF m4 macros are located. Otherwise, 67 | the `configure` script will be incomplete and will show confusing syntax 68 | errors mentioning, for example, `ATF_CHECK_SH`. To fix this, you have 69 | to run `autoreconf` in the following manner, replacing `` with 70 | the appropriate path: 71 | 72 | ```shell 73 | $ autoreconf -i -s -I /share/aclocal 74 | ``` 75 | 76 | # General build procedure 77 | 78 | To build and install the source package, you must follow these steps: 79 | 80 | #. Configure the sources to adapt to your operating system. This is 81 | done using the `configure` script located on the sources' top 82 | directory, and it is usually invoked without arguments unless you 83 | want to change the installation prefix. More details on this 84 | procedure are given on a later section. 85 | 86 | #. Build the sources to generate the binaries and scripts. Simply run 87 | `make` on the sources' top directory after configuring them. No 88 | problems should arise. 89 | 90 | #. Install the library by running `make install`. You may need to 91 | become root to issue this step. 92 | 93 | #. Issue any manual installation steps that may be required. These are 94 | described later in their own section. 95 | 96 | #. Check that the installed library works by running `make installcheck`. 97 | You do not need to be root to do this. 98 | 99 | 100 | # Configuration flags 101 | 102 | The most common, standard flags given to `configure` are: 103 | 104 | - `--prefix=directory` 105 | - **Possible values**: any path 106 | - **Default**: "/usr/local" 107 | 108 | Specifies where the library (binaries and all associated files) will 109 | be installed. 110 | 111 | - `--help` 112 | Shows information about all available flags and exits immediately, 113 | without running any configuration tasks. 114 | 115 | The following flags are specific to Lutok's `configure` script: 116 | 117 | - `--enable-developer` 118 | - **Possible values**: "yes", "no" 119 | - **Default**: "yes" in Git HEAD builds; "no" in formal releases. 120 | 121 | Enables several features useful for development, such as the inclusion 122 | of debugging symbols in all objects or the enforcement of compilation 123 | warnings. 124 | 125 | The compiler will be executed with an exhaustive collection of warning 126 | detection features regardless of the value of this flag. However, such 127 | warnings are only fatal when `--enable-developer` is set to "yes". 128 | 129 | - `--enable-atf` 130 | - **Possible values**: "yes", "no", "auto". 131 | - **Default**: "auto" 132 | 133 | Enables usage of ATF to build (and later install) the tests. 134 | 135 | Setting this to "yes" causes the `configure` script to look for ATF 136 | unconditionally and abort if not found. Setting this to "auto" lets 137 | `configure` perform the best decision based on availability of ATF. 138 | Setting this to "no" explicitly disables ATF usage. 139 | 140 | When support for tests is enabled, the build process will generate the 141 | test programs and will later install them into the tests tree. 142 | Running `make check` or `make installcheck` from within the source 143 | directory will cause these tests to be run with Kyua (assuming it is 144 | also installed). 145 | 146 | - `--with-doxygen` 147 | - **Possible values**: "yes", "no", "auto", or a path. 148 | - **Default**: "auto". 149 | 150 | Enables usage of Doxygen to generate documentation for internal APIs. 151 | 152 | Setting this to "yes" causes the `configure` script to look for Doxygen 153 | unconditionally and abort if not found. Setting this to "auto" lets 154 | `configure` perform the best decision based on availability of Doxygen. 155 | Setting this to "no" explicitly disables Doxygen usage. And, lastly, 156 | setting this to a path forces `configure` to use a specific Doxygen 157 | binary, which must exist. 158 | 159 | When support for Doxygen is enabled, the build process will generate 160 | HTML documentation for the Lutok API. This documentation will later 161 | be installed in the HTML directory specified by the `configure` script. 162 | You can change the location of the HTML documents by providing your 163 | desired override with the `--htmldir` flag to the `configure` script. 164 | 165 | 166 | Run the tests! 167 | ============== 168 | 169 | Lastly, after a successful installation (and assuming you built the 170 | sources with support for ATF), you should periodically run the tests 171 | from the final location to ensure things remain stable. Do so as 172 | follows: 173 | 174 | ```shell 175 | $ kyua test -k /usr/local/tests/lutok/Kyuafile 176 | ``` 177 | 178 | And if you see any tests fail, do not hesitate to report them in: 179 | 180 | https://github.com/freebsd/lutok/issues/ 181 | 182 | Thank you! 183 | -------------------------------------------------------------------------------- /Kyuafile: -------------------------------------------------------------------------------- 1 | syntax("kyuafile", 1) 2 | 3 | test_suite("lutok") 4 | 5 | atf_test_program{name="c_gate_test"} 6 | atf_test_program{name="debug_test"} 7 | atf_test_program{name="examples_test"} 8 | atf_test_program{name="exceptions_test"} 9 | atf_test_program{name="operations_test"} 10 | atf_test_program{name="stack_cleaner_test"} 11 | atf_test_program{name="state_test"} 12 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright 2010 Google Inc. 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are 6 | # met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of Google Inc. nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | ACLOCAL_AMFLAGS = -I m4 30 | 31 | doc_DATA = AUTHORS COPYING NEWS README.md 32 | noinst_DATA = INSTALL.md README.md 33 | EXTRA_DIST = $(doc_DATA) INSTALL.md README.md 34 | 35 | LUTOK_CFLAGS = -I$(srcdir)/include $(LUA_CFLAGS) 36 | LUTOK_LIBS = liblutok.la $(LUA_LIBS) 37 | 38 | pkginclude_HEADERS = c_gate.hpp 39 | pkginclude_HEADERS += debug.hpp 40 | pkginclude_HEADERS += exceptions.hpp 41 | pkginclude_HEADERS += operations.hpp 42 | pkginclude_HEADERS += stack_cleaner.hpp 43 | pkginclude_HEADERS += state.hpp 44 | pkginclude_HEADERS += state.ipp 45 | pkginclude_HEADERS += test_utils.hpp 46 | 47 | EXTRA_DIST += include/lutok/README 48 | EXTRA_DIST += include/lutok/c_gate.hpp 49 | EXTRA_DIST += include/lutok/debug.hpp 50 | EXTRA_DIST += include/lutok/exceptions.hpp 51 | EXTRA_DIST += include/lutok/operations.hpp 52 | EXTRA_DIST += include/lutok/stack_cleaner.hpp 53 | EXTRA_DIST += include/lutok/state.hpp 54 | EXTRA_DIST += include/lutok/state.ipp 55 | 56 | lib_LTLIBRARIES = liblutok.la 57 | liblutok_la_SOURCES = c_gate.cpp 58 | liblutok_la_SOURCES += c_gate.hpp 59 | liblutok_la_SOURCES += debug.cpp 60 | liblutok_la_SOURCES += debug.hpp 61 | liblutok_la_SOURCES += exceptions.cpp 62 | liblutok_la_SOURCES += exceptions.hpp 63 | liblutok_la_SOURCES += operations.cpp 64 | liblutok_la_SOURCES += operations.hpp 65 | liblutok_la_SOURCES += stack_cleaner.cpp 66 | liblutok_la_SOURCES += stack_cleaner.hpp 67 | liblutok_la_SOURCES += state.cpp 68 | liblutok_la_SOURCES += state.hpp 69 | liblutok_la_SOURCES += state.ipp 70 | liblutok_la_SOURCES += test_utils.hpp 71 | liblutok_la_CPPFLAGS = $(LUTOK_CFLAGS) 72 | liblutok_la_LDFLAGS = -version-info 3:0:0 73 | liblutok_la_LIBADD = $(LUA_LIBS) 74 | 75 | pkgconfig_DATA = lutok.pc 76 | CLEANFILES = lutok.pc 77 | EXTRA_DIST += lutok.pc.in 78 | lutok.pc: $(srcdir)/lutok.pc.in Makefile 79 | $(AM_V_GEN)sed -e 's#__INCLUDEDIR__#$(includedir)#g' \ 80 | -e 's#__LIBDIR__#$(libdir)#g' \ 81 | -e 's#__LUA_CFLAGS__#$(LUA_CFLAGS)#g' \ 82 | -e 's#__LUA_LIBS__#$(LUA_LIBS)#g' \ 83 | -e 's#__VERSION__#$(PACKAGE_VERSION)#g' \ 84 | <$(srcdir)/lutok.pc.in >lutok.pc.tmp; \ 85 | mv lutok.pc.tmp lutok.pc 86 | 87 | CLEAN_TARGETS = 88 | DIST_HOOKS = 89 | PHONY_TARGETS = 90 | 91 | examplesdir = $(docdir)/examples 92 | examples_DATA = examples/Makefile 93 | examples_DATA += examples/bindings.cpp 94 | examples_DATA += examples/hello.cpp 95 | examples_DATA += examples/interpreter.cpp 96 | examples_DATA += examples/raii.cpp 97 | EXTRA_DIST += $(examples_DATA) 98 | 99 | if WITH_ATF 100 | tests_DATA = Kyuafile 101 | EXTRA_DIST += $(tests_DATA) 102 | 103 | tests_PROGRAMS = c_gate_test 104 | c_gate_test_SOURCES = c_gate_test.cpp test_utils.hpp 105 | c_gate_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS) 106 | c_gate_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS) 107 | 108 | tests_PROGRAMS += debug_test 109 | debug_test_SOURCES = debug_test.cpp test_utils.hpp 110 | debug_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS) 111 | debug_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS) 112 | 113 | tests_SCRIPTS = examples_test 114 | CLEANFILES += examples_test 115 | EXTRA_DIST += examples_test.sh 116 | examples_test: $(srcdir)/examples_test.sh 117 | $(AM_V_GEN)sed -e 's,__ATF_SH__,$(ATF_SH),g' \ 118 | -e 's,__CXX__,$(CXX),g' \ 119 | -e 's,__EXAMPLESDIR__,$(examplesdir),g' \ 120 | -e 's,__LIBDIR__,$(libdir),g' \ 121 | <$(srcdir)/examples_test.sh >examples_test.tmp; \ 122 | chmod +x examples_test.tmp; \ 123 | rm -f examples_test; \ 124 | mv examples_test.tmp examples_test 125 | 126 | tests_PROGRAMS += exceptions_test 127 | exceptions_test_SOURCES = exceptions_test.cpp 128 | exceptions_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS) 129 | exceptions_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS) 130 | 131 | tests_PROGRAMS += operations_test 132 | operations_test_SOURCES = operations_test.cpp test_utils.hpp 133 | operations_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS) 134 | operations_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS) 135 | 136 | tests_PROGRAMS += stack_cleaner_test 137 | stack_cleaner_test_SOURCES = stack_cleaner_test.cpp test_utils.hpp 138 | stack_cleaner_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS) 139 | stack_cleaner_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS) 140 | 141 | tests_PROGRAMS += state_test 142 | state_test_SOURCES = state_test.cpp test_utils.hpp 143 | state_test_CXXFLAGS = $(LUTOK_CFLAGS) $(ATF_CXX_CFLAGS) 144 | state_test_LDADD = $(LUTOK_LIBS) $(ATF_CXX_LIBS) 145 | 146 | if HAVE_KYUA 147 | check-local: check-kyua 148 | PHONY_TARGETS += check-kyua 149 | check-kyua: 150 | $(TESTS_ENVIRONMENT) kyua test \ 151 | --kyuafile='$(top_srcdir)/Kyuafile' --build-root='$(top_builddir)' 152 | 153 | installcheck-local: installcheck-kyua 154 | PHONY_TARGETS += installcheck-kyua 155 | installcheck-kyua: 156 | cd $(testsdir) && $(TESTS_ENVIRONMENT) kyua test 157 | endif 158 | else 159 | DIST_HOOKS += dist-no-atf 160 | PHONY_TARGETS += dist-no-atf 161 | dist-no-atf: 162 | @echo "Sorry; cannot build a distfile without atf" 163 | @false 164 | endif 165 | 166 | if WITH_DOXYGEN 167 | # This should probably be html-local, but it seems better to generate the 168 | # documentation in all cases to get warnings about missing documentation every 169 | # time the code is modified. (And, after all, the documentation is not 170 | # installed so generating it unconditionally is not a big problem.) 171 | all-local: api-docs/api-docs.tag 172 | 173 | api-docs/api-docs.tag: $(builddir)/Doxyfile $(SOURCES) 174 | $(AM_V_GEN)rm -rf api-docs; \ 175 | mkdir -p api-docs; \ 176 | ${DOXYGEN} $(builddir)/Doxyfile 2>&1 | tee api-docs/warnings; \ 177 | rm -f api-docs/html/installdox 178 | api-docs/html: api-docs/api-docs.tag 179 | 180 | CLEAN_TARGETS += clean-api-docs 181 | clean-api-docs: 182 | rm -rf api-docs 183 | 184 | EXTRA_DIST += api-docs/html 185 | else 186 | DIST_HOOKS += dist-no-doxygen 187 | PHONY_TARGETS += dist-no-doxygen 188 | dist-no-doxygen: 189 | @echo "Sorry; cannot build a distfile without Doxygen" 190 | @false 191 | endif 192 | 193 | install-data-local: install-api-docs 194 | install-api-docs: install-docDATA 195 | @echo "Installing HTML documentation into $(DESTDIR)$(htmldir)" 196 | @if [ -d api-docs/html ]; then \ 197 | test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)"; \ 198 | ( cd api-docs/html && tar cf - . ) | \ 199 | ( cd "$(DESTDIR)$(htmldir)" && tar xf - ); \ 200 | elif [ -d "$(srcdir)/api-docs/html" ]; then \ 201 | test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)"; \ 202 | ( cd "$(srcdir)/api-docs/html" && tar cf - . ) | \ 203 | ( cd "$(DESTDIR)$(htmldir)" && tar xf - ); \ 204 | else \ 205 | echo "Doxygen not installed and prebuilt documents not found"; \ 206 | fi 207 | 208 | uninstall-local: uninstall-api-docs 209 | uninstall-api-docs: 210 | find "$(DESTDIR)$(htmldir)" -type d -exec chmod 755 {} \; 211 | rm -rf "$(DESTDIR)$(htmldir)" 212 | 213 | clean-local: $(CLEAN_TARGETS) 214 | 215 | PHONY_TARGETS += clean-all 216 | clean-all: 217 | GIT="$(GIT)" $(SH) $(srcdir)/admin/clean-all.sh 218 | 219 | dist-hook: $(DIST_HOOKS) 220 | 221 | .PHONY: ${PHONY_TARGETS} 222 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | # Major changes between releases 2 | 3 | ## Changes in version 0.7 4 | 5 | Released on 2025/XX/YY. 6 | 7 | * Issue 37: fix release tarball by relying on `make dist`. 8 | 9 | ## Changes in version 0.6 10 | 11 | Released on 2025/01/04. 12 | 13 | * Remove lingering C++-11 support. The project now requires a C++14 compliant toolchain to build. 14 | 15 | * Fix a Doxygen warning by deleting the `stack_cleaner` copy/assignment operator. 16 | 17 | * Vendor the ATF m4 files from freebsd/atf@atf-0.22 , 18 | 19 | * `m4/lua.m4`: remove legacy `lua-config` support in favor of `pkg_config`. 20 | 21 | * Fix a benign buffer overrun complaint from gcc 13.2. 22 | 23 | * Rename `--with-atf` to `--enable-atf`. 24 | 25 | ## Changes in version 0.5 26 | 27 | Released on 2024/11/25. 28 | 29 | * Use more modern autotools macros. Bump the minimum autoconf version to 2.68 to 30 | support this change. 31 | 32 | * Modify build code to improve Lua 5.4 support. 33 | 34 | * Replace `std::auto_ptr` use with `std::unique_ptr` use. This improves C++ 35 | standard support and fixes the build with newer C++ standards. 36 | 37 | ## Changes in version 0.4 38 | 39 | Released on 2013/12/07. 40 | 41 | * Cope with the lack of AM_PROG_AR in configure.ac, which first 42 | appeared in Automake 1.11.2. Fixes a problem in Ubuntu 10.04 43 | LTS, which appears stuck in 1.11.1. 44 | 45 | * Stopped shipping an `Atffile`. The only supported way to run the tests 46 | is via Kyua. 47 | 48 | Interface changes: 49 | 50 | * Issue 5: New methods added to the state class: `open_all`. 51 | 52 | * Removed default parameter values from all state methods and all 53 | standalone operations. It is often unclear what the default value is 54 | given that it depends on the specific Lua operation. Being explicit 55 | on the caller side is clearer. 56 | 57 | * Modified operations `do_file` and `do_string` to support passing a number 58 | of arguments to the loaded chunks and an error handler to the backing 59 | `pcall` call. 60 | 61 | 62 | ## Changes in version 0.3 63 | 64 | Released on 2013/06/14. 65 | 66 | * Issue 1: Added support for Lua 5.2 while maintaining support for Lua 67 | 5.1. Applications using Lutok can be modified to use the new 68 | interface in this new version and thus support both Lua releases. 69 | However, because of incompatible changes to the Lua API, this release 70 | of Lutok is incompatible with previous releases as well. 71 | 72 | * Issue 3: Tweaked configure to look for Lua using the pkg-config names 73 | lua-5.2 and lua-5.1. These are the names used by FreeBSD. 74 | 75 | Interface changes: 76 | 77 | * New global constants: `registry_index`. 78 | 79 | * New methods added to the state class: `get_global_table`. 80 | 81 | * Removed global constants: `globals_index`. 82 | 83 | 84 | ## Changes in version 0.2 85 | 86 | Released on 2012/05/30. 87 | 88 | * New global constants: `globals_index`. 89 | 90 | * New methods added to the state class: `get_metafield`, `get_metatable`, 91 | `insert`, `push_value`, `raw_get`, and `raw_set`. 92 | 93 | * Acknowledged that Lua 5.2 is currently not supported. 94 | 95 | 96 | ## Changes in version 0.1 97 | 98 | Released on 2012/01/29. 99 | 100 | * This is the first public release of the Lutok package. 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to the Lutok project! 2 | 3 | Lutok is a **lightweight C++ API library** for Lua. 4 | 5 | Lutok provides thin C++ wrappers around the Lua C API to ease the 6 | interaction between C++ and Lua. These wrappers make intensive use of 7 | RAII to prevent resource leakage, expose C++-friendly data types, report 8 | errors by means of exceptions and ensure that the Lua stack is always 9 | left untouched in the face of errors. The library also provides a small 10 | subset of miscellaneous utility functions built on top of the wrappers. 11 | 12 | Lutok focuses on providing a clean and safe C++ interface; the drawback 13 | is that it is not suitable for performance-critical environments. In 14 | order to implement error-safe C++ wrappers on top of a Lua C binary 15 | library, Lutok adds several layers or abstraction and error checking 16 | that go against the original spirit of the Lua C API and thus degrade 17 | performance. 18 | 19 | For further information on the contents of this distribution file, 20 | please refer to the following other documents: 21 | 22 | * `AUTHORS`: List of authors and contributors to this project. 23 | * `COPYING`: License information. 24 | * `INSTALL.md:` Compilation and installation instructions. 25 | * `NEWS.md`: List of major changes between formal releases. 26 | 27 | For general project information, please visit [Lutok on GitHub](https://github.com/freebsd/lutok/) 28 | -------------------------------------------------------------------------------- /admin/.gitignore: -------------------------------------------------------------------------------- 1 | ar-lib 2 | compile 3 | config.guess 4 | config.sub 5 | depcomp 6 | install-sh 7 | ltmain.sh 8 | missing 9 | -------------------------------------------------------------------------------- /admin/clean-all.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Copyright 2010 Google Inc. 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are 7 | # met: 8 | # 9 | # * Redistributions of source code must retain the above copyright 10 | # notice, this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # * Neither the name of Google Inc. nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software 16 | # without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | Prog_Name=${0##*/} 31 | 32 | if [ ! -f ./state.hpp ]; then 33 | echo "${Prog_Name}: must be run from the source top directory" 1>&2 34 | exit 1 35 | fi 36 | 37 | if [ ! -f configure ]; then 38 | echo "${Prog_Name}: configure not found; nothing to clean?" 1>&2 39 | exit 1 40 | fi 41 | 42 | [ -f Makefile ] || ./configure 43 | make distclean 44 | 45 | # Top-level directory. 46 | rm -f Makefile.in 47 | rm -f aclocal.m4 48 | rm -rf autom4te.cache 49 | rm -f config.h.in 50 | rm -f configure 51 | rm -f mkinstalldirs 52 | rm -f lutok-*.tar.gz 53 | 54 | # admin directory. 55 | rm -f admin/compile 56 | rm -f admin/config.guess 57 | rm -f admin/config.sub 58 | rm -f admin/depcomp 59 | rm -f admin/install-sh 60 | rm -f admin/ltmain.sh 61 | rm -f admin/mdate-sh 62 | rm -f admin/missing 63 | rm -f admin/texinfo.tex 64 | 65 | # bootstrap directory. 66 | rm -f bootstrap/package.m4 67 | rm -f bootstrap/testsuite 68 | 69 | # doc directory. 70 | rm -f doc/*.info 71 | rm -f doc/stamp-vti 72 | rm -f doc/version.texi 73 | 74 | # m4 directory. 75 | rm -f m4/libtool.m4 76 | rm -f m4/lt*.m4 77 | 78 | # Files and directories spread all around the tree. 79 | find . -name '#*' | xargs rm -rf 80 | find . -name '*~' | xargs rm -rf 81 | find . -name .deps | xargs rm -rf 82 | find . -name .gdb_history | xargs rm -rf 83 | find . -name .libs | xargs rm -rf 84 | find . -name .tmp | xargs rm -rf 85 | 86 | # Show remaining files. 87 | if [ -n "${GIT}" ]; then 88 | echo ">>> untracked and ignored files" 89 | "${GIT}" status --porcelain --ignored | grep -E '^(\?\?|!!)' || true 90 | fi 91 | -------------------------------------------------------------------------------- /admin/make-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Create release artifacts from a release tag. 4 | # 5 | # Example: 6 | # ./admin/make-release.sh atf-0.23 7 | 8 | set -eux 9 | 10 | tag=$1 11 | 12 | cd "$(dirname "$(dirname "$0")")" 13 | 14 | mkdir -p releases 15 | release_root=$(realpath releases) 16 | 17 | release_dir="${release_root}/${tag}" 18 | release_artifact="${release_root}/${tag}.tar.gz" 19 | 20 | rm -Rf "${release_dir}" 21 | mkdir -p "${release_dir}" 22 | git archive "${tag}" | tar xzvf - -C "${release_dir}" 23 | cd "${release_dir}" 24 | autoreconf -isv 25 | ./configure --enable-atf 26 | make dist 27 | mv *.tar.gz "${release_root}/${tag}.tar.gz" 28 | cd "${release_root}" 29 | sha256 "${release_artifact##*/}" > "${release_artifact}.sha256" 30 | 31 | # vim: syntax=sh 32 | -------------------------------------------------------------------------------- /admin/travis-build.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Copyright 2014 Google Inc. 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are 7 | # met: 8 | # 9 | # * Redistributions of source code must retain the above copyright 10 | # notice, this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # * Neither the name of Google Inc. nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software 16 | # without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | set -e -x 31 | 32 | if [ -d /usr/local/share/aclocal ]; then 33 | autoreconf -isv -I/usr/local/share/aclocal 34 | else 35 | autoreconf -isv 36 | fi 37 | ./configure 38 | 39 | archflags= 40 | [ "${ARCH?}" != i386 ] || archflags=-m32 41 | 42 | f= 43 | f="${f} CPPFLAGS='-I/usr/local/include'" 44 | f="${f} CXX='${CXX} ${archflags}'" 45 | f="${f} LDFLAGS='-L/usr/local/lib -Wl,-R/usr/local/lib'" 46 | f="${f} PKG_CONFIG_PATH='/usr/local/lib/pkgconfig'" 47 | if [ "${AS_ROOT:-no}" = yes ]; then 48 | sudo -H PATH="${PATH}" make distcheck DISTCHECK_CONFIGURE_FLAGS="${f}" 49 | else 50 | make distcheck DISTCHECK_CONFIGURE_FLAGS="${f}" 51 | fi 52 | -------------------------------------------------------------------------------- /admin/travis-install-deps.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Copyright 2014 Google Inc. 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are 7 | # met: 8 | # 9 | # * Redistributions of source code must retain the above copyright 10 | # notice, this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # * Neither the name of Google Inc. nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software 16 | # without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | set -e -x 31 | 32 | install_deps() { 33 | sudo apt-get update -qq 34 | 35 | local pkgsuffix= 36 | local packages= 37 | if [ "${ARCH?}" = i386 ]; then 38 | pkgsuffix=:i386 39 | packages="${packages} gcc-multilib" 40 | packages="${packages} g++-multilib" 41 | fi 42 | packages="${packages} doxygen" 43 | packages="${packages} gdb" 44 | packages="${packages} liblua5.2-0${pkgsuffix}" 45 | packages="${packages} liblua5.2-dev${pkgsuffix}" 46 | packages="${packages} libsqlite3-0${pkgsuffix}" 47 | packages="${packages} libsqlite3-dev${pkgsuffix}" 48 | packages="${packages} pkg-config${pkgsuffix}" 49 | packages="${packages} sqlite3" 50 | sudo apt-get install -y ${packages} 51 | } 52 | 53 | install_from_github() { 54 | local project="${1}"; shift 55 | local name="${1}"; shift 56 | local release="${1}"; shift 57 | 58 | local distname="${name}-${release}" 59 | 60 | local baseurl="https://github.com/freebsd/${project}" 61 | wget --no-check-certificate \ 62 | "${baseurl}/releases/download/${distname}/${distname}.tar.gz" 63 | tar -xzvf "${distname}.tar.gz" 64 | 65 | local archflags= 66 | [ "${ARCH?}" != i386 ] || archflags=-m32 67 | 68 | cd "${distname}" 69 | ./configure \ 70 | --disable-developer \ 71 | --without-atf \ 72 | --without-doxygen \ 73 | CFLAGS="${archflags}" \ 74 | CPPFLAGS="-I/usr/local/include" \ 75 | CXXFLAGS="${archflags}" \ 76 | LDFLAGS="-L/usr/local/lib -Wl,-R/usr/local/lib" \ 77 | PKG_CONFIG_PATH="/usr/local/lib/pkgconfig" 78 | make 79 | sudo make install 80 | cd - 81 | 82 | rm -rf "${distname}" "${distname}.tar.gz" 83 | } 84 | 85 | install_from_bintray() { 86 | case "${ARCH?}" in 87 | amd64) 88 | name="20160204-usr-local-kyua-ubuntu-12-04-amd64-${CC?}.tar.gz" 89 | ;; 90 | i386) 91 | name="20160714-usr-local-kyua-ubuntu-12-04-i386-${CC?}.tar.gz" 92 | ;; 93 | *) 94 | echo "ERROR: Unknown ARCH value ${ARCH}" 1>&2 95 | exit 1 96 | ;; 97 | esac 98 | wget "http://dl.bintray.com/freebsd/kyua/${name}" || return 1 99 | sudo tar -xzvp -C / -f "${name}" 100 | rm -f "${name}" 101 | } 102 | 103 | install_deps 104 | if ! install_from_bintray; then 105 | install_from_github atf atf 0.20 106 | install_from_github lutok lutok 0.4 107 | install_from_github kyua kyua-testers 0.2 108 | install_from_github kyua kyua-cli 0.8 109 | fi 110 | -------------------------------------------------------------------------------- /c_gate.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #include "c_gate.hpp" 30 | #include "state.ipp" 31 | 32 | 33 | /// Creates a new gateway to an existing C++ Lua state. 34 | /// 35 | /// \param state_ The state to connect to. This object must remain alive while 36 | /// the newly-constructed state_c_gate is alive. 37 | lutok::state_c_gate::state_c_gate(state& state_) : 38 | _state(state_) 39 | { 40 | } 41 | 42 | 43 | /// Destructor. 44 | /// 45 | /// Destroying this object has no implications on the life cycle of the Lua 46 | /// state. Only the corresponding state object controls when the Lua state is 47 | /// closed. 48 | lutok::state_c_gate::~state_c_gate(void) 49 | { 50 | } 51 | 52 | 53 | /// Creates a C++ state for a C Lua state. 54 | /// 55 | /// \warning The created state object does NOT own the C state. You must take 56 | /// care to properly destroy the input lua_State when you are done with it to 57 | /// not leak resources. 58 | /// 59 | /// \param raw_state The raw state to wrap temporarily. 60 | /// 61 | /// \return The wrapped state without strong ownership on the input state. 62 | lutok::state 63 | lutok::state_c_gate::connect(lua_State* raw_state) 64 | { 65 | return state(static_cast< void* >(raw_state)); 66 | } 67 | 68 | 69 | /// Returns the C native Lua state. 70 | /// 71 | /// \return A native lua_State object holding the Lua C API state. 72 | lua_State* 73 | lutok::state_c_gate::c_state(void) 74 | { 75 | return static_cast< lua_State* >(_state.raw_state()); 76 | } 77 | -------------------------------------------------------------------------------- /c_gate.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file c_gate.hpp 30 | /// Provides direct access to the C state of the Lua wrappers. 31 | 32 | #if !defined(LUTOK_C_GATE_HPP) 33 | #define LUTOK_C_GATE_HPP 34 | 35 | #include 36 | 37 | namespace lutok { 38 | 39 | 40 | class state; 41 | 42 | 43 | /// Gateway to the raw C state of Lua. 44 | /// 45 | /// This class provides a mechanism to muck with the internals of the state 46 | /// wrapper class. Client code may wish to do so if Lutok is missing some 47 | /// features of the performance of Lutok in a particular situation is not 48 | /// reasonable. 49 | /// 50 | /// \warning The use of this class is discouraged. By using this class, you are 51 | /// entering the world of unsafety. Anything you do through the objects exposed 52 | /// through this class will not be controlled by RAII patterns not validated in 53 | /// any other way, so you can end up corrupting the Lua state and later get 54 | /// crashes on otherwise perfectly-valid C++ code. 55 | class state_c_gate { 56 | /// The C++ state that this class wraps. 57 | state& _state; 58 | 59 | public: 60 | state_c_gate(state&); 61 | ~state_c_gate(void); 62 | 63 | static state connect(lua_State*); 64 | 65 | lua_State* c_state(void); 66 | }; 67 | 68 | 69 | } // namespace lutok 70 | 71 | #endif // !defined(LUTOK_C_GATE_HPP) 72 | -------------------------------------------------------------------------------- /c_gate_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #include "c_gate.hpp" 30 | 31 | #include 32 | #include 33 | 34 | #include "state.ipp" 35 | #include "test_utils.hpp" 36 | 37 | 38 | ATF_TEST_CASE_WITHOUT_HEAD(connect); 39 | ATF_TEST_CASE_BODY(connect) 40 | { 41 | lua_State* raw_state = luaL_newstate(); 42 | ATF_REQUIRE(raw_state != NULL); 43 | 44 | { 45 | lutok::state state = lutok::state_c_gate::connect(raw_state); 46 | lua_pushinteger(raw(state), 123); 47 | } 48 | // If the wrapper object had closed the Lua state, we could very well crash 49 | // here. 50 | ATF_REQUIRE_EQ(123, lua_tointeger(raw_state, -1)); 51 | 52 | lua_close(raw_state); 53 | } 54 | 55 | 56 | ATF_TEST_CASE_WITHOUT_HEAD(c_state); 57 | ATF_TEST_CASE_BODY(c_state) 58 | { 59 | lutok::state state; 60 | state.push_integer(5); 61 | { 62 | lutok::state_c_gate gate(state); 63 | lua_State* raw_state = gate.c_state(); 64 | ATF_REQUIRE_EQ(5, lua_tointeger(raw_state, -1)); 65 | } 66 | state.pop(1); 67 | } 68 | 69 | 70 | ATF_INIT_TEST_CASES(tcs) 71 | { 72 | ATF_ADD_TEST_CASE(tcs, c_state); 73 | ATF_ADD_TEST_CASE(tcs, connect); 74 | } 75 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl Copyright 2011 Google Inc. 2 | dnl All rights reserved. 3 | dnl 4 | dnl Redistribution and use in source and binary forms, with or without 5 | dnl modification, are permitted provided that the following conditions are 6 | dnl met: 7 | dnl 8 | dnl * Redistributions of source code must retain the above copyright 9 | dnl notice, this list of conditions and the following disclaimer. 10 | dnl * Redistributions in binary form must reproduce the above copyright 11 | dnl notice, this list of conditions and the following disclaimer in the 12 | dnl documentation and/or other materials provided with the distribution. 13 | dnl * Neither the name of Google Inc. nor the names of its contributors 14 | dnl may be used to endorse or promote products derived from this software 15 | dnl without specific prior written permission. 16 | dnl 17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | AC_INIT([Lutok], [0.6], 30 | [testing@FreeBSD.org], [lutok], 31 | [https://github.com/freebsd/lutok/]) 32 | AC_PREREQ([2.68]) 33 | 34 | 35 | AC_COPYRIGHT([Copyright 2011 Google Inc.]) 36 | AC_CONFIG_AUX_DIR([admin]) 37 | AC_CONFIG_FILES([Doxyfile Makefile]) 38 | AC_CONFIG_HEADERS([config.h]) 39 | AC_CONFIG_MACRO_DIR([m4]) 40 | AC_CONFIG_SRCDIR([state.hpp]) 41 | 42 | 43 | AM_INIT_AUTOMAKE([1.9 check-news foreign subdir-objects -Wall]) 44 | 45 | AM_PROG_AR 46 | LT_INIT 47 | 48 | 49 | AC_LANG([C++]) 50 | AC_PROG_CXX 51 | AX_CXX_COMPILE_STDCXX(14, noext, mandatory) 52 | KYUA_DEVELOPER_MODE([C++]) 53 | 54 | # Check for ATF and add --enable-atf flag 55 | AC_ARG_ENABLE([atf], 56 | [AS_HELP_STRING([--enable-atf], [Enable ATF tests (default: no)])], 57 | [enable_atf=$enableval], 58 | [enable_atf=no]) 59 | AM_CONDITIONAL([WITH_ATF], [test "x$enable_atf" = "xyes"]) 60 | 61 | # ATF dependencies 62 | m4_ifdef([ATF_CHECK_CXX],[ 63 | AS_IF([test "x$enable_atf" = "xyes"],[ 64 | ATF_CHECK_CXX([>= 0.21]) 65 | ATF_CHECK_SH([>= 0.21]) 66 | ],[AC_MSG_NOTICE([ATF support disabled])]) 67 | ]) 68 | 69 | KYUA_DOXYGEN 70 | KYUA_LUA 71 | 72 | # Check for Kyua 73 | AC_PATH_PROG([KYUA], [kyua]) 74 | AM_CONDITIONAL([HAVE_KYUA], [test -n "${KYUA}"]) 75 | 76 | # Check for Git 77 | AC_PATH_PROG([GIT], [git]) 78 | 79 | # Define pkg-config and tests directory 80 | AC_SUBST(pkgconfigdir, \${libdir}/pkgconfig) 81 | AC_SUBST(testsdir, \${exec_prefix}/tests/lutok) 82 | 83 | # Output configuration 84 | AC_OUTPUT 85 | -------------------------------------------------------------------------------- /debug.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #include 30 | 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | 39 | /// Internal implementation for lutok::debug. 40 | struct lutok::debug::impl { 41 | /// The Lua internal debug state. 42 | lua_Debug lua_debug; 43 | }; 44 | 45 | 46 | /// Constructor for an empty debug structure. 47 | lutok::debug::debug(void) : 48 | _pimpl(new impl()) 49 | { 50 | } 51 | 52 | 53 | /// Destructor. 54 | lutok::debug::~debug(void) 55 | { 56 | } 57 | 58 | 59 | /// Wrapper around lua_getinfo. 60 | /// 61 | /// \param s The Lua state. 62 | /// \param what_ The second parameter to lua_getinfo. 63 | /// 64 | /// \warning Terminates execution if there is not enough memory to manipulate 65 | /// the Lua stack. 66 | void 67 | lutok::debug::get_info(state& s, const std::string& what_) 68 | { 69 | lua_State* raw_state = state_c_gate(s).c_state(); 70 | 71 | if (lua_getinfo(raw_state, what_.c_str(), &_pimpl->lua_debug) == 0) 72 | throw lutok::api_error::from_stack(s, "lua_getinfo"); 73 | } 74 | 75 | 76 | /// Wrapper around lua_getstack. 77 | /// 78 | /// \param s The Lua state. 79 | /// \param level The second parameter to lua_getstack. 80 | void 81 | lutok::debug::get_stack(state& s, const int level) 82 | { 83 | lua_State* raw_state = state_c_gate(s).c_state(); 84 | 85 | lua_getstack(raw_state, level, &_pimpl->lua_debug); 86 | } 87 | 88 | 89 | /// Accessor for the 'event' field of lua_Debug. 90 | /// 91 | /// \return Returns the 'event' field of the internal lua_Debug structure. 92 | int 93 | lutok::debug::event(void) const 94 | { 95 | return _pimpl->lua_debug.event; 96 | } 97 | 98 | 99 | /// Accessor for the 'name' field of lua_Debug. 100 | /// 101 | /// \return Returns the 'name' field of the internal lua_Debug structure. 102 | std::string 103 | lutok::debug::name(void) const 104 | { 105 | assert(_pimpl->lua_debug.name != NULL); 106 | return _pimpl->lua_debug.name; 107 | } 108 | 109 | 110 | /// Accessor for the 'namewhat' field of lua_Debug. 111 | /// 112 | /// \return Returns the 'namewhat' field of the internal lua_Debug structure. 113 | std::string 114 | lutok::debug::name_what(void) const 115 | { 116 | assert(_pimpl->lua_debug.namewhat != NULL); 117 | return _pimpl->lua_debug.namewhat; 118 | } 119 | 120 | 121 | /// Accessor for the 'what' field of lua_Debug. 122 | /// 123 | /// \return Returns the 'what' field of the internal lua_Debug structure. 124 | std::string 125 | lutok::debug::what(void) const 126 | { 127 | assert(_pimpl->lua_debug.what != NULL); 128 | return _pimpl->lua_debug.what; 129 | } 130 | 131 | 132 | /// Accessor for the 'source' field of lua_Debug. 133 | /// 134 | /// \return Returns the 'source' field of the internal lua_Debug structure. 135 | std::string 136 | lutok::debug::source(void) const 137 | { 138 | assert(_pimpl->lua_debug.source != NULL); 139 | return _pimpl->lua_debug.source; 140 | } 141 | 142 | 143 | /// Accessor for the 'currentline' field of lua_Debug. 144 | /// 145 | /// \return Returns the 'currentline' field of the internal lua_Debug structure. 146 | int 147 | lutok::debug::current_line(void) const 148 | { 149 | return _pimpl->lua_debug.currentline; 150 | } 151 | 152 | 153 | /// Accessor for the 'nups' field of lua_Debug. 154 | /// 155 | /// \return Returns the 'nups' field of the internal lua_Debug structure. 156 | int 157 | lutok::debug::n_ups(void) const 158 | { 159 | return _pimpl->lua_debug.nups; 160 | } 161 | 162 | 163 | /// Accessor for the 'linedefined' field of lua_Debug. 164 | /// 165 | /// \return Returns the 'linedefined' field of the internal lua_Debug structure. 166 | int 167 | lutok::debug::line_defined(void) const 168 | { 169 | return _pimpl->lua_debug.linedefined; 170 | } 171 | 172 | 173 | /// Accessor for the 'lastlinedefined' field of lua_Debug. 174 | /// 175 | /// \return Returns the 'lastlinedefined' field of the internal lua_Debug 176 | /// structure. 177 | int 178 | lutok::debug::last_line_defined(void) const 179 | { 180 | return _pimpl->lua_debug.lastlinedefined; 181 | } 182 | 183 | 184 | /// Accessor for the 'short_src' field of lua_Debug. 185 | /// 186 | /// \return Returns the 'short_src' field of the internal lua_Debug structure. 187 | std::string 188 | lutok::debug::short_src(void) const 189 | { 190 | assert(_pimpl->lua_debug.short_src != NULL); 191 | return _pimpl->lua_debug.short_src; 192 | } 193 | -------------------------------------------------------------------------------- /debug.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file debug.hpp 30 | /// Provides the debug wrapper class for the Lua C debug state. 31 | 32 | #if !defined(LUTOK_DEBUG_HPP) 33 | #define LUTOK_DEBUG_HPP 34 | 35 | #include 36 | #include 37 | 38 | namespace lutok { 39 | 40 | 41 | class state; 42 | 43 | 44 | /// A model for the Lua debug state. 45 | /// 46 | /// This extremely-simple class provides a mechanism to hide the internals of 47 | /// the C native lua_Debug type, exposing its internal fields using friendlier 48 | /// C++ types. 49 | /// 50 | /// This class also acts as a complement to the state class by exposing any 51 | /// state-related functions as methods of this function. For example, while it 52 | /// might seem that get_info() belongs in state, we expose it from here because 53 | /// its result is really mutating a debug object, not the state object. 54 | class debug { 55 | struct impl; 56 | 57 | /// Pointer to the shared internal implementation. 58 | std::shared_ptr< impl > _pimpl; 59 | 60 | public: 61 | debug(void); 62 | ~debug(void); 63 | 64 | void get_info(state&, const std::string&); 65 | void get_stack(state&, const int); 66 | 67 | int event(void) const; 68 | std::string name(void) const; 69 | std::string name_what(void) const; 70 | std::string what(void) const; 71 | std::string source(void) const; 72 | int current_line(void) const; 73 | int n_ups(void) const; 74 | int line_defined(void) const; 75 | int last_line_defined(void) const; 76 | std::string short_src(void) const; 77 | }; 78 | 79 | 80 | } // namespace lutok 81 | 82 | #endif // !defined(LUTOK_DEBUG_HPP) 83 | -------------------------------------------------------------------------------- /debug_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #include "debug.hpp" 30 | 31 | #include 32 | #include 33 | 34 | #include "state.ipp" 35 | #include "test_utils.hpp" 36 | 37 | 38 | ATF_TEST_CASE_WITHOUT_HEAD(get_info); 39 | ATF_TEST_CASE_BODY(get_info) 40 | { 41 | lutok::state state; 42 | ATF_REQUIRE(luaL_dostring(raw(state), "\n\nfunction hello() end\n" 43 | "return hello") == 0); 44 | lutok::debug debug; 45 | debug.get_info(state, ">S"); 46 | ATF_REQUIRE_EQ(3, debug.line_defined()); 47 | } 48 | 49 | 50 | ATF_TEST_CASE_WITHOUT_HEAD(get_stack); 51 | ATF_TEST_CASE_BODY(get_stack) 52 | { 53 | lutok::state state; 54 | ATF_REQUIRE(luaL_dostring(raw(state), "error('Hello')") == 1); 55 | lutok::debug debug; 56 | debug.get_stack(state, 0); 57 | lua_pop(raw(state), 1); 58 | // Not sure if we can actually validate anything here, other than we did not 59 | // crash... (because get_stack only is supposed to update internal values of 60 | // the debug structure). 61 | } 62 | 63 | 64 | ATF_INIT_TEST_CASES(tcs) 65 | { 66 | ATF_ADD_TEST_CASE(tcs, get_info); 67 | ATF_ADD_TEST_CASE(tcs, get_stack); 68 | } 69 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2012 Google Inc. 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are 6 | # met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of Google Inc. nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | CXX ?= c++ 30 | CPPFLAGS ?= 31 | CXXFLAGS ?= -Wall -O2 32 | LDFLAGS ?= 33 | LIBS ?= 34 | 35 | LUTOK_CPPFLAGS = $$(pkg-config --cflags-only-I lutok) 36 | LUTOK_CXXFLAGS = $$(pkg-config --cflags-only-other lutok) 37 | LUTOK_LDFLAGS = $$(pkg-config --libs-only-L lutok) \ 38 | $$(pkg-config --libs-only-other lutok) 39 | LUTOK_LIBS = $$(pkg-config --libs-only-l lutok) 40 | 41 | BUILD = $(CXX) \ 42 | $(CPPFLAGS) $(LUTOK_CPPFLAGS) \ 43 | $(CXXFLAGS) $(LUTOK_CXXFLAGS) \ 44 | $(LDFLAGS) $(LUTOK_LDFLAGS) \ 45 | -o $${target} $${source} \ 46 | $(LIBS) $(LUTOK_LIBS) 47 | 48 | PROGRAMS = bindings hello interpreter raii 49 | 50 | .PHONY: all 51 | all: $(PROGRAMS) 52 | 53 | bindings: bindings.cpp 54 | @target=bindings source=bindings.cpp; echo $(BUILD); $(BUILD) 55 | 56 | hello: hello.cpp 57 | @target=hello source=hello.cpp; echo $(BUILD); $(BUILD) 58 | 59 | interpreter: interpreter.cpp 60 | @target=interpreter source=interpreter.cpp; echo $(BUILD); $(BUILD) 61 | 62 | raii: raii.cpp 63 | @target=raii source=raii.cpp; echo $(BUILD); $(BUILD) 64 | 65 | .PHONY: clean 66 | clean: 67 | rm -f $(PROGRAMS) 68 | -------------------------------------------------------------------------------- /examples/bindings.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file examples/bindings.cpp 30 | /// Showcases how to define Lua functions from C++ code. 31 | /// 32 | /// A major selling point of Lua is that it is very easy too hook native C and 33 | /// C++ functions into the runtime environment so that Lua can call them. The 34 | /// purpose of this example program is to show how this is done by using Lutok. 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include 45 | #include 46 | #include 47 | 48 | 49 | /// Calculates the factorial of a given number. 50 | /// 51 | /// \param i The postivie number to calculate the factorial of. 52 | /// 53 | /// \return The factorial of i. 54 | static int 55 | factorial(const int i) 56 | { 57 | assert(i >= 0); 58 | 59 | if (i == 0) 60 | return 1; 61 | else 62 | return i * factorial(i - 1); 63 | } 64 | 65 | 66 | /// A custom factorial function for Lua. 67 | /// 68 | /// \pre stack(-1) contains the number to calculate the factorial of. 69 | /// \post stack(-1) contains the result of the operation. 70 | /// 71 | /// \param state The Lua state from which to get the function arguments and into 72 | /// which to push the results. 73 | /// 74 | /// \return The number of results pushed onto the stack, i.e. 1. 75 | /// 76 | /// \throw std::runtime_error If the input parameters are invalid. Note that 77 | /// Lutok will convert this exception to lutok::error. 78 | static int 79 | lua_factorial(lutok::state& state) 80 | { 81 | if (!state.is_number(-1)) 82 | throw std::runtime_error("Argument to factorial must be an integer"); 83 | const int i = state.to_integer(-1); 84 | if (i < 0) 85 | throw std::runtime_error("Argument to factorial must be positive"); 86 | state.push_integer(factorial(i)); 87 | return 1; 88 | } 89 | 90 | 91 | /// Program's entry point. 92 | /// 93 | /// \param argc Length of argv. Must be 2. 94 | /// \param argv Command-line arguments to the program. The first argument to 95 | /// the tool has to be a number. 96 | /// 97 | /// \return A system exit code. 98 | int 99 | main(int argc, char** argv) 100 | { 101 | if (argc != 2) { 102 | std::cerr << "Usage: bindings \n"; 103 | return EXIT_FAILURE; 104 | } 105 | 106 | // Create a new Lua session and load the print() function. 107 | lutok::state state; 108 | state.open_base(); 109 | 110 | // Construct a 'module' that contains an entry point to our native factorial 111 | // function. A module is just a Lua table that contains a mapping of names 112 | // to functions. Instead of creating a module by using our create_module() 113 | // helper function, we could have used push_cxx_function on the state to 114 | // define the function ourselves. 115 | std::map< std::string, lutok::cxx_function > module; 116 | module["factorial"] = lua_factorial; 117 | lutok::create_module(state, "native", module); 118 | 119 | // Use a little Lua script to call our native factorial function providing 120 | // it the first argument passed to the program. Note that this will error 121 | // out in a controlled manner if the passed argument is not an integer. The 122 | // important thing to notice is that the exception comes from our own C++ 123 | // binding and that it has been converted to a lutok::error. 124 | std::ostringstream script; 125 | script << "print(native.factorial(" << argv[1] << "))"; 126 | try { 127 | lutok::do_string(state, script.str(), 0, 0, 0); 128 | return EXIT_SUCCESS; 129 | } catch (const lutok::error& e) { 130 | std::cerr << "ERROR: " << e.what() << '\n'; 131 | return EXIT_FAILURE; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /examples/hello.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file examples/hello.cpp 30 | /// Minimal example using Lua code to print a traditional hello-world message. 31 | 32 | #include 33 | 34 | #include 35 | 36 | 37 | /// Program's entry point. 38 | /// 39 | /// \return A system exit code. 40 | int 41 | main(void) 42 | { 43 | // Initializes a new Lua state. Every Lua state is independent from each 44 | // other. 45 | lutok::state state; 46 | 47 | // Loads the standard library into the Lua state. Among many other 48 | // functions, this gives us access to print(), which is used below. 49 | state.open_base(); 50 | 51 | // Pushes the print() function into the Lua stack, then its only argument, 52 | // and then proceeds to execute it within the Lua state. 53 | state.get_global("print"); 54 | state.push_string("Hello, world!"); 55 | state.pcall(1, 0, 0); 56 | 57 | return EXIT_SUCCESS; 58 | } 59 | -------------------------------------------------------------------------------- /examples/interpreter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file examples/interpreter.cpp 30 | /// Implementation of a basic command-line Lua interpreter. 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | 41 | /// Executes a Lua statement provided by the user with error checking. 42 | /// 43 | /// \param state The Lua state in which to process the statement. 44 | /// \param line The textual statement provided by the user. 45 | static void 46 | run_statement(lutok::state& state, const std::string& line) 47 | { 48 | try { 49 | // This utility function allows us to feed a given piece of Lua code to 50 | // the interpreter and process it. The piece of code can include 51 | // multiple statements separated by a semicolon or by a newline 52 | // character. 53 | lutok::do_string(state, line, 0, 0, 0); 54 | } catch (const lutok::error& error) { 55 | std::cerr << "ERROR: " << error.what() << '\n'; 56 | } 57 | } 58 | 59 | 60 | /// Program's entry point. 61 | /// 62 | /// \return A system exit code. 63 | int 64 | main(void) 65 | { 66 | // Create a new session and load some standard libraries. 67 | lutok::state state; 68 | state.open_base(); 69 | state.open_string(); 70 | state.open_table(); 71 | 72 | for (;;) { 73 | std::cout << "lua> "; 74 | std::cout.flush(); 75 | 76 | std::string line; 77 | if (!std::getline(std::cin, line).good()) 78 | break; 79 | run_statement(state, line); 80 | } 81 | 82 | return EXIT_SUCCESS; 83 | } 84 | -------------------------------------------------------------------------------- /examples/raii.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file examples/raii.cpp 30 | /// Demonstrates how RAII helps in keeping the Lua state consistent. 31 | /// 32 | /// One of the major complains that is raised against the Lua C API is that it 33 | /// is very hard to ensure it remains consistent during the execution of the 34 | /// program. In the case of native C code, there exist many tools that help the 35 | /// developer catch memory leaks, access to uninitialized variables, etc. 36 | /// However, when using the Lua C API, none of these tools can validate that, 37 | /// for example, the Lua stack remains balanced across calls. 38 | /// 39 | /// Enter RAII. The RAII pattern, intensively applied by Lutok, helps the 40 | /// developer in maintaining the Lua state consistent at all times in a 41 | /// transparent manner. This example program attempts to illustrate this. 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #include 49 | #include 50 | #include 51 | 52 | 53 | /// Prints the string-typed field of a table. 54 | /// 55 | /// If the field contains a string, this function prints its value. If the 56 | /// field contains any other type, this prints an error message. 57 | /// 58 | /// \pre The top of the Lua stack in 'state' references a table. 59 | /// 60 | /// \param state The Lua state. 61 | /// \param field The name of the string-typed field. 62 | static void 63 | print_table_field(lutok::state& state, const std::string& field) 64 | { 65 | assert(state.is_table(-1)); 66 | 67 | // Bring in some RAII magic: the stack_cleaner object captures the current 68 | // height of the Lua stack at this point. Whenever the object goes out of 69 | // scope, it will pop as many entries from the stack as necessary to restore 70 | // the stack to its previous level. 71 | // 72 | // This ensures that, no matter how we exit the function, we do not leak 73 | // objects in the stack. 74 | lutok::stack_cleaner cleaner(state); 75 | 76 | // Stack contents: -1: table. 77 | state.push_string(field); 78 | // Stack contents: -2: table, -1: field name. 79 | state.get_table(-2); 80 | // Stack contents: -2: table, -1: field value. 81 | 82 | if (!state.is_string(-1)) { 83 | std::cout << "The field " << field << " does not contain a string\n"; 84 | // Stack contents: -2: table, -1: field value. 85 | // 86 | // This is different than when we started! We should pop our extra 87 | // value from the stack at this point. However, it is extremely common 88 | // for software to have bugs (in this case, leaks) in error paths, 89 | // mostly because such code paths are rarely exercised. 90 | // 91 | // By using the stack_cleaner object, we can be confident that the Lua 92 | // stack will be cleared for us at this point, no matter what happened 93 | // earlier on the stack nor how we exit the function. 94 | return; 95 | } 96 | 97 | std::cout << "String in field " << field << ": " << state.to_string(-1) 98 | << '\n'; 99 | // A well-behaved program explicitly pops anything extra from the stack to 100 | // return it to its original state. Mostly for clarity. 101 | state.pop(1); 102 | 103 | // Stack contents: -1: table. Same as when we started. 104 | } 105 | 106 | 107 | /// Program's entry point. 108 | /// 109 | /// \return A system exit code. 110 | int 111 | main(void) 112 | { 113 | lutok::state state; 114 | state.open_base(); 115 | 116 | lutok::do_string(state, "example = {foo='hello', bar=123, baz='bye'}", 117 | 0, 0, 0); 118 | 119 | state.get_global("example"); 120 | print_table_field(state, "foo"); 121 | print_table_field(state, "bar"); 122 | print_table_field(state, "baz"); 123 | state.pop(1); 124 | 125 | return EXIT_SUCCESS; 126 | } 127 | -------------------------------------------------------------------------------- /examples_test.sh: -------------------------------------------------------------------------------- 1 | #! __ATF_SH__ 2 | # Copyright 2012 Google Inc. 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are 7 | # met: 8 | # 9 | # * Redistributions of source code must retain the above copyright 10 | # notice, this list of conditions and the following disclaimer. 11 | # * Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in the 13 | # documentation and/or other materials provided with the distribution. 14 | # * Neither the name of Google Inc. nor the names of its contributors 15 | # may be used to endorse or promote products derived from this software 16 | # without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | Cxx="__CXX__" 31 | ExamplesDir="__EXAMPLESDIR__" 32 | LibDir="__LIBDIR__" 33 | 34 | 35 | make_example() { 36 | cp "${ExamplesDir}/Makefile" "${ExamplesDir}/${1}.cpp" . 37 | make CXX="${Cxx}" "${1}" 38 | 39 | # Ensure that the binary we just built can find liblutok. This is 40 | # needed because the lutok.pc file (which the Makefile used above 41 | # queries) does not provide rpaths to the installed library and 42 | # therefore the binary may not be able to locate it. Hardcoding the 43 | # rpath flags into lutok.pc is non-trivial because we simply don't 44 | # have any knowledge about what the correct flag to set an rpath is. 45 | # 46 | # Additionally, setting rpaths is not always the right thing to do. 47 | # For example, pkgsrc will automatically change lutok.pc to add the 48 | # missing rpath, in which case this is unnecessary. But in the case 49 | # of Fedora, adding rpaths goes against the packaging guidelines. 50 | if [ -n "${LD_LIBRARY_PATH}" ]; then 51 | export LD_LIBRARY_PATH="${LibDir}:${LD_LIBRARY_PATH}" 52 | else 53 | export LD_LIBRARY_PATH="${LibDir}" 54 | fi 55 | } 56 | 57 | 58 | example_test_case() { 59 | local name="${1}"; shift 60 | 61 | atf_test_case "${name}" 62 | eval "${name}_head() { \ 63 | atf_set 'require.files' '${ExamplesDir}/${name}.cpp'; \ 64 | atf_set 'require.progs' 'make pkg-config'; \ 65 | }" 66 | eval "${name}_body() { \ 67 | make_example '${name}'; \ 68 | ${name}_validate; \ 69 | }" 70 | } 71 | 72 | 73 | example_test_case bindings 74 | bindings_validate() { 75 | atf_check -s exit:0 -o inline:'120\n' ./bindings 5 76 | atf_check -s exit:1 -e match:'Argument.*must be an integer' ./bindings foo 77 | atf_check -s exit:1 -e match:'Argument.*must be positive' ./bindings -5 78 | } 79 | 80 | 81 | example_test_case hello 82 | hello_validate() { 83 | atf_check -s exit:0 -o inline:'Hello, world!\n' ./hello 84 | } 85 | 86 | 87 | example_test_case interpreter 88 | interpreter_validate() { 89 | cat >script.lua <expout < 30 | 31 | #include 32 | 33 | #include "c_gate.hpp" 34 | #include "exceptions.hpp" 35 | #include "state.ipp" 36 | 37 | 38 | /// Constructs a new error with a plain-text message. 39 | /// 40 | /// \param message The plain-text error message. 41 | lutok::error::error(const std::string& message) : 42 | std::runtime_error(message) 43 | { 44 | } 45 | 46 | 47 | /// Destructor for the error. 48 | lutok::error::~error(void) throw() 49 | { 50 | } 51 | 52 | 53 | /// Constructs a new error. 54 | /// 55 | /// \param api_function_ The name of the API function that caused the error. 56 | /// \param message The plain-text error message provided by Lua. 57 | lutok::api_error::api_error(const std::string& api_function_, 58 | const std::string& message) : 59 | error(message), 60 | _api_function(api_function_) 61 | { 62 | } 63 | 64 | 65 | /// Destructor for the error. 66 | lutok::api_error::~api_error(void) throw() 67 | { 68 | } 69 | 70 | 71 | /// Constructs a new api_error with the message on the top of the Lua stack. 72 | /// 73 | /// \pre There is an error message on the top of the stack. 74 | /// \post The error message is popped from the stack. 75 | /// 76 | /// \param state_ The Lua state. 77 | /// \param api_function_ The name of the Lua API function that caused the error. 78 | /// 79 | /// \return A new api_error with the popped message. 80 | lutok::api_error 81 | lutok::api_error::from_stack(state& state_, const std::string& api_function_) 82 | { 83 | lua_State* raw_state = lutok::state_c_gate(state_).c_state(); 84 | 85 | assert(lua_isstring(raw_state, -1)); 86 | const std::string message = lua_tostring(raw_state, -1); 87 | lua_pop(raw_state, 1); 88 | return lutok::api_error(api_function_, message); 89 | } 90 | 91 | 92 | /// Gets the name of the Lua API function that caused this error. 93 | /// 94 | /// \return The name of the function. 95 | const std::string& 96 | lutok::api_error::api_function(void) const 97 | { 98 | return _api_function; 99 | } 100 | 101 | 102 | /// Constructs a new error. 103 | /// 104 | /// \param filename_ The file that count not be found. 105 | lutok::file_not_found_error::file_not_found_error( 106 | const std::string& filename_) : 107 | error("File '" + filename_ + "' not found"), 108 | _filename(filename_) 109 | { 110 | } 111 | 112 | 113 | /// Destructor for the error. 114 | lutok::file_not_found_error::~file_not_found_error(void) throw() 115 | { 116 | } 117 | 118 | 119 | /// Gets the name of the file that could not be found. 120 | /// 121 | /// \return The name of the file. 122 | const std::string& 123 | lutok::file_not_found_error::filename(void) const 124 | { 125 | return _filename; 126 | } 127 | -------------------------------------------------------------------------------- /exceptions.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file exceptions.hpp 30 | /// Exception types raised by lutok. 31 | 32 | #if !defined(LUTOK_EXCEPTIONS_HPP) 33 | #define LUTOK_EXCEPTIONS_HPP 34 | 35 | #include 36 | #include 37 | 38 | namespace lutok { 39 | 40 | 41 | class state; 42 | 43 | 44 | /// Base exception for lua errors. 45 | class error : public std::runtime_error { 46 | public: 47 | explicit error(const std::string&); 48 | virtual ~error(void) throw(); 49 | }; 50 | 51 | 52 | /// Exception for errors raised by the Lua API library. 53 | class api_error : public error { 54 | /// Name of the Lua C API function that caused the error. 55 | std::string _api_function; 56 | 57 | public: 58 | explicit api_error(const std::string&, const std::string&); 59 | virtual ~api_error(void) throw(); 60 | 61 | static api_error from_stack(state&, const std::string&); 62 | 63 | const std::string& api_function(void) const; 64 | }; 65 | 66 | 67 | /// File not found error. 68 | class file_not_found_error : public error { 69 | /// Name of the not-found file. 70 | std::string _filename; 71 | 72 | public: 73 | explicit file_not_found_error(const std::string&); 74 | virtual ~file_not_found_error(void) throw(); 75 | 76 | const std::string& filename(void) const; 77 | }; 78 | 79 | 80 | } // namespace lutok 81 | 82 | 83 | #endif // !defined(LUTOK_EXCEPTIONS_HPP) 84 | -------------------------------------------------------------------------------- /exceptions_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #include "exceptions.hpp" 30 | 31 | #include 32 | 33 | #include 34 | 35 | #include "state.ipp" 36 | 37 | 38 | ATF_TEST_CASE_WITHOUT_HEAD(error); 39 | ATF_TEST_CASE_BODY(error) 40 | { 41 | const lutok::error e("Some text"); 42 | ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); 43 | } 44 | 45 | 46 | ATF_TEST_CASE_WITHOUT_HEAD(api_error__explicit); 47 | ATF_TEST_CASE_BODY(api_error__explicit) 48 | { 49 | const lutok::api_error e("some_function", "Some text"); 50 | ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); 51 | ATF_REQUIRE_EQ("some_function", e.api_function()); 52 | } 53 | 54 | 55 | ATF_TEST_CASE_WITHOUT_HEAD(api_error__from_stack); 56 | ATF_TEST_CASE_BODY(api_error__from_stack) 57 | { 58 | lutok::state state; 59 | state.push_integer(123); 60 | state.push_string("The error message"); 61 | const lutok::api_error e = lutok::api_error::from_stack(state, 62 | "the_function"); 63 | ATF_REQUIRE_EQ(1, state.get_top()); 64 | ATF_REQUIRE_EQ(123, state.to_integer(-1)); 65 | state.pop(1); 66 | ATF_REQUIRE(std::strcmp("The error message", e.what()) == 0); 67 | ATF_REQUIRE_EQ("the_function", e.api_function()); 68 | } 69 | 70 | 71 | ATF_TEST_CASE_WITHOUT_HEAD(file_not_found_error); 72 | ATF_TEST_CASE_BODY(file_not_found_error) 73 | { 74 | const lutok::file_not_found_error e("missing-file"); 75 | ATF_REQUIRE(std::strcmp("File 'missing-file' not found", e.what()) == 0); 76 | ATF_REQUIRE_EQ("missing-file", e.filename()); 77 | } 78 | 79 | 80 | ATF_INIT_TEST_CASES(tcs) 81 | { 82 | ATF_ADD_TEST_CASE(tcs, error); 83 | 84 | ATF_ADD_TEST_CASE(tcs, api_error__explicit); 85 | ATF_ADD_TEST_CASE(tcs, api_error__from_stack); 86 | 87 | ATF_ADD_TEST_CASE(tcs, file_not_found_error); 88 | } 89 | -------------------------------------------------------------------------------- /include/lutok/README: -------------------------------------------------------------------------------- 1 | This directory contains forward includes for the public header files of 2 | Lutok. These files are only necessary during the build of Lutok itself 3 | so that the compiler can locate the include files in a path that mimics 4 | the final installation location. 5 | -------------------------------------------------------------------------------- /include/lutok/c_gate.hpp: -------------------------------------------------------------------------------- 1 | #include "../../c_gate.hpp" 2 | -------------------------------------------------------------------------------- /include/lutok/debug.hpp: -------------------------------------------------------------------------------- 1 | #include "../../debug.hpp" 2 | -------------------------------------------------------------------------------- /include/lutok/exceptions.hpp: -------------------------------------------------------------------------------- 1 | #include "../../exceptions.hpp" 2 | -------------------------------------------------------------------------------- /include/lutok/operations.hpp: -------------------------------------------------------------------------------- 1 | #include "../../operations.hpp" 2 | -------------------------------------------------------------------------------- /include/lutok/stack_cleaner.hpp: -------------------------------------------------------------------------------- 1 | #include "../../stack_cleaner.hpp" 2 | -------------------------------------------------------------------------------- /include/lutok/state.hpp: -------------------------------------------------------------------------------- 1 | #include "../../state.hpp" 2 | -------------------------------------------------------------------------------- /include/lutok/state.ipp: -------------------------------------------------------------------------------- 1 | #include "../../state.ipp" 2 | -------------------------------------------------------------------------------- /lutok.pc.in: -------------------------------------------------------------------------------- 1 | includedir=__INCLUDEDIR__ 2 | libdir=__LIBDIR__ 3 | 4 | Name: lutok 5 | Description: Lightweight C++ API for Lua 6 | Version: __VERSION__ 7 | Cflags: __LUA_CFLAGS__ -I${includedir} 8 | Libs: __LUA_LIBS__ -L${libdir} -llutok 9 | -------------------------------------------------------------------------------- /m4/.gitignore: -------------------------------------------------------------------------------- 1 | libtool.m4 2 | ltoptions.m4 3 | ltsugar.m4 4 | ltversion.m4 5 | lt~obsolete.m4 6 | -------------------------------------------------------------------------------- /m4/atf-c++.m4: -------------------------------------------------------------------------------- 1 | dnl Copyright 2011 Google Inc. 2 | dnl All rights reserved. 3 | dnl 4 | dnl Redistribution and use in source and binary forms, with or without 5 | dnl modification, are permitted provided that the following conditions are 6 | dnl met: 7 | dnl 8 | dnl * Redistributions of source code must retain the above copyright 9 | dnl notice, this list of conditions and the following disclaimer. 10 | dnl * Redistributions in binary form must reproduce the above copyright 11 | dnl notice, this list of conditions and the following disclaimer in the 12 | dnl documentation and/or other materials provided with the distribution. 13 | dnl * Neither the name of Google Inc. nor the names of its contributors 14 | dnl may be used to endorse or promote products derived from this software 15 | dnl without specific prior written permission. 16 | dnl 17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | dnl ATF_CHECK_CXX([version-spec]) 30 | dnl 31 | dnl Checks if atf-c++ is present. If version-spec is provided, ensures that 32 | dnl the installed version of atf-sh matches the required version. This 33 | dnl argument must be something like '>= 0.14' and accepts any version 34 | dnl specification supported by pkg-config. 35 | dnl 36 | dnl Defines and substitutes ATF_CXX_CFLAGS and ATF_CXX_LIBS with the compiler 37 | dnl and linker flags need to build against atf-c++. 38 | AC_DEFUN([ATF_CHECK_CXX], [ 39 | spec="atf-c++[]m4_default_nblank([ $1], [])" 40 | _ATF_CHECK_ARG_WITH( 41 | [PKG_CHECK_MODULES([ATF_CXX], [${spec}], 42 | [found=yes found_atf_cxx=yes], [found=no])], 43 | [required ${spec} not found]) 44 | ]) 45 | -------------------------------------------------------------------------------- /m4/atf-c.m4: -------------------------------------------------------------------------------- 1 | dnl Copyright 2011 Google Inc. 2 | dnl All rights reserved. 3 | dnl 4 | dnl Redistribution and use in source and binary forms, with or without 5 | dnl modification, are permitted provided that the following conditions are 6 | dnl met: 7 | dnl 8 | dnl * Redistributions of source code must retain the above copyright 9 | dnl notice, this list of conditions and the following disclaimer. 10 | dnl * Redistributions in binary form must reproduce the above copyright 11 | dnl notice, this list of conditions and the following disclaimer in the 12 | dnl documentation and/or other materials provided with the distribution. 13 | dnl * Neither the name of Google Inc. nor the names of its contributors 14 | dnl may be used to endorse or promote products derived from this software 15 | dnl without specific prior written permission. 16 | dnl 17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | dnl ATF_CHECK_C([version-spec]) 30 | dnl 31 | dnl Checks if atf-c is present. If version-spec is provided, ensures that 32 | dnl the installed version of atf-sh matches the required version. This 33 | dnl argument must be something like '>= 0.14' and accepts any version 34 | dnl specification supported by pkg-config. 35 | dnl 36 | dnl Defines and substitutes ATF_C_CFLAGS and ATF_C_LIBS with the compiler 37 | dnl and linker flags need to build against atf-c. 38 | AC_DEFUN([ATF_CHECK_C], [ 39 | spec="atf-c[]m4_default_nblank([ $1], [])" 40 | _ATF_CHECK_ARG_WITH( 41 | [PKG_CHECK_MODULES([ATF_C], [${spec}], 42 | [found=yes found_atf_c=yes], [found=no])], 43 | [required ${spec} not found]) 44 | ]) 45 | -------------------------------------------------------------------------------- /m4/atf-common.m4: -------------------------------------------------------------------------------- 1 | dnl Copyright 2011 Google Inc. 2 | dnl All rights reserved. 3 | dnl 4 | dnl Redistribution and use in source and binary forms, with or without 5 | dnl modification, are permitted provided that the following conditions are 6 | dnl met: 7 | dnl 8 | dnl * Redistributions of source code must retain the above copyright 9 | dnl notice, this list of conditions and the following disclaimer. 10 | dnl * Redistributions in binary form must reproduce the above copyright 11 | dnl notice, this list of conditions and the following disclaimer in the 12 | dnl documentation and/or other materials provided with the distribution. 13 | dnl * Neither the name of Google Inc. nor the names of its contributors 14 | dnl may be used to endorse or promote products derived from this software 15 | dnl without specific prior written permission. 16 | dnl 17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | dnl ATF_ARG_WITH 30 | dnl 31 | dnl Adds a --with-atf flag to the configure script that allows the user to 32 | dnl enable or disable atf support. 33 | dnl 34 | dnl The ATF_CHECK_{C,CXX,SH} macros honor the flag defined herein if 35 | dnl instantiated. If not instantiated, they will request the presence of 36 | dnl the libraries unconditionally. 37 | dnl 38 | dnl Defines the WITH_ATF Automake conditional if ATF has been found by any 39 | dnl of the ATF_CHECK_{C,CXX,SH} macros. 40 | AC_DEFUN([ATF_ARG_WITH], [ 41 | m4_define([atf_arg_with_called], [yes]) 42 | 43 | m4_divert_text([DEFAULTS], [with_atf=auto]) 44 | AC_ARG_WITH([atf], 45 | [AS_HELP_STRING([--with-atf=], 46 | [build atf-based test programs])], 47 | [with_atf=${withval}], [with_atf=auto]) 48 | 49 | m4_divert_text([DEFAULTS], [ 50 | found_atf_c=no 51 | found_atf_cxx=no 52 | found_atf_sh=no 53 | ]) 54 | AM_CONDITIONAL([WITH_ATF], [test x"${found_atf_c}" = x"yes" -o \ 55 | x"${found_atf_cxx}" = x"yes" -o \ 56 | x"${found_atf_sh}" = x"yes"]) 57 | ]) 58 | 59 | dnl _ATF_CHECK_ARG_WITH(check, error_message) 60 | dnl 61 | dnl Internal macro to execute a check conditional on the --with-atf flag 62 | dnl and handle the result accordingly. 63 | dnl 64 | dnl 'check' specifies the piece of code to be run to detect the feature. 65 | dnl This code must set the 'found' shell variable to yes or no depending 66 | dnl on the raw result of the check. 67 | AC_DEFUN([_ATF_CHECK_ARG_WITH], [ 68 | m4_ifdef([atf_arg_with_called], [ 69 | m4_fatal([ATF_ARG_WITH must be called after the ATF_CHECK_* checks]) 70 | ]) 71 | 72 | m4_divert_text([DEFAULTS], [with_atf=yes]) 73 | 74 | if test x"${with_atf}" = x"no"; then 75 | _found=no 76 | else 77 | $1 78 | if test x"${with_atf}" = x"auto"; then 79 | _found="${found}" 80 | else 81 | if test x"${found}" = x"yes"; then 82 | _found=yes 83 | else 84 | AC_MSG_ERROR([$2]) 85 | fi 86 | fi 87 | fi 88 | ]) 89 | -------------------------------------------------------------------------------- /m4/atf-sh.m4: -------------------------------------------------------------------------------- 1 | dnl Copyright 2011 Google Inc. 2 | dnl All rights reserved. 3 | dnl 4 | dnl Redistribution and use in source and binary forms, with or without 5 | dnl modification, are permitted provided that the following conditions are 6 | dnl met: 7 | dnl 8 | dnl * Redistributions of source code must retain the above copyright 9 | dnl notice, this list of conditions and the following disclaimer. 10 | dnl * Redistributions in binary form must reproduce the above copyright 11 | dnl notice, this list of conditions and the following disclaimer in the 12 | dnl documentation and/or other materials provided with the distribution. 13 | dnl * Neither the name of Google Inc. nor the names of its contributors 14 | dnl may be used to endorse or promote products derived from this software 15 | dnl without specific prior written permission. 16 | dnl 17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | dnl ATF_CHECK_SH([version-spec]) 30 | dnl 31 | dnl Checks if atf-sh is present. If version-spec is provided, ensures that 32 | dnl the installed version of atf-sh matches the required version. This 33 | dnl argument must be something like '>= 0.14' and accepts any version 34 | dnl specification supported by pkg-config. 35 | dnl 36 | dnl Defines and substitutes ATF_SH with the full path to the atf-sh interpreter. 37 | AC_DEFUN([ATF_CHECK_SH], [ 38 | spec="atf-sh[]m4_default_nblank([ $1], [])" 39 | _ATF_CHECK_ARG_WITH( 40 | [AC_MSG_CHECKING([for ${spec}]) 41 | PKG_CHECK_EXISTS([${spec}], [found=yes], [found=no]) 42 | if test "${found}" = yes; then 43 | ATF_SH="$(${PKG_CONFIG} --variable=interpreter atf-sh)" 44 | AC_SUBST([ATF_SH], [${ATF_SH}]) 45 | found_atf_sh=yes 46 | fi 47 | AC_MSG_RESULT([${ATF_SH}])], 48 | [required ${spec} not found]) 49 | ]) 50 | -------------------------------------------------------------------------------- /m4/compiler-features.m4: -------------------------------------------------------------------------------- 1 | dnl Copyright 2010 Google Inc. 2 | dnl All rights reserved. 3 | dnl 4 | dnl Redistribution and use in source and binary forms, with or without 5 | dnl modification, are permitted provided that the following conditions are 6 | dnl met: 7 | dnl 8 | dnl * Redistributions of source code must retain the above copyright 9 | dnl notice, this list of conditions and the following disclaimer. 10 | dnl * Redistributions in binary form must reproduce the above copyright 11 | dnl notice, this list of conditions and the following disclaimer in the 12 | dnl documentation and/or other materials provided with the distribution. 13 | dnl * Neither the name of Google Inc. nor the names of its contributors 14 | dnl may be used to endorse or promote products derived from this software 15 | dnl without specific prior written permission. 16 | dnl 17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | dnl 30 | dnl KYUA_ATTRIBUTE_NORETURN 31 | dnl 32 | dnl Checks if the current compiler has a way to mark functions that do not 33 | dnl return and defines ATTRIBUTE_NORETURN to the appropriate string. 34 | dnl 35 | AC_DEFUN([KYUA_ATTRIBUTE_NORETURN], [ 36 | dnl This check is overly simple and should be fixed. For example, 37 | dnl Sun's cc does support the noreturn attribute but CC (the C++ 38 | dnl compiler) does not. And in that case, CC just raises a warning 39 | dnl during compilation, not an error. 40 | AC_MSG_CHECKING(whether __attribute__((noreturn)) is supported) 41 | AC_RUN_IFELSE([AC_LANG_PROGRAM([], [ 42 | #if ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2) 43 | return 0; 44 | #else 45 | return 1; 46 | #endif 47 | ])], 48 | [AC_MSG_RESULT(yes) 49 | value="__attribute__((noreturn))"], 50 | [AC_MSG_RESULT(no) 51 | value=""] 52 | ) 53 | AC_SUBST([ATTRIBUTE_NORETURN], [${value}]) 54 | ]) 55 | 56 | 57 | dnl 58 | dnl KYUA_ATTRIBUTE_UNUSED 59 | dnl 60 | dnl Checks if the current compiler has a way to mark parameters as unused 61 | dnl so that the -Wunused-parameter warning can be avoided. 62 | dnl 63 | AC_DEFUN([KYUA_ATTRIBUTE_UNUSED], [ 64 | AC_MSG_CHECKING(whether __attribute__((__unused__)) is supported) 65 | AC_COMPILE_IFELSE( 66 | [AC_LANG_PROGRAM([ 67 | static void 68 | function(int a __attribute__((__unused__))) 69 | { 70 | }], [ 71 | function(3); 72 | return 0; 73 | ])], 74 | [AC_MSG_RESULT(yes) 75 | value="__attribute__((__unused__))"], 76 | [AC_MSG_RESULT(no) 77 | value=""] 78 | ) 79 | AC_SUBST([ATTRIBUTE_UNUSED], [${value}]) 80 | ]) 81 | -------------------------------------------------------------------------------- /m4/compiler-flags.m4: -------------------------------------------------------------------------------- 1 | dnl Copyright 2010 Google Inc. 2 | dnl All rights reserved. 3 | dnl 4 | dnl Redistribution and use in source and binary forms, with or without 5 | dnl modification, are permitted provided that the following conditions are 6 | dnl met: 7 | dnl 8 | dnl * Redistributions of source code must retain the above copyright 9 | dnl notice, this list of conditions and the following disclaimer. 10 | dnl * Redistributions in binary form must reproduce the above copyright 11 | dnl notice, this list of conditions and the following disclaimer in the 12 | dnl documentation and/or other materials provided with the distribution. 13 | dnl * Neither the name of Google Inc. nor the names of its contributors 14 | dnl may be used to endorse or promote products derived from this software 15 | dnl without specific prior written permission. 16 | dnl 17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | dnl \file compiler-flags.m4 30 | dnl 31 | dnl Macros to check for the existence of compiler flags. The macros in this 32 | dnl file support both C and C++. 33 | dnl 34 | dnl Be aware that, in order to detect a flag accurately, we may need to enable 35 | dnl strict warning checking in the compiler (i.e. enable -Werror). Some 36 | dnl compilers, e.g. Clang, report unknown -W flags as warnings unless -Werror is 37 | dnl selected. This fact would confuse the flag checks below because we would 38 | dnl conclude that a flag is valid while in reality it is not. To resolve this, 39 | dnl the macros below will pass -Werror to the compiler along with any other flag 40 | dnl being checked. 41 | 42 | 43 | dnl Checks for a compiler flag and sets a result variable. 44 | dnl 45 | dnl This is an auxiliary macro for the implementation of _KYUA_FLAG. 46 | dnl 47 | dnl \param 1 The shell variable containing the compiler name. Used for 48 | dnl reporting purposes only. C or CXX. 49 | dnl \param 2 The shell variable containing the flags for the compiler. 50 | dnl CFLAGS or CXXFLAGS. 51 | dnl \param 3 The name of the compiler flag to check for. 52 | dnl \param 4 The shell variable to set with the result of the test. Will 53 | dnl be set to 'yes' if the flag is valid, 'no' otherwise. 54 | dnl \param 5 Additional, optional flags to pass to the C compiler while 55 | dnl looking for the flag in $3. We use this here to pass -Werror to the 56 | dnl flag checks (unless we are checking for -Werror already). 57 | AC_DEFUN([_KYUA_FLAG_AUX], [ 58 | if test x"${$4-unset}" = xunset; then 59 | AC_MSG_CHECKING(whether ${$1} supports $3) 60 | saved_flags="${$2}" 61 | $4=no 62 | $2="${$2} $5 $3" 63 | AC_LINK_IFELSE([AC_LANG_PROGRAM([], [return 0;])], 64 | AC_MSG_RESULT(yes) 65 | $4=yes, 66 | AC_MSG_RESULT(no)) 67 | $2="${saved_flags}" 68 | fi 69 | ]) 70 | 71 | 72 | dnl Checks for a compiler flag and appends it to a result variable. 73 | dnl 74 | dnl \param 1 The shell variable containing the compiler name. Used for 75 | dnl reporting purposes only. CC or CXX. 76 | dnl \param 2 The shell variable containing the flags for the compiler. 77 | dnl CFLAGS or CXXFLAGS. 78 | dnl \param 3 The name of the compiler flag to check for. 79 | dnl \param 4 The shell variable to which to append $3 if the flag is valid. 80 | AC_DEFUN([_KYUA_FLAG], [ 81 | _KYUA_FLAG_AUX([$1], [$2], [-Werror], [kyua_$1_has_werror]) 82 | if test "$3" = "-Werror"; then 83 | found=${kyua_$1_has_werror} 84 | else 85 | found=unset 86 | if test ${kyua_$1_has_werror} = yes; then 87 | _KYUA_FLAG_AUX([$1], [$2], [$3], [found], [-Werror]) 88 | else 89 | _KYUA_FLAG_AUX([$1], [$2], [$3], [found], []) 90 | fi 91 | fi 92 | if test ${found} = yes; then 93 | $4="${$4} $3" 94 | fi 95 | ]) 96 | 97 | 98 | dnl Checks for a C compiler flag and appends it to a variable. 99 | dnl 100 | dnl \pre The current language is C. 101 | dnl 102 | dnl \param 1 The name of the compiler flag to check for. 103 | dnl \param 2 The shell variable to which to append $1 if the flag is valid. 104 | AC_DEFUN([KYUA_CC_FLAG], [ 105 | AC_LANG_ASSERT([C]) 106 | _KYUA_FLAG([CC], [CFLAGS], [$1], [$2]) 107 | ]) 108 | 109 | 110 | dnl Checks for a C++ compiler flag and appends it to a variable. 111 | dnl 112 | dnl \pre The current language is C++. 113 | dnl 114 | dnl \param 1 The name of the compiler flag to check for. 115 | dnl \param 2 The shell variable to which to append $1 if the flag is valid. 116 | AC_DEFUN([KYUA_CXX_FLAG], [ 117 | AC_LANG_ASSERT([C++]) 118 | _KYUA_FLAG([CXX], [CXXFLAGS], [$1], [$2]) 119 | ]) 120 | 121 | 122 | dnl Checks for a set of C compiler flags and appends them to CFLAGS. 123 | dnl 124 | dnl The checks are performed independently and only when all the checks are 125 | dnl done, the output variable is modified. 126 | dnl 127 | dnl \param 1 Whitespace-separated list of C flags to check. 128 | AC_DEFUN([KYUA_CC_FLAGS], [ 129 | AC_LANG_PUSH([C]) 130 | valid_cflags= 131 | for f in $1; do 132 | KYUA_CC_FLAG(${f}, valid_cflags) 133 | done 134 | if test -n "${valid_cflags}"; then 135 | CFLAGS="${CFLAGS} ${valid_cflags}" 136 | fi 137 | AC_LANG_POP([C]) 138 | ]) 139 | 140 | 141 | dnl Checks for a set of C++ compiler flags and appends them to CXXFLAGS. 142 | dnl 143 | dnl The checks are performed independently and only when all the checks are 144 | dnl done, the output variable is modified. 145 | dnl 146 | dnl \pre The current language is C++. 147 | dnl 148 | dnl \param 1 Whitespace-separated list of C flags to check. 149 | AC_DEFUN([KYUA_CXX_FLAGS], [ 150 | AC_LANG_PUSH([C++]) 151 | valid_cxxflags= 152 | for f in $1; do 153 | KYUA_CXX_FLAG(${f}, valid_cxxflags) 154 | done 155 | if test -n "${valid_cxxflags}"; then 156 | CXXFLAGS="${CXXFLAGS} ${valid_cxxflags}" 157 | fi 158 | AC_LANG_POP([C++]) 159 | ]) 160 | -------------------------------------------------------------------------------- /m4/developer-mode.m4: -------------------------------------------------------------------------------- 1 | dnl Copyright 2010 Google Inc. 2 | dnl All rights reserved. 3 | dnl 4 | dnl Redistribution and use in source and binary forms, with or without 5 | dnl modification, are permitted provided that the following conditions are 6 | dnl met: 7 | dnl 8 | dnl * Redistributions of source code must retain the above copyright 9 | dnl notice, this list of conditions and the following disclaimer. 10 | dnl * Redistributions in binary form must reproduce the above copyright 11 | dnl notice, this list of conditions and the following disclaimer in the 12 | dnl documentation and/or other materials provided with the distribution. 13 | dnl * Neither the name of Google Inc. nor the names of its contributors 14 | dnl may be used to endorse or promote products derived from this software 15 | dnl without specific prior written permission. 16 | dnl 17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | dnl \file developer-mode.m4 30 | dnl 31 | dnl "Developer mode" is a mode in which the build system reports any 32 | dnl build-time warnings as fatal errors. This helps in minimizing the 33 | dnl amount of trivial coding problems introduced in the code. 34 | dnl Unfortunately, this is not bullet-proof due to the wide variety of 35 | dnl compilers available and their different warning diagnostics. 36 | dnl 37 | dnl When developer mode support is added to a package, the compilation will 38 | dnl gain a bunch of extra warning diagnostics. These will NOT be enforced 39 | dnl unless developer mode is enabled. 40 | dnl 41 | dnl Developer mode is enabled when the user requests it through the 42 | dnl configure command line, or when building from the repository. The 43 | dnl latter is to minimize the risk of committing new code with warnings 44 | dnl into the tree. 45 | 46 | 47 | dnl Adds "developer mode" support to the package. 48 | dnl 49 | dnl This macro performs the actual definition of the --enable-developer 50 | dnl flag and implements all of its logic. See the file-level comment for 51 | dnl details as to what this implies. 52 | AC_DEFUN([KYUA_DEVELOPER_MODE], [ 53 | m4_foreach([language], [$1], [m4_set_add([languages], language)]) 54 | 55 | AC_ARG_ENABLE( 56 | [developer], 57 | AS_HELP_STRING([--enable-developer], [enable developer features]),, 58 | [if test -d ${srcdir}/.git; then 59 | AC_MSG_NOTICE([building from HEAD; developer mode autoenabled]) 60 | enable_developer=yes 61 | else 62 | enable_developer=no 63 | fi]) 64 | 65 | # 66 | # The following warning flags should also be enabled but cannot be. 67 | # Reasons given below. 68 | # 69 | # -Wold-style-cast: Raises errors when using TIOCGWINSZ, at least under 70 | # Mac OS X. This is due to the way _IOR is defined. 71 | # 72 | 73 | try_c_cxx_flags="-D_FORTIFY_SOURCE=2 \ 74 | -Wall \ 75 | -Wcast-qual \ 76 | -Wextra \ 77 | -Wpointer-arith \ 78 | -Wredundant-decls \ 79 | -Wreturn-type \ 80 | -Wshadow \ 81 | -Wsign-compare \ 82 | -Wswitch \ 83 | -Wwrite-strings" 84 | 85 | try_c_flags="-Wmissing-prototypes \ 86 | -Wno-traditional \ 87 | -Wstrict-prototypes" 88 | 89 | try_cxx_flags="-Wabi \ 90 | -Wctor-dtor-privacy \ 91 | -Wno-deprecated \ 92 | -Wno-non-template-friend \ 93 | -Wno-pmf-conversions \ 94 | -Wnon-virtual-dtor \ 95 | -Woverloaded-virtual \ 96 | -Wreorder \ 97 | -Wsign-promo \ 98 | -Wsynth" 99 | 100 | if test ${enable_developer} = yes; then 101 | try_werror=yes 102 | try_c_cxx_flags="${try_c_cxx_flags} -g -Werror" 103 | else 104 | try_werror=no 105 | try_c_cxx_flags="${try_c_cxx_flags} -DNDEBUG" 106 | fi 107 | 108 | m4_set_contains([languages], [C], 109 | [KYUA_CC_FLAGS(${try_c_cxx_flags} ${try_c_flags})]) 110 | m4_set_contains([languages], [C++], 111 | [KYUA_CXX_FLAGS(${try_c_cxx_flags} ${try_cxx_flags})]) 112 | ]) 113 | -------------------------------------------------------------------------------- /m4/doxygen.m4: -------------------------------------------------------------------------------- 1 | dnl Copyright 2010 Google Inc. 2 | dnl All rights reserved. 3 | dnl 4 | dnl Redistribution and use in source and binary forms, with or without 5 | dnl modification, are permitted provided that the following conditions are 6 | dnl met: 7 | dnl 8 | dnl * Redistributions of source code must retain the above copyright 9 | dnl notice, this list of conditions and the following disclaimer. 10 | dnl * Redistributions in binary form must reproduce the above copyright 11 | dnl notice, this list of conditions and the following disclaimer in the 12 | dnl documentation and/or other materials provided with the distribution. 13 | dnl * Neither the name of Google Inc. nor the names of its contributors 14 | dnl may be used to endorse or promote products derived from this software 15 | dnl without specific prior written permission. 16 | dnl 17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | dnl 30 | dnl KYUA_DOXYGEN 31 | dnl 32 | dnl Adds a --with-doxygen flag to the configure script and, when Doxygen support 33 | dnl is requested by the user, sets DOXYGEN to the path of the Doxygen binary and 34 | dnl enables the WITH_DOXYGEN Automake conditional. 35 | dnl 36 | AC_DEFUN([KYUA_DOXYGEN], [ 37 | AC_ARG_WITH([doxygen], 38 | AS_HELP_STRING([--with-doxygen], 39 | [build documentation for internal APIs]), 40 | [], 41 | [with_doxygen=auto]) 42 | 43 | if test "${with_doxygen}" = yes; then 44 | AC_PATH_PROG([DOXYGEN], [doxygen], []) 45 | if test -z "${DOXYGEN}"; then 46 | AC_MSG_ERROR([Doxygen explicitly requested but not found]) 47 | fi 48 | elif test "${with_doxygen}" = auto; then 49 | AC_PATH_PROG([DOXYGEN], [doxygen], []) 50 | elif test "${with_doxygen}" = no; then 51 | DOXYGEN= 52 | else 53 | AC_MSG_CHECKING([for doxygen]) 54 | DOXYGEN="${with_doxygen}" 55 | AC_MSG_RESULT([${DOXYGEN}]) 56 | if test ! -x "${DOXYGEN}"; then 57 | AC_MSG_ERROR([Doxygen binary ${DOXYGEN} is not executable]) 58 | fi 59 | fi 60 | AM_CONDITIONAL([WITH_DOXYGEN], [test -n "${DOXYGEN}"]) 61 | AC_SUBST([DOXYGEN]) 62 | ]) 63 | -------------------------------------------------------------------------------- /m4/lua.m4: -------------------------------------------------------------------------------- 1 | dnl Copyright 2011 Google Inc. 2 | dnl All rights reserved. 3 | dnl 4 | dnl Redistribution and use in source and binary forms, with or without 5 | dnl modification, are permitted provided that the following conditions are 6 | dnl met: 7 | dnl 8 | dnl * Redistributions of source code must retain the above copyright 9 | dnl notice, this list of conditions and the following disclaimer. 10 | dnl * Redistributions in binary form must reproduce the above copyright 11 | dnl notice, this list of conditions and the following disclaimer in the 12 | dnl documentation and/or other materials provided with the distribution. 13 | dnl * Neither the name of Google Inc. nor the names of its contributors 14 | dnl may be used to endorse or promote products derived from this software 15 | dnl without specific prior written permission. 16 | dnl 17 | dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | dnl 30 | dnl KYUA_LUA 31 | dnl 32 | dnl Helper macro to detect Lua in a variety of systems. 33 | dnl 34 | AC_DEFUN([KYUA_LUA], [ 35 | lua_found=no 36 | for lua_release in ${LUA_VERSION:-5.4 5.3}; do 37 | PKG_CHECK_MODULES([LUA], [lua-${lua_release} >= ${lua_release}], 38 | [lua_found="lua-${lua_release}"],[ 39 | PKG_CHECK_MODULES([LUA], [lua${lua_release} >= ${lua_release}], 40 | [lua_found="lua${lua_release}"],[ 41 | PKG_CHECK_MODULES([LUA], [lua >= ${lua_release}], 42 | [lua_found="lua"],[]) 43 | ])]) 44 | if test "${lua_found}" != no; then 45 | break 46 | fi 47 | done 48 | 49 | AS_IF([test "${lua_found}" = no],[],[ 50 | AC_SUBST([LUA_CFLAGS], [$(${PKG_CONFIG} --cflags ${lua_found})]) 51 | AC_SUBST([LUA_LIBS], [$(${PKG_CONFIG} --libs ${lua_found})]) 52 | ]) 53 | 54 | AS_IF([test "${lua_found}" = no], 55 | [AC_MSG_ERROR([lua (5.3 or newer) is required])], 56 | [ 57 | AC_MSG_NOTICE([using LUA_CFLAGS = ${LUA_CFLAGS}]) 58 | AC_MSG_NOTICE([using LUA_LIBS = ${LUA_LIBS}]) 59 | ]) 60 | ]) 61 | -------------------------------------------------------------------------------- /operations.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #include 30 | 31 | #include 32 | 33 | #include "exceptions.hpp" 34 | #include "operations.hpp" 35 | #include "stack_cleaner.hpp" 36 | #include "state.hpp" 37 | 38 | 39 | /// Creates a module: i.e. a table with a set of methods in it. 40 | /// 41 | /// \param s The Lua state. 42 | /// \param name The name of the module to create. 43 | /// \param members The list of member functions to add to the module. 44 | void 45 | lutok::create_module(state& s, const std::string& name, 46 | const std::map< std::string, cxx_function >& members) 47 | { 48 | stack_cleaner cleaner(s); 49 | s.new_table(); 50 | for (std::map< std::string, cxx_function >::const_iterator 51 | iter = members.begin(); iter != members.end(); iter++) { 52 | s.push_string((*iter).first); 53 | s.push_cxx_function((*iter).second); 54 | s.set_table(-3); 55 | } 56 | s.set_global(name); 57 | } 58 | 59 | 60 | /// Loads and processes a Lua file. 61 | /// 62 | /// This is a replacement for luaL_dofile but with proper error reporting 63 | /// and stack control. 64 | /// 65 | /// \param s The Lua state. 66 | /// \param file The file to load. 67 | /// \param nargs The number of arguments on the stack to pass to the file. 68 | /// \param nresults The number of results to expect; -1 for any. 69 | /// \param errfunc If not 0, index of a function in the stack to act as an 70 | /// error handler. 71 | /// 72 | /// \return The number of results left on the stack. 73 | /// 74 | /// \throw error If there is a problem processing the file. 75 | unsigned int 76 | lutok::do_file(state& s, const std::string& file, const int nargs, 77 | const int nresults, const int errfunc) 78 | { 79 | assert(nresults >= -1); 80 | const int height = s.get_top() - nargs; 81 | 82 | try { 83 | s.load_file(file); 84 | if (nargs > 0) 85 | s.insert(-nargs - 1); 86 | s.pcall(nargs, nresults == -1 ? LUA_MULTRET : nresults, 87 | errfunc == 0 ? 0 : errfunc - 1); 88 | } catch (const lutok::api_error& e) { 89 | throw lutok::error("Failed to load Lua file '" + file + "': " + 90 | e.what()); 91 | } 92 | 93 | const int actual_results = s.get_top() - height; 94 | assert(nresults == -1 || actual_results == nresults); 95 | assert(actual_results >= 0); 96 | return static_cast< unsigned int >(actual_results); 97 | } 98 | 99 | 100 | /// Processes a Lua script. 101 | /// 102 | /// This is a replacement for luaL_dostring but with proper error reporting 103 | /// and stack control. 104 | /// 105 | /// \param s The Lua state. 106 | /// \param str The string to process. 107 | /// \param nargs The number of arguments on the stack to pass to the chunk. 108 | /// \param nresults The number of results to expect; -1 for any. 109 | /// \param errfunc If not 0, index of a function in the stack to act as an 110 | /// error handler. 111 | /// 112 | /// \return The number of results left on the stack. 113 | /// 114 | /// \throw error If there is a problem processing the string. 115 | unsigned int 116 | lutok::do_string(state& s, const std::string& str, const int nargs, 117 | const int nresults, const int errfunc) 118 | { 119 | assert(nresults >= -1); 120 | const int height = s.get_top() - nargs; 121 | 122 | try { 123 | s.load_string(str); 124 | if (nargs > 0) 125 | s.insert(-nargs - 1); 126 | s.pcall(nargs, nresults == -1 ? LUA_MULTRET : nresults, 127 | errfunc == 0 ? 0 : errfunc - 1); 128 | } catch (const lutok::api_error& e) { 129 | throw lutok::error("Failed to process Lua string '" + str + "': " + 130 | e.what()); 131 | } 132 | 133 | const int actual_results = s.get_top() - height; 134 | assert(nresults == -1 || actual_results == nresults); 135 | assert(actual_results >= 0); 136 | return static_cast< unsigned int >(actual_results); 137 | } 138 | 139 | 140 | /// Convenience function to evaluate a Lua expression. 141 | /// 142 | /// \param s The Lua state. 143 | /// \param expression The textual expression to evaluate. 144 | /// \param nresults The number of results to leave on the stack. Must be 145 | /// positive. 146 | /// 147 | /// \throw api_error If there is a problem evaluating the expression. 148 | void 149 | lutok::eval(state& s, const std::string& expression, const int nresults) 150 | { 151 | assert(nresults > 0); 152 | do_string(s, "return " + expression, 0, nresults, 0); 153 | } 154 | -------------------------------------------------------------------------------- /operations.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file operations.hpp 30 | /// Extra generic functions to interact with Lua. 31 | 32 | #if !defined(LUTOK_OPERATIONS_HPP) 33 | #define LUTOK_OPERATIONS_HPP 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | 41 | namespace lutok { 42 | 43 | 44 | void create_module(state&, const std::string&, 45 | const std::map< std::string, cxx_function >&); 46 | unsigned int do_file(state&, const std::string&, const int, const int, 47 | const int); 48 | unsigned int do_string(state&, const std::string&, const int, const int, 49 | const int); 50 | void eval(state&, const std::string&, const int); 51 | 52 | 53 | } // namespace lutok 54 | 55 | #endif // !defined(LUTOK_OPERATIONS_HPP) 56 | -------------------------------------------------------------------------------- /operations_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #include "operations.hpp" 30 | 31 | #include 32 | 33 | #include 34 | 35 | #include "exceptions.hpp" 36 | #include "state.ipp" 37 | #include "test_utils.hpp" 38 | 39 | 40 | namespace { 41 | 42 | 43 | /// Addition function for injection into Lua. 44 | /// 45 | /// \pre stack(-2) The first summand. 46 | /// \pre stack(-1) The second summand. 47 | /// \post stack(-1) The result of the sum. 48 | /// 49 | /// \param state The Lua state. 50 | /// 51 | /// \return The number of results (1). 52 | static int 53 | hook_add(lutok::state& state) 54 | { 55 | state.push_integer(state.to_integer(-1) + state.to_integer(-2)); 56 | return 1; 57 | } 58 | 59 | 60 | /// Multiplication function for injection into Lua. 61 | /// 62 | /// \pre stack(-2) The first factor. 63 | /// \pre stack(-1) The second factor. 64 | /// \post stack(-1) The product. 65 | /// 66 | /// \param state The Lua state. 67 | /// 68 | /// \return The number of results (1). 69 | static int 70 | hook_multiply(lutok::state& state) 71 | { 72 | state.push_integer(state.to_integer(-1) * state.to_integer(-2)); 73 | return 1; 74 | } 75 | 76 | 77 | } // anonymous namespace 78 | 79 | 80 | ATF_TEST_CASE_WITHOUT_HEAD(create_module__empty); 81 | ATF_TEST_CASE_BODY(create_module__empty) 82 | { 83 | lutok::state state; 84 | std::map< std::string, lutok::cxx_function > members; 85 | lutok::create_module(state, "my_math", members); 86 | 87 | state.open_base(); 88 | lutok::do_string(state, "return next(my_math) == nil", 0, 1, 0); 89 | ATF_REQUIRE(state.to_boolean(-1)); 90 | state.pop(1); 91 | } 92 | 93 | 94 | ATF_TEST_CASE_WITHOUT_HEAD(create_module__one); 95 | ATF_TEST_CASE_BODY(create_module__one) 96 | { 97 | lutok::state state; 98 | std::map< std::string, lutok::cxx_function > members; 99 | members["add"] = hook_add; 100 | lutok::create_module(state, "my_math", members); 101 | 102 | lutok::do_string(state, "return my_math.add(10, 20)", 0, 1, 0); 103 | ATF_REQUIRE_EQ(30, state.to_integer(-1)); 104 | state.pop(1); 105 | } 106 | 107 | 108 | ATF_TEST_CASE_WITHOUT_HEAD(create_module__many); 109 | ATF_TEST_CASE_BODY(create_module__many) 110 | { 111 | lutok::state state; 112 | std::map< std::string, lutok::cxx_function > members; 113 | members["add"] = hook_add; 114 | members["multiply"] = hook_multiply; 115 | members["add2"] = hook_add; 116 | lutok::create_module(state, "my_math", members); 117 | 118 | lutok::do_string(state, "return my_math.add(10, 20)", 0, 1, 0); 119 | ATF_REQUIRE_EQ(30, state.to_integer(-1)); 120 | lutok::do_string(state, "return my_math.multiply(10, 20)", 0, 1, 0); 121 | ATF_REQUIRE_EQ(200, state.to_integer(-1)); 122 | lutok::do_string(state, "return my_math.add2(20, 30)", 0, 1, 0); 123 | ATF_REQUIRE_EQ(50, state.to_integer(-1)); 124 | state.pop(3); 125 | } 126 | 127 | 128 | ATF_TEST_CASE_WITHOUT_HEAD(do_file__some_args); 129 | ATF_TEST_CASE_BODY(do_file__some_args) 130 | { 131 | std::ofstream output("test.lua"); 132 | output << "local a1, a2 = ...\nreturn a1 * 2, a2 * 2\n"; 133 | output.close(); 134 | 135 | lutok::state state; 136 | state.push_integer(456); 137 | state.push_integer(3); 138 | state.push_integer(5); 139 | state.push_integer(123); 140 | ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 3, -1, 0)); 141 | ATF_REQUIRE_EQ(3, state.get_top()); 142 | ATF_REQUIRE_EQ(456, state.to_integer(-3)); 143 | ATF_REQUIRE_EQ(6, state.to_integer(-2)); 144 | ATF_REQUIRE_EQ(10, state.to_integer(-1)); 145 | state.pop(3); 146 | } 147 | 148 | 149 | ATF_TEST_CASE_WITHOUT_HEAD(do_file__any_results); 150 | ATF_TEST_CASE_BODY(do_file__any_results) 151 | { 152 | std::ofstream output("test.lua"); 153 | output << "return 10, 20, 30\n"; 154 | output.close(); 155 | 156 | lutok::state state; 157 | ATF_REQUIRE_EQ(3, lutok::do_file(state, "test.lua", 0, -1, 0)); 158 | ATF_REQUIRE_EQ(3, state.get_top()); 159 | ATF_REQUIRE_EQ(10, state.to_integer(-3)); 160 | ATF_REQUIRE_EQ(20, state.to_integer(-2)); 161 | ATF_REQUIRE_EQ(30, state.to_integer(-1)); 162 | state.pop(3); 163 | } 164 | 165 | 166 | ATF_TEST_CASE_WITHOUT_HEAD(do_file__no_results); 167 | ATF_TEST_CASE_BODY(do_file__no_results) 168 | { 169 | std::ofstream output("test.lua"); 170 | output << "return 10, 20, 30\n"; 171 | output.close(); 172 | 173 | lutok::state state; 174 | ATF_REQUIRE_EQ(0, lutok::do_file(state, "test.lua", 0, 0, 0)); 175 | ATF_REQUIRE_EQ(0, state.get_top()); 176 | } 177 | 178 | 179 | ATF_TEST_CASE_WITHOUT_HEAD(do_file__many_results); 180 | ATF_TEST_CASE_BODY(do_file__many_results) 181 | { 182 | std::ofstream output("test.lua"); 183 | output << "return 10, 20, 30\n"; 184 | output.close(); 185 | 186 | lutok::state state; 187 | ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 0, 2, 0)); 188 | ATF_REQUIRE_EQ(2, state.get_top()); 189 | ATF_REQUIRE_EQ(10, state.to_integer(-2)); 190 | ATF_REQUIRE_EQ(20, state.to_integer(-1)); 191 | state.pop(2); 192 | } 193 | 194 | 195 | ATF_TEST_CASE_WITHOUT_HEAD(do_file__not_found); 196 | ATF_TEST_CASE_BODY(do_file__not_found) 197 | { 198 | lutok::state state; 199 | stack_balance_checker checker(state); 200 | ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua", 201 | lutok::do_file(state, "missing.lua", 0, 0, 0)); 202 | } 203 | 204 | 205 | ATF_TEST_CASE_WITHOUT_HEAD(do_file__error); 206 | ATF_TEST_CASE_BODY(do_file__error) 207 | { 208 | std::ofstream output("test.lua"); 209 | output << "a b c\n"; 210 | output.close(); 211 | 212 | lutok::state state; 213 | stack_balance_checker checker(state); 214 | ATF_REQUIRE_THROW_RE(lutok::error, "Failed to load Lua file 'test.lua'", 215 | lutok::do_file(state, "test.lua", 0, 0, 0)); 216 | } 217 | 218 | 219 | ATF_TEST_CASE_WITHOUT_HEAD(do_file__error_with_errfunc); 220 | ATF_TEST_CASE_BODY(do_file__error_with_errfunc) 221 | { 222 | std::ofstream output("test.lua"); 223 | output << "unknown_function()\n"; 224 | output.close(); 225 | 226 | lutok::state state; 227 | lutok::eval(state, "function(message) return 'This is an error!' end", 1); 228 | { 229 | stack_balance_checker checker(state); 230 | ATF_REQUIRE_THROW_RE(lutok::error, "This is an error!", 231 | lutok::do_file(state, "test.lua", 0, 0, -2)); 232 | } 233 | state.pop(1); 234 | } 235 | 236 | 237 | ATF_TEST_CASE_WITHOUT_HEAD(do_string__some_args); 238 | ATF_TEST_CASE_BODY(do_string__some_args) 239 | { 240 | lutok::state state; 241 | state.push_integer(456); 242 | state.push_integer(3); 243 | state.push_integer(5); 244 | state.push_integer(123); 245 | ATF_REQUIRE_EQ(2, lutok::do_string( 246 | state, "local a1, a2 = ...\nreturn a1 * 2, a2 * 2\n", 3, -1, 0)); 247 | ATF_REQUIRE_EQ(3, state.get_top()); 248 | ATF_REQUIRE_EQ(456, state.to_integer(-3)); 249 | ATF_REQUIRE_EQ(6, state.to_integer(-2)); 250 | ATF_REQUIRE_EQ(10, state.to_integer(-1)); 251 | state.pop(3); 252 | } 253 | 254 | 255 | ATF_TEST_CASE_WITHOUT_HEAD(do_string__any_results); 256 | ATF_TEST_CASE_BODY(do_string__any_results) 257 | { 258 | lutok::state state; 259 | ATF_REQUIRE_EQ(3, lutok::do_string(state, "return 10, 20, 30", 0, -1, 0)); 260 | ATF_REQUIRE_EQ(3, state.get_top()); 261 | ATF_REQUIRE_EQ(10, state.to_integer(-3)); 262 | ATF_REQUIRE_EQ(20, state.to_integer(-2)); 263 | ATF_REQUIRE_EQ(30, state.to_integer(-1)); 264 | state.pop(3); 265 | } 266 | 267 | 268 | ATF_TEST_CASE_WITHOUT_HEAD(do_string__no_results); 269 | ATF_TEST_CASE_BODY(do_string__no_results) 270 | { 271 | lutok::state state; 272 | ATF_REQUIRE_EQ(0, lutok::do_string(state, "return 10, 20, 30", 0, 0, 0)); 273 | ATF_REQUIRE_EQ(0, state.get_top()); 274 | } 275 | 276 | 277 | ATF_TEST_CASE_WITHOUT_HEAD(do_string__many_results); 278 | ATF_TEST_CASE_BODY(do_string__many_results) 279 | { 280 | lutok::state state; 281 | ATF_REQUIRE_EQ(2, lutok::do_string(state, "return 10, 20, 30", 0, 2, 0)); 282 | ATF_REQUIRE_EQ(2, state.get_top()); 283 | ATF_REQUIRE_EQ(10, state.to_integer(-2)); 284 | ATF_REQUIRE_EQ(20, state.to_integer(-1)); 285 | state.pop(2); 286 | } 287 | 288 | 289 | ATF_TEST_CASE_WITHOUT_HEAD(do_string__error); 290 | ATF_TEST_CASE_BODY(do_string__error) 291 | { 292 | lutok::state state; 293 | stack_balance_checker checker(state); 294 | ATF_REQUIRE_THROW_RE(lutok::error, "Failed to process Lua string 'a b c'", 295 | lutok::do_string(state, "a b c", 0, 0, 0)); 296 | } 297 | 298 | 299 | ATF_TEST_CASE_WITHOUT_HEAD(do_string__error_with_errfunc); 300 | ATF_TEST_CASE_BODY(do_string__error_with_errfunc) 301 | { 302 | lutok::state state; 303 | lutok::eval(state, "function(message) return 'This is an error!' end", 1); 304 | { 305 | stack_balance_checker checker(state); 306 | ATF_REQUIRE_THROW_RE(lutok::error, "This is an error!", 307 | lutok::do_string(state, "unknown_function()", 308 | 0, 0, -2)); 309 | } 310 | state.pop(1); 311 | } 312 | 313 | 314 | ATF_TEST_CASE_WITHOUT_HEAD(eval__one_result); 315 | ATF_TEST_CASE_BODY(eval__one_result) 316 | { 317 | lutok::state state; 318 | stack_balance_checker checker(state); 319 | lutok::eval(state, "3 + 10", 1); 320 | ATF_REQUIRE_EQ(13, state.to_integer(-1)); 321 | state.pop(1); 322 | } 323 | 324 | 325 | ATF_TEST_CASE_WITHOUT_HEAD(eval__many_results); 326 | ATF_TEST_CASE_BODY(eval__many_results) 327 | { 328 | lutok::state state; 329 | stack_balance_checker checker(state); 330 | lutok::eval(state, "5, 8, 10", 3); 331 | ATF_REQUIRE_EQ(5, state.to_integer(-3)); 332 | ATF_REQUIRE_EQ(8, state.to_integer(-2)); 333 | ATF_REQUIRE_EQ(10, state.to_integer(-1)); 334 | state.pop(3); 335 | } 336 | 337 | 338 | ATF_TEST_CASE_WITHOUT_HEAD(eval__error); 339 | ATF_TEST_CASE_BODY(eval__error) 340 | { 341 | lutok::state state; 342 | stack_balance_checker checker(state); 343 | ATF_REQUIRE_THROW(lutok::error, 344 | lutok::eval(state, "non_existent.method()", 1)); 345 | } 346 | 347 | 348 | ATF_INIT_TEST_CASES(tcs) 349 | { 350 | ATF_ADD_TEST_CASE(tcs, create_module__empty); 351 | ATF_ADD_TEST_CASE(tcs, create_module__one); 352 | ATF_ADD_TEST_CASE(tcs, create_module__many); 353 | 354 | ATF_ADD_TEST_CASE(tcs, do_file__some_args); 355 | ATF_ADD_TEST_CASE(tcs, do_file__any_results); 356 | ATF_ADD_TEST_CASE(tcs, do_file__no_results); 357 | ATF_ADD_TEST_CASE(tcs, do_file__many_results); 358 | ATF_ADD_TEST_CASE(tcs, do_file__not_found); 359 | ATF_ADD_TEST_CASE(tcs, do_file__error); 360 | ATF_ADD_TEST_CASE(tcs, do_file__error_with_errfunc); 361 | 362 | ATF_ADD_TEST_CASE(tcs, do_string__some_args); 363 | ATF_ADD_TEST_CASE(tcs, do_string__any_results); 364 | ATF_ADD_TEST_CASE(tcs, do_string__no_results); 365 | ATF_ADD_TEST_CASE(tcs, do_string__many_results); 366 | ATF_ADD_TEST_CASE(tcs, do_string__error); 367 | ATF_ADD_TEST_CASE(tcs, do_string__error_with_errfunc); 368 | 369 | ATF_ADD_TEST_CASE(tcs, eval__one_result); 370 | ATF_ADD_TEST_CASE(tcs, eval__many_results); 371 | ATF_ADD_TEST_CASE(tcs, eval__error); 372 | } 373 | -------------------------------------------------------------------------------- /stack_cleaner.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #include 30 | #include 31 | 32 | #include "stack_cleaner.hpp" 33 | #include "state.ipp" 34 | 35 | 36 | /// Internal implementation for lutok::stack_cleaner. 37 | struct lutok::stack_cleaner::impl { 38 | /// Reference to the Lua state this stack_cleaner refers to. 39 | state& state_ref; 40 | 41 | /// The depth of the Lua stack to be restored. 42 | unsigned int original_depth; 43 | 44 | /// Constructor. 45 | /// 46 | /// \param state_ref_ Reference to the Lua state. 47 | /// \param original_depth_ The depth of the Lua stack. 48 | impl(state& state_ref_, const unsigned int original_depth_) : 49 | state_ref(state_ref_), 50 | original_depth(original_depth_) 51 | { 52 | } 53 | }; 54 | 55 | 56 | /// Creates a new stack cleaner. 57 | /// 58 | /// This gathers the current height of the stack so that extra elements can be 59 | /// popped during destruction. 60 | /// 61 | /// \param state_ The Lua state. 62 | lutok::stack_cleaner::stack_cleaner(state& state_) : 63 | _pimpl(new impl(state_, state_.get_top())) 64 | { 65 | } 66 | 67 | 68 | /// Pops any values from the stack not known at construction time. 69 | /// 70 | /// \pre The current height of the stack must be equal or greater to the height 71 | /// of the stack when this object was instantiated. 72 | lutok::stack_cleaner::~stack_cleaner(void) 73 | { 74 | const unsigned int current_depth = _pimpl->state_ref.get_top(); 75 | assert(current_depth >= _pimpl->original_depth); 76 | const unsigned int diff = current_depth - _pimpl->original_depth; 77 | if (diff > 0) 78 | _pimpl->state_ref.pop(diff); 79 | } 80 | 81 | 82 | /// Forgets about any elements currently in the stack. 83 | /// 84 | /// This allows a function to return values on the stack because all the 85 | /// elements that are currently in the stack will not be touched during 86 | /// destruction when the function is called. 87 | void 88 | lutok::stack_cleaner::forget(void) 89 | { 90 | _pimpl->original_depth = _pimpl->state_ref.get_top(); 91 | } 92 | -------------------------------------------------------------------------------- /stack_cleaner.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file stack_cleaner.hpp 30 | /// Provides the stack_cleaner class. 31 | 32 | #if !defined(LUTOK_STACK_CLEANER_HPP) 33 | #define LUTOK_STACK_CLEANER_HPP 34 | 35 | #include 36 | 37 | #include 38 | 39 | namespace lutok { 40 | 41 | 42 | /// A RAII model for values on the Lua stack. 43 | /// 44 | /// At creation time, the object records the current depth of the Lua stack and, 45 | /// during destruction, restores the recorded depth by popping as many stack 46 | /// entries as required. As a corollary, the stack can only grow during the 47 | /// lifetime of a stack_cleaner object (or shrink, but cannot become shorter 48 | /// than the depth recorded at creation time). 49 | /// 50 | /// Use this class as follows: 51 | /// 52 | /// state s; 53 | /// { 54 | /// stack_cleaner cleaner1(s); 55 | /// s.push_integer(3); 56 | /// s.push_integer(5); 57 | /// ... do stuff here ... 58 | /// for (...) { 59 | /// stack_cleaner cleaner2(s); 60 | /// s.load_string("..."); 61 | /// s.pcall(0, 1, 0); 62 | /// ... do stuff here ... 63 | /// } 64 | /// // cleaner2 destroyed; the result of pcall is gone. 65 | /// } 66 | /// // cleaner1 destroyed; the integers 3 and 5 are gone. 67 | /// 68 | /// You must give a name to the instantiated objects even if they cannot be 69 | /// accessed later. Otherwise, the instance will be destroyed right away and 70 | /// will not have the desired effect. 71 | class stack_cleaner { 72 | struct impl; 73 | 74 | /// Pointer to the shared internal implementation. 75 | std::unique_ptr< impl > _pimpl; 76 | 77 | /// Disallow copies. 78 | stack_cleaner(const stack_cleaner&) = delete; 79 | 80 | /// Disallow assignment. 81 | stack_cleaner& operator=(const stack_cleaner&) = delete; 82 | 83 | public: 84 | stack_cleaner(state&); 85 | ~stack_cleaner(void); 86 | 87 | void forget(void); 88 | }; 89 | 90 | 91 | } // namespace lutok 92 | 93 | #endif // !defined(LUTOK_STACK_CLEANER_HPP) 94 | -------------------------------------------------------------------------------- /stack_cleaner_test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #include "stack_cleaner.hpp" 30 | 31 | #include 32 | 33 | 34 | ATF_TEST_CASE_WITHOUT_HEAD(empty); 35 | ATF_TEST_CASE_BODY(empty) 36 | { 37 | lutok::state state; 38 | { 39 | lutok::stack_cleaner cleaner(state); 40 | ATF_REQUIRE_EQ(0, state.get_top()); 41 | } 42 | ATF_REQUIRE_EQ(0, state.get_top()); 43 | } 44 | 45 | 46 | ATF_TEST_CASE_WITHOUT_HEAD(some); 47 | ATF_TEST_CASE_BODY(some) 48 | { 49 | lutok::state state; 50 | { 51 | lutok::stack_cleaner cleaner(state); 52 | state.push_integer(15); 53 | ATF_REQUIRE_EQ(1, state.get_top()); 54 | state.push_integer(30); 55 | ATF_REQUIRE_EQ(2, state.get_top()); 56 | } 57 | ATF_REQUIRE_EQ(0, state.get_top()); 58 | } 59 | 60 | 61 | ATF_TEST_CASE_WITHOUT_HEAD(nested); 62 | ATF_TEST_CASE_BODY(nested) 63 | { 64 | lutok::state state; 65 | { 66 | lutok::stack_cleaner cleaner1(state); 67 | state.push_integer(10); 68 | ATF_REQUIRE_EQ(1, state.get_top()); 69 | ATF_REQUIRE_EQ(10, state.to_integer(-1)); 70 | { 71 | lutok::stack_cleaner cleaner2(state); 72 | state.push_integer(20); 73 | ATF_REQUIRE_EQ(2, state.get_top()); 74 | ATF_REQUIRE_EQ(20, state.to_integer(-1)); 75 | ATF_REQUIRE_EQ(10, state.to_integer(-2)); 76 | } 77 | ATF_REQUIRE_EQ(1, state.get_top()); 78 | ATF_REQUIRE_EQ(10, state.to_integer(-1)); 79 | } 80 | ATF_REQUIRE_EQ(0, state.get_top()); 81 | } 82 | 83 | 84 | ATF_TEST_CASE_WITHOUT_HEAD(forget); 85 | ATF_TEST_CASE_BODY(forget) 86 | { 87 | lutok::state state; 88 | { 89 | lutok::stack_cleaner cleaner(state); 90 | state.push_integer(15); 91 | state.push_integer(30); 92 | cleaner.forget(); 93 | state.push_integer(60); 94 | ATF_REQUIRE_EQ(3, state.get_top()); 95 | } 96 | ATF_REQUIRE_EQ(2, state.get_top()); 97 | ATF_REQUIRE_EQ(30, state.to_integer(-1)); 98 | state.pop(2); 99 | } 100 | 101 | 102 | ATF_INIT_TEST_CASES(tcs) 103 | { 104 | ATF_ADD_TEST_CASE(tcs, empty); 105 | ATF_ADD_TEST_CASE(tcs, some); 106 | ATF_ADD_TEST_CASE(tcs, nested); 107 | ATF_ADD_TEST_CASE(tcs, forget); 108 | } 109 | -------------------------------------------------------------------------------- /state.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | extern "C" { 30 | #include 31 | } 32 | 33 | #include 34 | #include 35 | 36 | #include "c_gate.hpp" 37 | #include "exceptions.hpp" 38 | #include "state.ipp" 39 | 40 | 41 | namespace { 42 | 43 | 44 | /// Wrapper around lua_getglobal to run in a protected environment. 45 | /// 46 | /// \pre stack(-1) is the name of the global to get. 47 | /// \post stack(-1) is the value of the global. 48 | /// 49 | /// \param state The Lua C API state. 50 | /// 51 | /// \return The number of return values pushed onto the stack. 52 | static int 53 | protected_getglobal(lua_State* state) 54 | { 55 | lua_getglobal(state, lua_tostring(state, -1)); 56 | return 1; 57 | } 58 | 59 | 60 | /// Wrapper around lua_gettable to run in a protected environment. 61 | /// 62 | /// \pre stack(-2) is the table to get the element from. 63 | /// \pre stack(-1) is the table index. 64 | /// \post stack(-1) is the value of stack(-2)[stack(-1)]. 65 | /// 66 | /// \param state The Lua C API state. 67 | /// 68 | /// \return The number of return values pushed onto the stack. 69 | static int 70 | protected_gettable(lua_State* state) 71 | { 72 | lua_gettable(state, -2); 73 | return 1; 74 | } 75 | 76 | 77 | /// Wrapper around lua_next to run in a protected environment. 78 | /// 79 | /// \pre stack(-2) is the table to get the next element from. 80 | /// \pre stack(-1) is the last processed key. 81 | /// \post stack(-1) is the value of next(stack(-2), stack(-1)). 82 | /// 83 | /// \param state The Lua C API state. 84 | /// 85 | /// \return The number of return values pushed onto the stack. 86 | static int 87 | protected_next(lua_State* state) 88 | { 89 | const int more = lua_next(state, -2) != 0; 90 | lua_pushboolean(state, more); 91 | return more ? 3 : 1; 92 | } 93 | 94 | 95 | /// Wrapper around lua_setglobal to run in a protected environment. 96 | /// 97 | /// \pre stack(-2) is the name of the global to set. 98 | /// \pre stack(-1) is the value to set the global to. 99 | /// 100 | /// \param state The Lua C API state. 101 | /// 102 | /// \return The number of return values pushed onto the stack. 103 | static int 104 | protected_setglobal(lua_State* state) 105 | { 106 | lua_setglobal(state, lua_tostring(state, -2)); 107 | return 0; 108 | } 109 | 110 | 111 | /// Wrapper around lua_settable to run in a protected environment. 112 | /// 113 | /// \pre stack(-3) is the table to set the element into. 114 | /// \pre stack(-2) is the table index. 115 | /// \pre stack(-1) is the value to set. 116 | /// 117 | /// \param state The Lua C API state. 118 | /// 119 | /// \return The number of return values pushed onto the stack. 120 | static int 121 | protected_settable(lua_State* state) 122 | { 123 | lua_settable(state, -3); 124 | return 0; 125 | } 126 | 127 | 128 | /// Calls a C++ Lua function from a C calling environment. 129 | /// 130 | /// Any errors reported by the C++ function are caught and reported to the 131 | /// caller as Lua errors. 132 | /// 133 | /// \param function The C++ function to call. 134 | /// \param raw_state The raw Lua state. 135 | /// 136 | /// \return The number of return values pushed onto the Lua stack by the 137 | /// function. 138 | static int 139 | call_cxx_function_from_c(lutok::cxx_function function, 140 | lua_State* raw_state) throw() 141 | { 142 | char error_buf[1024]; 143 | 144 | try { 145 | lutok::state state = lutok::state_c_gate::connect(raw_state); 146 | return function(state); 147 | } catch (const std::exception& e) { 148 | std::strncpy(error_buf, e.what(), sizeof(error_buf) - 1); 149 | } catch (...) { 150 | std::strncpy(error_buf, "Unhandled exception in Lua C++ hook", 151 | sizeof(error_buf) - 1); 152 | } 153 | error_buf[sizeof(error_buf) - 1] = '\0'; 154 | // We raise the Lua error from outside the try/catch context and we use 155 | // a stack-based buffer to hold the message to ensure that we do not leak 156 | // any C++ objects (and, as a likely result, memory) when Lua performs its 157 | // longjmp. 158 | return luaL_error(raw_state, "%s", error_buf); 159 | } 160 | 161 | 162 | /// Lua glue to call a C++ closure. 163 | /// 164 | /// This Lua binding is actually a closure that we have constructed from the 165 | /// state.push_cxx_closure() method. The closure contains the same upvalues 166 | /// provided by the user plus an extra upvalue that contains the address of the 167 | /// C++ function we have to call. All we do here is safely delegate the 168 | /// execution to the wrapped C++ closure. 169 | /// 170 | /// \param raw_state The Lua C API state. 171 | /// 172 | /// \return The number of return values of the called closure. 173 | static int 174 | cxx_closure_trampoline(lua_State* raw_state) 175 | { 176 | lutok::state state = lutok::state_c_gate::connect(raw_state); 177 | 178 | int nupvalues; 179 | { 180 | lua_Debug debug; 181 | lua_getstack(raw_state, 0, &debug); 182 | lua_getinfo(raw_state, "u", &debug); 183 | nupvalues = debug.nups; 184 | } 185 | 186 | lutok::cxx_function* function = state.to_userdata< lutok::cxx_function >( 187 | state.upvalue_index(nupvalues)); 188 | return call_cxx_function_from_c(*function, raw_state); 189 | } 190 | 191 | 192 | /// Lua glue to call a C++ function. 193 | /// 194 | /// This Lua binding is actually a closure that we have constructed from the 195 | /// state.push_cxx_function() method. The closure has a single upvalue that 196 | /// contains the address of the C++ function we have to call. All we do here is 197 | /// safely delegate the execution to the wrapped C++ function. 198 | /// 199 | /// \param raw_state The Lua C API state. 200 | /// 201 | /// \return The number of return values of the called function. 202 | static int 203 | cxx_function_trampoline(lua_State* raw_state) 204 | { 205 | lutok::state state = lutok::state_c_gate::connect(raw_state); 206 | lutok::cxx_function* function = state.to_userdata< lutok::cxx_function >( 207 | state.upvalue_index(1)); 208 | return call_cxx_function_from_c(*function, raw_state); 209 | } 210 | 211 | 212 | } // anonymous namespace 213 | 214 | 215 | const int lutok::registry_index = LUA_REGISTRYINDEX; 216 | 217 | 218 | /// Internal implementation for lutok::state. 219 | struct lutok::state::impl { 220 | /// The Lua internal state. 221 | lua_State* lua_state; 222 | 223 | /// Whether we own the state or not (to decide if we close it). 224 | bool owned; 225 | 226 | /// Constructor. 227 | /// 228 | /// \param lua_ The Lua internal state. 229 | /// \param owned_ Whether we own the state or not. 230 | impl(lua_State* lua_, bool owned_) : 231 | lua_state(lua_), 232 | owned(owned_) 233 | { 234 | } 235 | }; 236 | 237 | 238 | /// Initializes the Lua state. 239 | /// 240 | /// You must share the same state object alongside the lifetime of your Lua 241 | /// session. As soon as the object is destroyed, the session is terminated. 242 | lutok::state::state(void) 243 | { 244 | lua_State* lua = luaL_newstate(); 245 | if (lua == NULL) 246 | throw lutok::error("lua open failed"); 247 | _pimpl.reset(new impl(lua, true)); 248 | } 249 | 250 | 251 | /// Initializes the Lua state from an existing raw state. 252 | /// 253 | /// Instances constructed using this method do NOT own the raw state. This 254 | /// means that, on exit, the state will not be destroyed. 255 | /// 256 | /// \param raw_state_ The raw Lua state to wrap. 257 | lutok::state::state(void* raw_state_) : 258 | _pimpl(new impl(reinterpret_cast< lua_State* >(raw_state_), false)) 259 | { 260 | } 261 | 262 | 263 | /// Destructor for the Lua state. 264 | /// 265 | /// Closes the session unless it has already been closed by calling the 266 | /// close() method. It is recommended to explicitly close the session in the 267 | /// code. 268 | lutok::state::~state(void) 269 | { 270 | if (_pimpl->owned && _pimpl->lua_state != NULL) 271 | close(); 272 | } 273 | 274 | 275 | /// Terminates this Lua session. 276 | /// 277 | /// It is recommended to call this instead of relying on the destructor to do 278 | /// the cleanup, but it is not a requirement to use close(). 279 | /// 280 | /// \pre close() has not yet been called. 281 | /// \pre The Lua stack is empty. This is not truly necessary but ensures that 282 | /// our code is consistent and clears the stack explicitly. 283 | void 284 | lutok::state::close(void) 285 | { 286 | assert(_pimpl->lua_state != NULL); 287 | assert(lua_gettop(_pimpl->lua_state) == 0); 288 | lua_close(_pimpl->lua_state); 289 | _pimpl->lua_state = NULL; 290 | } 291 | 292 | 293 | /// Wrapper around lua_getglobal. 294 | /// 295 | /// \param name The second parameter to lua_getglobal. 296 | /// 297 | /// \throw api_error If lua_getglobal fails. 298 | /// 299 | /// \warning Terminates execution if there is not enough memory to manipulate 300 | /// the Lua stack. 301 | void 302 | lutok::state::get_global(const std::string& name) 303 | { 304 | lua_pushcfunction(_pimpl->lua_state, protected_getglobal); 305 | lua_pushstring(_pimpl->lua_state, name.c_str()); 306 | if (lua_pcall(_pimpl->lua_state, 1, 1, 0) != 0) 307 | throw lutok::api_error::from_stack(*this, "lua_getglobal"); 308 | } 309 | 310 | 311 | /// Pushes a reference to the global table onto the stack. 312 | /// 313 | /// This is a wrapper around the incompatible differences between Lua 5.1 and 314 | /// 5.2 to access to the globals table. 315 | /// 316 | /// \post state(-1) Contains the reference to the globals table. 317 | void 318 | lutok::state::get_global_table(void) 319 | { 320 | #if LUA_VERSION_NUM >= 502 321 | lua_pushvalue(_pimpl->lua_state, registry_index); 322 | lua_pushinteger(_pimpl->lua_state, LUA_RIDX_GLOBALS); 323 | lua_gettable(_pimpl->lua_state, -2); 324 | lua_remove(_pimpl->lua_state, -2); 325 | #else 326 | lua_pushvalue(_pimpl->lua_state, LUA_GLOBALSINDEX); 327 | #endif 328 | } 329 | 330 | 331 | /// Wrapper around luaL_getmetafield. 332 | /// 333 | /// \param index The second parameter to luaL_getmetafield. 334 | /// \param name The third parameter to luaL_getmetafield. 335 | /// 336 | /// \return The return value of luaL_getmetafield. 337 | /// 338 | /// \warning Terminates execution if there is not enough memory to manipulate 339 | /// the Lua stack. 340 | bool 341 | lutok::state::get_metafield(const int index, const std::string& name) 342 | { 343 | return luaL_getmetafield(_pimpl->lua_state, index, name.c_str()) != 0; 344 | } 345 | 346 | 347 | /// Wrapper around lua_getmetatable. 348 | /// 349 | /// \param index The second parameter to lua_getmetatable. 350 | /// 351 | /// \return The return value of lua_getmetatable. 352 | bool 353 | lutok::state::get_metatable(const int index) 354 | { 355 | return lua_getmetatable(_pimpl->lua_state, index) != 0; 356 | } 357 | 358 | 359 | /// Wrapper around lua_gettable. 360 | /// 361 | /// \param index The second parameter to lua_gettable. 362 | /// 363 | /// \throw api_error If lua_gettable fails. 364 | /// 365 | /// \warning Terminates execution if there is not enough memory to manipulate 366 | /// the Lua stack. 367 | void 368 | lutok::state::get_table(const int index) 369 | { 370 | assert(lua_gettop(_pimpl->lua_state) >= 2); 371 | lua_pushcfunction(_pimpl->lua_state, protected_gettable); 372 | lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index); 373 | lua_pushvalue(_pimpl->lua_state, -3); 374 | if (lua_pcall(_pimpl->lua_state, 2, 1, 0) != 0) 375 | throw lutok::api_error::from_stack(*this, "lua_gettable"); 376 | lua_remove(_pimpl->lua_state, -2); 377 | } 378 | 379 | 380 | /// Wrapper around lua_gettop. 381 | /// 382 | /// \return The return value of lua_gettop. 383 | int 384 | lutok::state::get_top(void) 385 | { 386 | return lua_gettop(_pimpl->lua_state); 387 | } 388 | 389 | 390 | /// Wrapper around lua_insert. 391 | /// 392 | /// \param index The second parameter to lua_insert. 393 | void 394 | lutok::state::insert(const int index) 395 | { 396 | lua_insert(_pimpl->lua_state, index); 397 | } 398 | 399 | 400 | /// Wrapper around lua_isboolean. 401 | /// 402 | /// \param index The second parameter to lua_isboolean. 403 | /// 404 | /// \return The return value of lua_isboolean. 405 | bool 406 | lutok::state::is_boolean(const int index) 407 | { 408 | return lua_isboolean(_pimpl->lua_state, index); 409 | } 410 | 411 | 412 | /// Wrapper around lua_isfunction. 413 | /// 414 | /// \param index The second parameter to lua_isfunction. 415 | /// 416 | /// \return The return value of lua_isfunction. 417 | bool 418 | lutok::state::is_function(const int index) 419 | { 420 | return lua_isfunction(_pimpl->lua_state, index); 421 | } 422 | 423 | 424 | /// Wrapper around lua_isnil. 425 | /// 426 | /// \param index The second parameter to lua_isnil. 427 | /// 428 | /// \return The return value of lua_isnil. 429 | bool 430 | lutok::state::is_nil(const int index) 431 | { 432 | return lua_isnil(_pimpl->lua_state, index); 433 | } 434 | 435 | 436 | /// Wrapper around lua_isnumber. 437 | /// 438 | /// \param index The second parameter to lua_isnumber. 439 | /// 440 | /// \return The return value of lua_isnumber. 441 | bool 442 | lutok::state::is_number(const int index) 443 | { 444 | return lua_isnumber(_pimpl->lua_state, index); 445 | } 446 | 447 | 448 | /// Wrapper around lua_isstring. 449 | /// 450 | /// \param index The second parameter to lua_isstring. 451 | /// 452 | /// \return The return value of lua_isstring. 453 | bool 454 | lutok::state::is_string(const int index) 455 | { 456 | return lua_isstring(_pimpl->lua_state, index); 457 | } 458 | 459 | 460 | /// Wrapper around lua_istable. 461 | /// 462 | /// \param index The second parameter to lua_istable. 463 | /// 464 | /// \return The return value of lua_istable. 465 | bool 466 | lutok::state::is_table(const int index) 467 | { 468 | return lua_istable(_pimpl->lua_state, index); 469 | } 470 | 471 | 472 | /// Wrapper around lua_isuserdata. 473 | /// 474 | /// \param index The second parameter to lua_isuserdata. 475 | /// 476 | /// \return The return value of lua_isuserdata. 477 | bool 478 | lutok::state::is_userdata(const int index) 479 | { 480 | return lua_isuserdata(_pimpl->lua_state, index); 481 | } 482 | 483 | 484 | /// Wrapper around luaL_loadfile. 485 | /// 486 | /// \param file The second parameter to luaL_loadfile. 487 | /// 488 | /// \throw api_error If luaL_loadfile returns an error. 489 | /// \throw file_not_found_error If the file cannot be accessed. 490 | /// 491 | /// \warning Terminates execution if there is not enough memory. 492 | void 493 | lutok::state::load_file(const std::string& file) 494 | { 495 | if (::access(file.c_str(), R_OK) == -1) 496 | throw lutok::file_not_found_error(file); 497 | if (luaL_loadfile(_pimpl->lua_state, file.c_str()) != 0) 498 | throw lutok::api_error::from_stack(*this, "luaL_loadfile"); 499 | } 500 | 501 | 502 | /// Wrapper around luaL_loadstring. 503 | /// 504 | /// \param str The second parameter to luaL_loadstring. 505 | /// 506 | /// \throw api_error If luaL_loadstring returns an error. 507 | /// 508 | /// \warning Terminates execution if there is not enough memory. 509 | void 510 | lutok::state::load_string(const std::string& str) 511 | { 512 | if (luaL_loadstring(_pimpl->lua_state, str.c_str()) != 0) 513 | throw lutok::api_error::from_stack(*this, "luaL_loadstring"); 514 | } 515 | 516 | 517 | /// Wrapper around lua_newtable. 518 | /// 519 | /// \warning Terminates execution if there is not enough memory. 520 | void 521 | lutok::state::new_table(void) 522 | { 523 | lua_newtable(_pimpl->lua_state); 524 | } 525 | 526 | 527 | /// Wrapper around lua_newuserdata. 528 | /// 529 | /// This is internal. The public type-safe interface of this method should be 530 | /// used instead. 531 | /// 532 | /// \param size The second parameter to lua_newuserdata. 533 | /// 534 | /// \return The return value of lua_newuserdata. 535 | /// 536 | /// \warning Terminates execution if there is not enough memory. 537 | void* 538 | lutok::state::new_userdata_voidp(const size_t size) 539 | { 540 | return lua_newuserdata(_pimpl->lua_state, size); 541 | } 542 | 543 | 544 | /// Wrapper around lua_next. 545 | /// 546 | /// \param index The second parameter to lua_next. 547 | /// 548 | /// \return True if there are more elements to process; false otherwise. 549 | /// 550 | /// \warning Terminates execution if there is not enough memory. 551 | bool 552 | lutok::state::next(const int index) 553 | { 554 | assert(lua_istable(_pimpl->lua_state, index)); 555 | assert(lua_gettop(_pimpl->lua_state) >= 1); 556 | lua_pushcfunction(_pimpl->lua_state, protected_next); 557 | lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index); 558 | lua_pushvalue(_pimpl->lua_state, -3); 559 | if (lua_pcall(_pimpl->lua_state, 2, LUA_MULTRET, 0) != 0) 560 | throw lutok::api_error::from_stack(*this, "lua_next"); 561 | const bool more = lua_toboolean(_pimpl->lua_state, -1); 562 | lua_pop(_pimpl->lua_state, 1); 563 | if (more) 564 | lua_remove(_pimpl->lua_state, -3); 565 | else 566 | lua_pop(_pimpl->lua_state, 1); 567 | return more; 568 | } 569 | 570 | 571 | /// Wrapper around luaL_openlibs. 572 | /// 573 | /// \throw api_error If luaL_openlibs fails. 574 | /// 575 | /// \warning Terminates execution if there is not enough memory. 576 | void 577 | lutok::state::open_all(void) 578 | { 579 | luaL_openlibs(_pimpl->lua_state); 580 | } 581 | 582 | 583 | /// Wrapper around luaopen_base. 584 | /// 585 | /// \throw api_error If luaopen_base fails. 586 | /// 587 | /// \warning Terminates execution if there is not enough memory. 588 | void 589 | lutok::state::open_base(void) 590 | { 591 | lua_pushcfunction(_pimpl->lua_state, luaopen_base); 592 | if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0) 593 | throw lutok::api_error::from_stack(*this, "luaopen_base"); 594 | } 595 | 596 | 597 | /// Wrapper around luaopen_string. 598 | /// 599 | /// \throw api_error If luaopen_string fails. 600 | /// 601 | /// \warning Terminates execution if there is not enough memory. 602 | void 603 | lutok::state::open_string(void) 604 | { 605 | #if LUA_VERSION_NUM >= 502 606 | luaL_requiref(_pimpl->lua_state, LUA_STRLIBNAME, luaopen_string, 1); 607 | lua_pop(_pimpl->lua_state, 1); 608 | #else 609 | lua_pushcfunction(_pimpl->lua_state, luaopen_string); 610 | if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0) 611 | throw lutok::api_error::from_stack(*this, "luaopen_string"); 612 | #endif 613 | } 614 | 615 | 616 | /// Wrapper around luaopen_table. 617 | /// 618 | /// \throw api_error If luaopen_table fails. 619 | /// 620 | /// \warning Terminates execution if there is not enough memory. 621 | void 622 | lutok::state::open_table(void) 623 | { 624 | #if LUA_VERSION_NUM >= 502 625 | luaL_requiref(_pimpl->lua_state, LUA_TABLIBNAME, luaopen_table, 1); 626 | lua_pop(_pimpl->lua_state, 1); 627 | #else 628 | lua_pushcfunction(_pimpl->lua_state, luaopen_table); 629 | if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0) 630 | throw lutok::api_error::from_stack(*this, "luaopen_table"); 631 | #endif 632 | } 633 | 634 | 635 | /// Wrapper around lua_pcall. 636 | /// 637 | /// \param nargs The second parameter to lua_pcall. 638 | /// \param nresults The third parameter to lua_pcall. 639 | /// \param errfunc The fourth parameter to lua_pcall. 640 | /// 641 | /// \throw api_error If lua_pcall returns an error. 642 | void 643 | lutok::state::pcall(const int nargs, const int nresults, const int errfunc) 644 | { 645 | if (lua_pcall(_pimpl->lua_state, nargs, nresults, errfunc) != 0) 646 | throw lutok::api_error::from_stack(*this, "lua_pcall"); 647 | } 648 | 649 | 650 | /// Wrapper around lua_pop. 651 | /// 652 | /// \param count The second parameter to lua_pop. 653 | void 654 | lutok::state::pop(const int count) 655 | { 656 | assert(count <= lua_gettop(_pimpl->lua_state)); 657 | lua_pop(_pimpl->lua_state, count); 658 | assert(lua_gettop(_pimpl->lua_state) >= 0); 659 | } 660 | 661 | 662 | /// Wrapper around lua_pushboolean. 663 | /// 664 | /// \param value The second parameter to lua_pushboolean. 665 | void 666 | lutok::state::push_boolean(const bool value) 667 | { 668 | lua_pushboolean(_pimpl->lua_state, value ? 1 : 0); 669 | } 670 | 671 | 672 | /// Wrapper around lua_pushcclosure. 673 | /// 674 | /// This is not a pure wrapper around lua_pushcclosure because this has to do 675 | /// extra magic to allow passing C++ functions instead of plain C functions. 676 | /// 677 | /// \param function The C++ function to be pushed as a closure. 678 | /// \param nvalues The number of upvalues that the function receives. 679 | void 680 | lutok::state::push_cxx_closure(cxx_function function, const int nvalues) 681 | { 682 | cxx_function *data = static_cast< cxx_function* >( 683 | lua_newuserdata(_pimpl->lua_state, sizeof(cxx_function))); 684 | *data = function; 685 | lua_pushcclosure(_pimpl->lua_state, cxx_closure_trampoline, nvalues + 1); 686 | } 687 | 688 | 689 | /// Wrapper around lua_pushcfunction. 690 | /// 691 | /// This is not a pure wrapper around lua_pushcfunction because this has to do 692 | /// extra magic to allow passing C++ functions instead of plain C functions. 693 | /// 694 | /// \param function The C++ function to be pushed. 695 | void 696 | lutok::state::push_cxx_function(cxx_function function) 697 | { 698 | cxx_function *data = static_cast< cxx_function* >( 699 | lua_newuserdata(_pimpl->lua_state, sizeof(cxx_function))); 700 | *data = function; 701 | lua_pushcclosure(_pimpl->lua_state, cxx_function_trampoline, 1); 702 | } 703 | 704 | 705 | /// Wrapper around lua_pushinteger. 706 | /// 707 | /// \param value The second parameter to lua_pushinteger. 708 | void 709 | lutok::state::push_integer(const int value) 710 | { 711 | lua_pushinteger(_pimpl->lua_state, value); 712 | } 713 | 714 | 715 | /// Wrapper around lua_pushnil. 716 | void 717 | lutok::state::push_nil(void) 718 | { 719 | lua_pushnil(_pimpl->lua_state); 720 | } 721 | 722 | 723 | /// Wrapper around lua_pushstring. 724 | /// 725 | /// \param str The second parameter to lua_pushstring. 726 | /// 727 | /// \warning Terminates execution if there is not enough memory. 728 | void 729 | lutok::state::push_string(const std::string& str) 730 | { 731 | lua_pushstring(_pimpl->lua_state, str.c_str()); 732 | } 733 | 734 | 735 | /// Wrapper around lua_pushvalue. 736 | /// 737 | /// \param index The second parameter to lua_pushvalue. 738 | void 739 | lutok::state::push_value(const int index) 740 | { 741 | lua_pushvalue(_pimpl->lua_state, index); 742 | } 743 | 744 | 745 | /// Wrapper around lua_rawget. 746 | /// 747 | /// \param index The second parameter to lua_rawget. 748 | void 749 | lutok::state::raw_get(const int index) 750 | { 751 | lua_rawget(_pimpl->lua_state, index); 752 | } 753 | 754 | 755 | /// Wrapper around lua_rawset. 756 | /// 757 | /// \param index The second parameter to lua_rawset. 758 | /// 759 | /// \warning Terminates execution if there is not enough memory to manipulate 760 | /// the Lua stack. 761 | void 762 | lutok::state::raw_set(const int index) 763 | { 764 | lua_rawset(_pimpl->lua_state, index); 765 | } 766 | 767 | 768 | /// Wrapper around lua_setglobal. 769 | /// 770 | /// \param name The second parameter to lua_setglobal. 771 | /// 772 | /// \throw api_error If lua_setglobal fails. 773 | /// 774 | /// \warning Terminates execution if there is not enough memory to manipulate 775 | /// the Lua stack. 776 | void 777 | lutok::state::set_global(const std::string& name) 778 | { 779 | lua_pushcfunction(_pimpl->lua_state, protected_setglobal); 780 | lua_pushstring(_pimpl->lua_state, name.c_str()); 781 | lua_pushvalue(_pimpl->lua_state, -3); 782 | if (lua_pcall(_pimpl->lua_state, 2, 0, 0) != 0) 783 | throw lutok::api_error::from_stack(*this, "lua_setglobal"); 784 | lua_pop(_pimpl->lua_state, 1); 785 | } 786 | 787 | 788 | /// Wrapper around lua_setmetatable. 789 | /// 790 | /// \param index The second parameter to lua_setmetatable. 791 | void 792 | lutok::state::set_metatable(const int index) 793 | { 794 | lua_setmetatable(_pimpl->lua_state, index); 795 | } 796 | 797 | 798 | /// Wrapper around lua_settable. 799 | /// 800 | /// \param index The second parameter to lua_settable. 801 | /// 802 | /// \throw api_error If lua_settable fails. 803 | /// 804 | /// \warning Terminates execution if there is not enough memory to manipulate 805 | /// the Lua stack. 806 | void 807 | lutok::state::set_table(const int index) 808 | { 809 | lua_pushcfunction(_pimpl->lua_state, protected_settable); 810 | lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index); 811 | lua_pushvalue(_pimpl->lua_state, -4); 812 | lua_pushvalue(_pimpl->lua_state, -4); 813 | if (lua_pcall(_pimpl->lua_state, 3, 0, 0) != 0) 814 | throw lutok::api_error::from_stack(*this, "lua_settable"); 815 | lua_pop(_pimpl->lua_state, 2); 816 | } 817 | 818 | 819 | /// Wrapper around lua_toboolean. 820 | /// 821 | /// \param index The second parameter to lua_toboolean. 822 | /// 823 | /// \return The return value of lua_toboolean. 824 | bool 825 | lutok::state::to_boolean(const int index) 826 | { 827 | assert(is_boolean(index)); 828 | return lua_toboolean(_pimpl->lua_state, index); 829 | } 830 | 831 | 832 | /// Wrapper around lua_tointeger. 833 | /// 834 | /// \param index The second parameter to lua_tointeger. 835 | /// 836 | /// \return The return value of lua_tointeger. 837 | long 838 | lutok::state::to_integer(const int index) 839 | { 840 | assert(is_number(index)); 841 | return lua_tointeger(_pimpl->lua_state, index); 842 | } 843 | 844 | 845 | /// Wrapper around lua_touserdata. 846 | /// 847 | /// This is internal. The public type-safe interface of this method should be 848 | /// used instead. 849 | /// 850 | /// \param index The second parameter to lua_touserdata. 851 | /// 852 | /// \return The return value of lua_touserdata. 853 | /// 854 | /// \warning Terminates execution if there is not enough memory. 855 | void* 856 | lutok::state::to_userdata_voidp(const int index) 857 | { 858 | return lua_touserdata(_pimpl->lua_state, index); 859 | } 860 | 861 | 862 | 863 | /// Wrapper around lua_tostring. 864 | /// 865 | /// \param index The second parameter to lua_tostring. 866 | /// 867 | /// \return The return value of lua_tostring. 868 | /// 869 | /// \warning Terminates execution if there is not enough memory. 870 | std::string 871 | lutok::state::to_string(const int index) 872 | { 873 | assert(is_string(index)); 874 | const char *raw_string = lua_tostring(_pimpl->lua_state, index); 875 | // Note that the creation of a string object below (explicit for clarity) 876 | // implies that the raw string is duplicated and, henceforth, the string is 877 | // safe even if the corresponding element is popped from the Lua stack. 878 | return std::string(raw_string); 879 | } 880 | 881 | 882 | /// Wrapper around lua_upvalueindex. 883 | /// 884 | /// \param index The first parameter to lua_upvalueindex. 885 | /// 886 | /// \return The return value of lua_upvalueindex. 887 | int 888 | lutok::state::upvalue_index(const int index) 889 | { 890 | return lua_upvalueindex(index); 891 | } 892 | 893 | 894 | /// Gets the internal lua_State object. 895 | /// 896 | /// \return The raw Lua state. This is returned as a void pointer to prevent 897 | /// including the lua.hpp header file from our public interface. The only way 898 | /// to call this method is by using the c_gate module, and c_gate takes care of 899 | /// casting this object to the appropriate type. 900 | void* 901 | lutok::state::raw_state(void) 902 | { 903 | return _pimpl->lua_state; 904 | } 905 | -------------------------------------------------------------------------------- /state.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file state.hpp 30 | /// Provides the state wrapper class for the Lua C state. 31 | 32 | #if !defined(LUTOK_STATE_HPP) 33 | #define LUTOK_STATE_HPP 34 | 35 | #include 36 | #include 37 | 38 | namespace lutok { 39 | 40 | 41 | class debug; 42 | class state; 43 | 44 | 45 | /// The type of a C++ function that can be bound into Lua. 46 | /// 47 | /// Functions of this type are free to raise exceptions. These will not 48 | /// propagate into the Lua C API. However, any such exceptions will be reported 49 | /// as a Lua error and their type will be lost. 50 | typedef int (*cxx_function)(state&); 51 | 52 | 53 | /// Stack index constant pointing to the registry table. 54 | extern const int registry_index; 55 | 56 | 57 | /// A RAII model for the Lua state. 58 | /// 59 | /// This class holds the state of the Lua interpreter during its existence and 60 | /// provides wrappers around several Lua library functions that operate on such 61 | /// state. 62 | /// 63 | /// These wrapper functions differ from the C versions in that they use the 64 | /// implicit state hold by the class, they use C++ types where appropriate and 65 | /// they use exceptions to report errors. 66 | /// 67 | /// The wrappers intend to be as lightweight as possible but, in some 68 | /// situations, they are pretty complex because they need to do extra work to 69 | /// capture the errors reported by the Lua C API. We prefer having fine-grained 70 | /// error control rather than efficiency, so this is OK. 71 | class state { 72 | struct impl; 73 | 74 | /// Pointer to the shared internal implementation. 75 | std::shared_ptr< impl > _pimpl; 76 | 77 | void* new_userdata_voidp(const size_t); 78 | void* to_userdata_voidp(const int); 79 | 80 | friend class state_c_gate; 81 | explicit state(void*); 82 | void* raw_state(void); 83 | 84 | public: 85 | state(void); 86 | ~state(void); 87 | 88 | void close(void); 89 | void get_global(const std::string&); 90 | void get_global_table(void); 91 | bool get_metafield(const int, const std::string&); 92 | bool get_metatable(const int); 93 | void get_table(const int); 94 | int get_top(void); 95 | void insert(const int); 96 | bool is_boolean(const int); 97 | bool is_function(const int); 98 | bool is_nil(const int); 99 | bool is_number(const int); 100 | bool is_string(const int); 101 | bool is_table(const int); 102 | bool is_userdata(const int); 103 | void load_file(const std::string&); 104 | void load_string(const std::string&); 105 | void new_table(void); 106 | template< typename Type > Type* new_userdata(void); 107 | bool next(const int); 108 | void open_all(void); 109 | void open_base(void); 110 | void open_string(void); 111 | void open_table(void); 112 | void pcall(const int, const int, const int); 113 | void pop(const int); 114 | void push_boolean(const bool); 115 | void push_cxx_closure(cxx_function, const int); 116 | void push_cxx_function(cxx_function); 117 | void push_integer(const int); 118 | void push_nil(void); 119 | void push_string(const std::string&); 120 | void push_value(const int); 121 | void raw_get(const int); 122 | void raw_set(const int); 123 | void set_global(const std::string&); 124 | void set_metatable(const int); 125 | void set_table(const int); 126 | bool to_boolean(const int); 127 | long to_integer(const int); 128 | template< typename Type > Type* to_userdata(const int); 129 | std::string to_string(const int); 130 | int upvalue_index(const int); 131 | }; 132 | 133 | 134 | } // namespace lutok 135 | 136 | #endif // !defined(LUTOK_STATE_HPP) 137 | -------------------------------------------------------------------------------- /state.ipp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | #if !defined(LUTOK_STATE_IPP) 30 | #define LUTOK_STATE_IPP 31 | 32 | #include 33 | 34 | namespace lutok { 35 | 36 | 37 | /// Wrapper around lua_newuserdata. 38 | /// 39 | /// This allocates an object as big as the size of the provided Type. 40 | /// 41 | /// \return The pointer to the allocated userdata object. 42 | /// 43 | /// \warning Terminates execution if there is not enough memory. 44 | template< typename Type > 45 | Type* 46 | state::new_userdata(void) 47 | { 48 | return static_cast< Type* >(new_userdata_voidp(sizeof(Type))); 49 | } 50 | 51 | 52 | /// Wrapper around lua_touserdata. 53 | /// 54 | /// \param index The second parameter to lua_touserdata. 55 | /// 56 | /// \return The return value of lua_touserdata. 57 | template< typename Type > 58 | Type* 59 | state::to_userdata(const int index) 60 | { 61 | return static_cast< Type* >(to_userdata_voidp(index)); 62 | } 63 | 64 | 65 | } // namespace lutok 66 | 67 | #endif // !defined(LUTOK_STATE_IPP) 68 | -------------------------------------------------------------------------------- /test_utils.hpp: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above copyright 11 | // notice, this list of conditions and the following disclaimer in the 12 | // documentation and/or other materials provided with the distribution. 13 | // * Neither the name of Google Inc. nor the names of its contributors 14 | // may be used to endorse or promote products derived from this software 15 | // without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | /// \file test_utils.hpp 30 | /// Utilities for tests of the lua modules. 31 | /// 32 | /// This file is intended to be included once, and only once, for every test 33 | /// program that needs it. All the code is herein contained to simplify the 34 | /// dependency chain in the build rules. 35 | 36 | #if !defined(LUTOK_TEST_UTILS_HPP) 37 | # define LUTOK_TEST_UTILS_HPP 38 | #else 39 | # error "test_utils.hpp can only be included once" 40 | #endif 41 | 42 | #include 43 | 44 | #include "c_gate.hpp" 45 | #include "exceptions.hpp" 46 | #include "state.hpp" 47 | 48 | 49 | namespace { 50 | 51 | 52 | /// Checks that a given expression raises a particular lutok::api_error. 53 | /// 54 | /// We cannot make any assumptions regarding the error text provided by Lua, so 55 | /// we resort to checking only which API function raised the error (because our 56 | /// code is the one hardcoding these strings). 57 | /// 58 | /// \param exp_api_function The name of the Lua C API function that causes the 59 | /// error. 60 | /// \param statement The statement to execute. 61 | #define REQUIRE_API_ERROR(exp_api_function, statement) \ 62 | do { \ 63 | try { \ 64 | statement; \ 65 | ATF_FAIL("api_error not raised by " #statement); \ 66 | } catch (const lutok::api_error& api_error) { \ 67 | ATF_REQUIRE_EQ(exp_api_function, api_error.api_function()); \ 68 | } \ 69 | } while (0) 70 | 71 | 72 | /// Gets the pointer to the internal lua_State of a state object. 73 | /// 74 | /// This is pure syntactic sugar to simplify typing in the test cases. 75 | /// 76 | /// \param state The Lua state. 77 | /// 78 | /// \return The internal lua_State of the input Lua state. 79 | static inline lua_State* 80 | raw(lutok::state& state) 81 | { 82 | return lutok::state_c_gate(state).c_state(); 83 | } 84 | 85 | 86 | /// Ensures that the Lua stack maintains its original height upon exit. 87 | /// 88 | /// Use an instance of this class to check that a piece of code does not have 89 | /// side-effects on the Lua stack. 90 | /// 91 | /// To be used within a test case only. 92 | class stack_balance_checker { 93 | /// The Lua state. 94 | lutok::state& _state; 95 | 96 | /// Whether to install a sentinel on the stack for balance enforcement. 97 | bool _with_sentinel; 98 | 99 | /// The height of the stack on creation. 100 | unsigned int _old_count; 101 | 102 | public: 103 | /// Constructs a new stack balance checker. 104 | /// 105 | /// \param state_ The Lua state to validate. 106 | /// \param with_sentinel_ If true, insert a sentinel item into the stack and 107 | /// validate upon exit that the item is still there. This is an attempt 108 | /// to ensure that already-existing items are not removed from the stack 109 | /// by the code under test. 110 | stack_balance_checker(lutok::state& state_, 111 | const bool with_sentinel_ = true) : 112 | _state(state_), 113 | _with_sentinel(with_sentinel_), 114 | _old_count(_state.get_top()) 115 | { 116 | if (_with_sentinel) 117 | _state.push_integer(987654321); 118 | } 119 | 120 | /// Destructor for the object. 121 | /// 122 | /// If the stack height does not match the height when the instance was 123 | /// created, this fails the test case. 124 | ~stack_balance_checker(void) 125 | { 126 | if (_with_sentinel) { 127 | if (!_state.is_number(-1) || _state.to_integer(-1) != 987654321) 128 | ATF_FAIL("Stack corrupted: sentinel not found"); 129 | _state.pop(1); 130 | } 131 | 132 | unsigned int new_count = _state.get_top(); 133 | if (_old_count != new_count) 134 | //ATF_FAIL(F("Stack not balanced: before %d, after %d") % 135 | // _old_count % new_count); 136 | ATF_FAIL("Stack not balanced"); 137 | } 138 | }; 139 | 140 | 141 | } // anonymous namespace 142 | --------------------------------------------------------------------------------