From: <gua...@us...> - 2013-05-28 03:53:56
|
Revision: 4009 http://sourceforge.net/p/moneymanagerex/code/4009 Author: guanlisheng Date: 2013-05-28 03:53:51 +0000 (Tue, 28 May 2013) Log Message: ----------- sync wxpresets Modified Paths: -------------- trunk/mmex/Makefile.in trunk/mmex/build/bakefiles/common.bkl trunk/mmex/build/bakefiles/presets/wx.bkl trunk/mmex/build/bakefiles/presets/wx_unix.bkl trunk/mmex/build/bakefiles/presets/wx_win32.bkl trunk/mmex/build/msw/config.gcc trunk/mmex/build/msw/config.vc trunk/mmex/build/msw/makefile.gcc trunk/mmex/build/msw/makefile.vc trunk/mmex/build/msw/tests/makefile.gcc trunk/mmex/build/msw/tests/makefile.vc trunk/mmex/configure trunk/mmex/m4/autoconf_inc.m4 trunk/mmex/src/tests/Makefile.in Modified: trunk/mmex/Makefile.in =================================================================== --- trunk/mmex/Makefile.in 2013-05-28 03:15:07 UTC (rev 4008) +++ trunk/mmex/Makefile.in 2013-05-28 03:53:51 UTC (rev 4009) @@ -279,7 +279,7 @@ $(RANLIB) $@ mmex$(EXEEXT): $(MMEX_OBJECTS) $(LIBPREFIX)wxsqlite$(LIBEXT) $(LIBPREFIX)sqlite$(LIBEXT) $(LIBPREFIX)lua$(LIBEXT) $(__mmex___win32rc) - $(CXX) -o $@ $(MMEX_OBJECTS) -L. -L. -L. $(WX_LIBS) $(LDFLAGS_GUI) $(LDFLAGS) -lwxsqlite -lsqlite -llua $(LIBS) + $(CXX) -o $@ $(MMEX_OBJECTS) -L. -L. -L. $(LDFLAGS_GUI) $(LDFLAGS) -lwxsqlite -lsqlite -llua $(WX_LIBS) $(LIBS) $(__mmex___mac_setfilecmd) $(__mmex___os2_emxbindcmd) Modified: trunk/mmex/build/bakefiles/common.bkl =================================================================== --- trunk/mmex/build/bakefiles/common.bkl 2013-05-28 03:15:07 UTC (rev 4008) +++ trunk/mmex/build/bakefiles/common.bkl 2013-05-28 03:53:51 UTC (rev 4009) @@ -14,6 +14,7 @@ <include file="presets/wx.bkl"/> + <include file="config.bkl"/> <set var="CAN_CONFIG"> @@ -58,19 +59,6 @@ <!-- except VC++ IDE projects --> <if cond="not FORMAT.endswith('prj')"> - <option name="TARGET_CPU"> - - <default-value>$(DOLLAR)(CPU)</default-value> - - <description> -The target processor architecture must be specified when it is not X86. -This does not affect the compiler output, so you still need to make sure -your environment is set up appropriately with the correct compiler in the -PATH. Accepted values: AMD64, IA64. - </description> - - </option> - <set var="CPU_ARCH"> <if cond="TARGET_CPU==''">x86</if> <if cond="TARGET_CPU=='x86'">x86</if> Modified: trunk/mmex/build/bakefiles/presets/wx.bkl =================================================================== --- trunk/mmex/build/bakefiles/presets/wx.bkl 2013-05-28 03:15:07 UTC (rev 4008) +++ trunk/mmex/build/bakefiles/presets/wx.bkl 2013-05-28 03:53:51 UTC (rev 4009) @@ -1,28 +1,142 @@ <?xml version="1.0" ?> -<!-- $Id: wx.bkl 41871 2006-10-10 09:54:26Z VS $ --> +<!-- $Id$ --> <!-- Presets for building wxWidgets applications. - FIXME: docs + These presets provide the following "public" interface: + + OPTIONS: + + - WX_* : used to let the user of the generated makefile choose a wxWidgets + build among those available; you can use them in your project to + e.g. build a target only if WX_SHARED is 0 or if WX_PORT is "msw". + + + VARIABLES: + + - WXLIBPOSTFIX: contains the [u][d] string which is typically useful when + defining names of directories/files which should coexist + with other builds using different wxWidgets configurations. + + + TEMPLATES: + + - wx, wx-lib: templates to be used respectively for <dll>/<exe> and <lib> + targets; they add all the wxWidgets-related settings (e.g. the + include and library search paths, the necessary preprocessor + symbols, etc). + + - wxgui: to be used when building GUI-mode applications. + + - wxconsole: to be used when building console-only applications + (NOTE: it doesn't add the wxUSE_GUI=0 define since you don't + need it when compiling wxBase-only code). + + - wxlike: this template should be combined with "wx" or "wx-lib" and will + make your project build with the same Unicode & shared + config as the wxWidgets build selected using the WX_* options. + + + TARGET TAGS: + + - <wx-lib>: to define which wxWidgets libraries to link with; + please note that you should use them in the right order or + linking under Unix would result in errors, e.g. + + <wx-lib>core</wx-lib> + <wx-lib>base</wx-lib> + + is correct, but the reverse is not (if lib A depends on lib B, then + lib A must be listed before B). So <wx-lib>base</wx-lib> + (which must always be present) should be the last wx-lib tag. + + - <wxlike-libname>, + <wxlike-dllname>: useful if you want to have a build logic similar to the + wxWidgets build logic which allows different builds to + coexist without conflicts. These tags helps you to name + libraries using the same wxWidgets rules and thus avoid + conflicts between libraries compiled in e.g. Unicode, + shared mode and those compiled in ANSI, shared mode &c. + + - <wxlike-lib>: if your library/application needs to link with both + wxWidgets and some other wx-based library, which in turn + follows the wxWidgets naming conventions, then this tag is + what you need to reference the wx-based additional library. + + - <wxlike-dirname>: sets the output directory for the current target to $(value) + when on Unix and to e.g. $(value)/vc_lib when on Windows, + i.e. acts like <dirname> just following wxWidgets naming rules. + Useful to allow multiple builds of the + + - <wxlike-paths>: if your library/application needs to compile & link with both + wxWidgets and some other wx-based library, which in turn + follows the wxWidgets naming conventions, then this tag is + what you need to add to the compiler and linker flags the paths + of the "include" and "lib" folders of the wx-based additional library. + + + GLOBAL TAGS: + + - <set-wxlike-builddir>: sets BUILDDIR using wxWidgets naming rules to help + to keep object files compiled with different + settings separate. + + - <set-wxlike>: sets a variable with the name of a library named with the same + wxWidgets rules. + + + NOTE: as a reference here is a list of all wxWidgets libraries satisfying + the dependency constraints mentioned in <wx-lib> description: + + <wx-lib>webview</wx-lib> + <wx-lib>richtext</wx-lib> + <wx-lib>aui</wx-lib> + <wx-lib>ribbon</wx-lib> + <wx-lib>propgrid</wx-lib> + <wx-lib>stc</wx-lib> + <wx-lib>qa</wx-lib> + <wx-lib>gl</wx-lib> + <wx-lib>xrc</wx-lib> + <wx-lib>html</wx-lib> + <wx-lib>media</wx-lib> + <wx-lib>adv</wx-lib> + <wx-lib>net</wx-lib> + <wx-lib>xml</wx-lib> + <wx-lib>core</wx-lib> + <wx-lib>base</wx-lib> + --> <makefile> + <requires version="0.2.2"/> + + <using module="wx_presets"/> + <!-- this variable identifies the version of the wx presets. - this is changed only when major changes to wxpresets take place. --> - <set var="WX_PRESETS_VERSION">3</set> + this is changed only when major changes to wxpresets take place. + --> + <set var="WX_PRESETS_VERSION">4</set> - <!-- list of known libraries used by wx-lib tag defined in wx_unix.bkl and wx_win32.bkl --> - <set var="LIB_LIST"> - base core net xml odbc xrc html adv media gl dbgrid qa aui richtext + <!-- list of known libraries used by wx-lib tag defined in wx_unix.bkl and wx_win32.bkl + VERY IMPORTANT: when updating this list also update the <wx-lib> and <wx-all-libs> + tag definitions. + --> + <set var="WX_LIB_LIST"> + base core net xml xrc html adv media gl qa aui ribbon propgrid richtext stc webview </set> - <!-- NOTE: refer to the NET contrib using NETUTILS instead of NET - (which is already in LIB_LIST) --> - <set var="CONTRIBLIB_LIST">animate applet deprecated fl foldbar gizmos mmedia netutils ogl plot stc svg</set> - <set var="ALLLIB_LIST">$(LIB_LIST) $(CONTRIBLIB_LIST)</set> + <!-- if you define this variable to 0 before including wx presets, the + "test_for_selected_wxbuild" target which is added by default in win32 and GNU + makefiles, won't be added. + This is useful when e.g. you want to have wxWidgets as an optional + dependency and thus you don't want to perform that check unconditionally. + --> + <set var="WX_TEST_FOR_SELECTED_WXBUILD" overwrite="0"> + 1 + </set> <!-- this is a temporary variable until there is non general --> <!-- function in bakefiles for returning native markup for --> @@ -33,10 +147,112 @@ </set> + + <!-- OPTIONS --> + <!-- --> + <!-- These are essentially the configurations you --> + <!-- want in bakefile. --> + <!-- --> + <!-- In MSVC these are the different build --> + <!-- configurations you can have (in the build menu), --> + <!-- and in autoconf is enabled with enable-xxx=xx. --> + <!-- For other compilers a separate configuration --> + <!-- file is created (such as config.gcc on gcc) --> + <!-- which has several options a user can modify. --> + <!-- --> + <!-- Note that the above only happens if an option --> + <!-- is not constant, i.e. if it cannot be determined --> + <!-- by bakefile itself. --> + <!-- Also note that for 'autoconf' format these options --> + <!-- are only useful when used together with wxpresets.m4 --> + <!-- macro file which contains macros for detecting the --> + <!-- option values for wx-based projects. See wxpresets.m4 --> + <!-- comments for more info. --> + + + <!-- Presets for limited dmars make.exe format: --> + <if cond="FORMAT=='dmars'"> + <set var="WX_UNICODE">1</set> + <set var="WX_DEBUG">1</set> + <set var="WX_SHARED">0</set> + </if> + + <!-- 'gnu' format needs to redefine the following options later in wx_unix.bkl --> + <if cond="FORMAT=='gnu'"> + <set var="WX_UNICODE"/> + <set var="WX_SHARED"/> + <set var="WX_PORT"/> + <set var="WX_VERSION"/> + </if> + + + <!-- This is a standard option that determines --> + <!-- whether the user wants to build this library as --> + <!-- a dll or as a static library. --> + <if cond="not isdefined('WX_SHARED')"> + <set var="WX_SHARED_DEFAULT" overwrite="0">0</set> + <option name="WX_SHARED"> + <values>0,1</values> + <values-description>Static,DLL</values-description> + <default-value>$(WX_SHARED_DEFAULT)</default-value> + <description> + Use DLL build of wx library? + </description> + </option> + </if> + + <!-- Configuration for building the bakefile with --> + <!-- unicode strings or not (unicode or ansi). --> + <if cond="not isdefined('WX_UNICODE')"> + <set var="WX_UNICODE_DEFAULT" overwrite="0">1</set> + <option name="WX_UNICODE"> + <values>0,1</values> + <values-description>ANSI,Unicode</values-description> + <default-value>$(WX_UNICODE_DEFAULT)</default-value> + <description> + Use Unicode build of wxWidgets? + </description> + </option> + </if> + + <if cond="not isdefined('WX_DEBUG')"> + <set var="WX_DEBUG_DEFAULT" overwrite="0">1</set> + <option name="WX_DEBUG"> + <values>0,1</values> + <values-description>Release,Debug</values-description> + <default-value>$(WX_DEBUG_DEFAULT)</default-value> + <description> + Use debug build of wxWidgets (linked with debug CRT)? + </description> + </option> + </if> + + <if cond="not isdefined('WX_VERSION')"> + <set var="WX_VERSION_DEFAULT" overwrite="0">29</set> + <option name="WX_VERSION"> + <default-value>$(WX_VERSION_DEFAULT)</default-value> + <description> + Version of the wx library to build against. + </description> + </option> + </if> + + <if cond="not isdefined('WX_MONOLITHIC')"> + <set var="WX_MONOLITHIC_DEFAULT" overwrite="0">0</set> + <option name="WX_MONOLITHIC"> + <values>0,1</values> + <values-description>Multilib,Monolithic</values-description> + <default-value>$(WX_MONOLITHIC_DEFAULT)</default-value> + <description> + Use monolithic build of wxWidgets? + </description> + </option> + </if> + <!-- The directory where wxWidgets is installed: --> <if cond="not isdefined('WX_DIR')"> <set var="WX_DIR_DEFAULT" overwrite="0">$(DOLLAR)($(ENV_VAR)WXWIN)</set> - <option name="WX_DIR" category="path"> + <option name="WX_DIR" category="path" never_empty="1"> <default-value>$(WX_DIR_DEFAULT)</default-value> <description> The directory where wxWidgets library is installed @@ -46,8 +262,28 @@ - <!-- this is just a wrapper that includes the real implementation: --> + <!-- HELPER VARIABLES --> + <!-- --> + <!-- These are handy ways of dealing with the --> + <!-- extensions in the library names of the --> + <!-- wxWindows library. --> + <set var="WXLIBPOSTFIX"> + <if cond="WX_DEBUG=='1' and WX_UNICODE=='1'">ud</if> + <if cond="WX_DEBUG=='1' and WX_UNICODE=='0'">d</if> + <if cond="WX_DEBUG=='0' and WX_UNICODE=='1'">u</if> + </set> + + <if cond="FORMAT!='autoconf'"> + <set var="COMPILER_PREFIX" make_var="1">$(COMPILER)</set> + </if> + + + + + <!-- REAL IMPLEMENTATION --> + <!-- --> + <set var="__wx_included_impl">0</set> <if cond="FORMAT in ['autoconf','gnu']"> @@ -60,8 +296,257 @@ <set var="__wx_included_impl">1</set> </if> + <if cond="FORMAT=='xcode2'"> + <!-- xCode2 is an IDE and thus reuses almost nothing from unix part of wxpresets; + better use the win32 part! --> + <include file="wx_win32.bkl"/> + <set var="__wx_included_impl">1</set> + </if> + <if cond="__wx_included_impl=='0'"> <error>This format is not (yet) supported by wx preset.</error> </if> + + + + <!-- HIGH-LEVEL TEMPLATE --> + <!-- --> + + <!-- Combine 'wxlike' with 'wx' or 'wx-lib' templates to have your + project build in the same configuration used by the selected + wxWidgets build --> + <template id="wxlike"> + <!-- WX_DEBUG-dependent --> + <set var="_OPT"> + <if cond="WX_DEBUG=='1'">off</if> + <if cond="WX_DEBUG=='0'">speed</if> + </set> + <set var="_DEBUGINFO"> + <if cond="WX_DEBUG=='1'">on</if> + <if cond="WX_DEBUG=='0'">off</if> + </set> + + <if cond="FORMAT!='autoconf'"> + <optimize>$(_OPT)</optimize> + <debug-info>$(_DEBUGINFO)</debug-info> + </if> + </template> + + <!-- Template for building wx-based GUI applications --> + <template id="wxgui" template="wx"> + <app-type>gui</app-type> + </template> + + <!-- Template for building wx-based console applications --> + <template id="wxconsole" template="wx"> + <app-type>console</app-type> + </template> + + + + <!-- UTILITY TAGS --> + <!-- --> + + <!-- private helper tag: does the same thing as for <set-wxlike> except that: + - the variable created is always named "__temp" + - can be used (only) inside targets as this is a non-global tag + --> + <define-tag name="__setlibname" rules="lib,dll,module,exe"> + <set var="__temp"> + <if cond="FORMAT!='autoconf' and FORMAT!='gnu'"> + $(attributes['prefix'])_$(WX_PORT)$(WX_VERSION)$(WXLIBPOSTFIX)_$(value) + </if> + <if cond="FORMAT=='autoconf' or FORMAT=='gnu'"> + $(attributes['prefix'])_$(WX_PORT)$(WXLIBPOSTFIX)_$(value)-$(WX_VERSION_MAJOR).$(WX_VERSION_MINOR) + </if> + </set> + </define-tag> + + <!-- A simple tag which helps you to define a library name using the same rules used + by wxWidgets. Use the 'prefix' attribute to add your lib's prefix. + E.g.: + <wxlike-libname prefix='mylib'>module1</wxlike-libname> + <wxlike-libname prefix='mylib'>module2</wxlike-libname> + --> + <define-tag name="wxlike-libname" rules="lib"> + <__setlibname prefix="$(attributes['prefix'])">$(value)</__setlibname> + <libname>$(__temp)</libname> + </define-tag> + + <!-- exactly like <wxlike-libname> but this one sets the DLL name (and the DLL lib import name) + and thus must be used only inside a <dll> target... + --> + <define-tag name="wxlike-dllname" rules="dll,module"> + <__setlibname prefix="$(attributes['prefix'])">$(value)</__setlibname> + <libname>$(__temp)</libname> + <dllname>$(__temp)</dllname> + </define-tag> + + <!-- Links against a library which uses the same wxWidgets conventions. + --> + <define-tag name="wxlike-lib" rules="exe,lib,dll,module"> + <__setlibname prefix="$(attributes['prefix'])">$(value)</__setlibname> + <sys-lib>$(__temp)</sys-lib> + </define-tag> + + <!-- Sets as output folder for the current target a directory + called "$(value)/$(COMPILER_PREFIX)_lib|dll", just like wxWidgets does. + This makes it possible to keep separated the libraries/exes compiled with + different compilers and with a different value for WX_SHARED. + --> + <define-tag name="wxlike-dirname" rules="lib,dll,exe,module"> + <if cond="FORMAT!='autoconf'"> + <set var="_DIRNAME_SHARED_SUFFIX"> + <if cond="WX_SHARED=='0'">lib</if> + <if cond="WX_SHARED=='1'">dll</if> + </set> + <set var="_DIRNAME"> + $(value)/$(COMPILER_PREFIX)_$(_DIRNAME_SHARED_SUFFIX) + </set> + + <dirname>$(_DIRNAME)</dirname> + + <if cond="FORMAT_SUPPORTS_ACTIONS=='1'"> + <set var="__mkdir_tgt">make_dir_$(id)</set> + + <add-target target="$(__mkdir_tgt)" type="action"/> + <modify-target target="$(__mkdir_tgt)"> + <command cond="TOOLSET=='unix'"> + @mkdir -p $(_DIRNAME) + </command> + <command cond="TOOLSET in ['win32','os2','dos']"> + if not exist $(nativePaths(_DIRNAME)) mkdir $(nativePaths(_DIRNAME)) + </command> + </modify-target> + + <!-- the following code is mostly equivalent to a: + <dependency-of>$(id)</dependency-of> + put into the __mkdir_tgt target, except that it does _prepend_ + the __mkdir_tgt dependency instead of appending it. + + This is required because some compilers (e.g. MSVC) need to store in the + output folder some files (e.g. the PDB file) while compiling and thus + the library output folder must have been created before _any_ source file + is compiled, not just before the library is linked. + --> + <modify-target target="$(id)"> + <set var="__deps" prepend="1"> + $(substitute(__mkdir_tgt, lambda x: ref('__depname', x), 'DEP')) + </set> + </modify-target> + </if> + </if> + <if cond="FORMAT=='autoconf'"> + <set var="_DIRNAME">$(value)</set> + <dirname>$(_DIRNAME)</dirname> + </if> + </define-tag> + + <!-- Adds to the compiler & linker flags the path for the "include" and the + "lib" folders of a library following wxWidgets conventions which is + located in $(value). + --> + <define-tag name="wxlike-paths" rules="exe,lib,dll,module"> + <if cond="FORMAT!='autoconf' and FORMAT!='gnu'"> + <!-- WXLIBPATH is a path like "/lib/vc_lib" + NOTE: even if this template is going to be used for a "lib" + target (which does not uses lib-paths at all), we can still + use the <lib-path> target: it will just be discarded + --> + <lib-path>$(value)$(WXLIBPATH)</lib-path> + + <!-- no special include paths for a lib following wxWidgets naming + conventions --> + <include>$(value)/include</include> + </if> + + <!-- for autoconf format the user should use CPPFLAGS and LDFLAGS to + specify non-system paths since the wx-based library should have + been installed in standard paths + --> + </define-tag> + + + + <!-- UTILITY GLOBAL TAGS --> + <!-- --> + + <!-- Sets the BUILDDIR variable using the same rules used by wxWidgets itself. + This makes it possible to keep separated the object files compiled with + different configuration settings. + --> + <define-global-tag name="set-wxlike-builddir"> + <!-- note that the builddir for autoconf should always be '.' --> + <if cond="FORMAT!='autoconf'"> + <set var="_BUILDDIR_SHARED_SUFFIX"> + <if cond="WX_SHARED=='0'"></if> + <if cond="WX_SHARED=='1'">_dll</if> + </set> + + <set var="BUILDDIR"> + $(COMPILER_PREFIX)$(WX_PORT)$(WXLIBPOSTFIX)$(_BUILDDIR_SHARED_SUFFIX) + </set> + </if> + </define-global-tag> + + <!-- Sets a variable with the name of the 'var' attribute value using the + same rules used for wxWidgets library naming. + E.g. + + <set-wxlike var='MYMODULE_LIBNAME' prefix='mylib'> + mymodule + </set-wxlike> + + This tag also supports a 'cond' attribute making it very powerful + for conditional linking a wx-based library: + + <option name="USE_MYMODULE"> + <values>0,1</values> + </option> + <set-wxlike var='MYMODULE_DEP' + prefix='mylib' + cond="USE_MYMODULE=='1'"> + mymodule + </set-wxlike> + ... + <exe id="myexe"> + <sys-lib>$(MYMODULE_DEP)</sys-lib> + </exe> + --> + <define-global-tag name="set-wxlike"> + <if cond="FORMAT!='autoconf' and FORMAT!='gnu'"> + <if cond="'cond' not in attributes"> + <set var="$(attributes['var'])"> + $(attributes['prefix'])_$(WX_PORT)$(WX_VERSION)$(WXLIBPOSTFIX)_$(value) + </set> + </if> + <if cond="'cond' in attributes"> + <set var="$(attributes['var'])"> + <if cond="$(attributes['cond'])"> + $(attributes['prefix'])_$(WX_PORT)$(WX_VERSION)$(WXLIBPOSTFIX)_$(value) + </if> + </set> + </if> + </if> + + <if cond="FORMAT=='autoconf' or FORMAT=='gnu'"> + <if cond="'cond' not in attributes"> + <set var="$(attributes['var'])"> + $(attributes['prefix'])_$(WX_PORT)$(WXLIBPOSTFIX)_$(value)-$(WX_VERSION_MAJOR).$(WX_VERSION_MINOR) + </set> + </if> + <if cond="'cond' in attributes"> + <set var="$(attributes['var'])"> + <if cond="$(attributes['cond'])"> + $(attributes['prefix'])_$(WX_PORT)$(WXLIBPOSTFIX)_$(value)-$(WX_VERSION_MAJOR).$(WX_VERSION_MINOR) + </if> + </set> + </if> + </if> + </define-global-tag> + + + <include file="wx_xrc.bkl"/> + </makefile> Modified: trunk/mmex/build/bakefiles/presets/wx_unix.bkl =================================================================== --- trunk/mmex/build/bakefiles/presets/wx_unix.bkl 2013-05-28 03:15:07 UTC (rev 4008) +++ trunk/mmex/build/bakefiles/presets/wx_unix.bkl 2013-05-28 03:53:51 UTC (rev 4009) @@ -1,68 +1,207 @@ <?xml version="1.0" ?> -<!-- $Id: wx_unix.bkl 49815 2007-11-10 19:31:25Z KO $ --> +<!-- $Id$ --> <!-- Presents for building wxWidgets applications using Autoconf or GNU toosets. See wx.bkl for platform-independent notes. -Usage: - Options WX_CPPFLAGS, WX_CFLAGS, WX_CXXFLAGS, WX_LIBS are defined. - - Format-specific notes: * autoconf: - Beware that you have to use AM_OPTIONS_WXCONFIG and - AM_PATH_WXCONFIG in your configure.in! + Beware that you have to use WX_CONFIG_OPTIONS and + WX_CONFIG_CHECK in your configure.in to get at least the + WX_CPPFLAGS, WX_CFLAGS, WX_CXXFLAGS, WX_LIBS option values defined. + To detect the WX_* option values typically you also want to use + the WX_STANDARD_OPTIONS, WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS, + WX_CONFIG_CHECK and finally WX_DETECT_STANDARD_OPTION_VALUES macros + (see wxwin.m4 for more info). + --> <makefile> + + <!-- ============================================================== --> <!-- Autoconf --> <!-- ============================================================== --> <if cond="FORMAT=='autoconf'"> - <!-- Autoconf backend is simplicity itself thanks to wx-config... --> <option name="WX_CFLAGS"/> <option name="WX_CXXFLAGS"/> <option name="WX_CPPFLAGS"/> <option name="WX_LIBS"/> <option name="WX_RESCOMP"/> + <option name="WX_VERSION_MAJOR"/> + <option name="WX_VERSION_MINOR"/> + <option name="WX_PORT"/> + + <!-- wxwin.m4 macros will detect all WX_* options defined above --> + + + <!-- VERY IMPORTANT: <wx-lib>base</wx-lib> must be the last wx-lib tag + in all your bakefiles !! + --> + <define-tag name="wx-lib" rules="exe,dll,module"> + <if cond="value=='base'"> + <!-- all wx-dependent libraries should have been already listed + thus we can now add WX_LIBS to the linker line --> + <ldlibs>$(WX_LIBS)</ldlibs> + </if> + <if cond="value not in WX_LIB_LIST.split()"> + <error>Unknown wxWidgets library given in the wx-lib tag</error> + </if> + </define-tag> </if> + <!-- ============================================================== --> <!-- GNU makefiles for Unix --> <!-- ============================================================== --> <if cond="FORMAT=='gnu'"> + + <!-- remove those WX_* vars which were created just to avoid the definition + of the WX_* options in wx.bkl --> + <unset var="WX_SHARED"/> + <unset var="WX_UNICODE"/> + <unset var="WX_PORT"/> + <unset var="WX_VERSION"/> + <set var="WX_CONFIG_DEFAULT" overwrite="0">wx-config</set> <option name="WX_CONFIG"> <default-value>$(WX_CONFIG_DEFAULT)</default-value> <description>Location and arguments of wx-config script</description> </option> - <option name="WX_CFLAGS"> - <default-value>`$(DOLLAR)(WX_CONFIG) --cflags`</default-value> - <description>C flags to use with wxWidgets code</description> + + <set var="WX_PORT_DEFAULT" overwrite="0"> + $(DOLLAR)(shell $(WX_CONFIG) --query-toolkit) + </set> + <option name="WX_PORT"> + <values>gtk1,gtk2,msw,x11,motif,osx_cocoa,osx_carbon,dfb</values> + <default-value force="1">$(WX_PORT_DEFAULT)</default-value> + <description> + Port of the wx library to build against + </description> </option> - <option name="WX_CXXFLAGS"> - <default-value>`$(DOLLAR)(WX_CONFIG) --cxxflags`</default-value> - <description>C++ flags to use with wxWidgets code</description> + + <set var="WX_SHARED_DEFAULT" overwrite="0"> + $(DOLLAR)(shell if test -z `$(WX_CONFIG) --query-linkage`; then echo 1; else echo 0; fi) + </set> + <option name="WX_SHARED"> + <values>0,1</values> + <values-description>Static,DLL</values-description> + <default-value force="1">$(WX_SHARED_DEFAULT)</default-value> + <description> + Use DLL build of wx library to use? + </description> </option> - <option name="WX_CPPFLAGS"> - <default-value>`$(DOLLAR)(WX_CONFIG) --cppflags`</default-value> - <description>C preprocessor flags to use with wxWidgets code</description> + + <set var="WX_UNICODE_DEFAULT" overwrite="0"> + $(DOLLAR)(shell $(WX_CONFIG) --query-chartype | sed 's/unicode/1/;s/ansi/0/') + </set> + <option name="WX_UNICODE"> + <values>0,1</values> + <values-description>ANSI,Unicode</values-description> + <default-value force="1">$(WX_UNICODE_DEFAULT)</default-value> + <description> + Compile Unicode build of wxWidgets? + </description> </option> - <option name="WX_RESCOMP"> - <default-value>`$(DOLLAR)(WX_CONFIG) --rescomp`</default-value> - <description>wxWidgets resource compiler and flags</description> + + <set var="WX_VERSION_DEFAULT" overwrite="0"> + $(DOLLAR)(shell $(WX_CONFIG) --query-version | sed -e 's/\([0-9]*\)\.\([0-9]*\)/\1\2/') + </set> + <option name="WX_VERSION"> + <default-value>$(WX_VERSION_DEFAULT)</default-value> + <description> + Version of the wx library to build against. + </description> </option> - <!-- we need this but the trick used in default-values above + <!-- Get MAJOR and MINOR version numbers --> + <set var="WX_VERSION_MAJOR" make_var="1"> + $(DOLLAR)(shell echo $(DOLLAR)(WX_VERSION) | cut -c1,1) + </set> + <set var="WX_VERSION_MINOR" make_var="1"> + $(DOLLAR)(shell echo $(DOLLAR)(WX_VERSION) | cut -c2,2) + </set> + + + <!-- + Using the GNU format creates a configurable makefile just like + a win32 makefile: i.e. a makefile where you can select the wanted + wxWidgets build using the WX_* options. + + The difference with win32 makefiles is that WX_PORT, WX_UNICODE and + WX_SHARED options have a smart default value which is created using + the installed wx-config or the wx-config given using WX_CONFIG option + --> + <set var="WX_CONFIG_UNICODE_FLAG"> + <if cond="WX_UNICODE=='0'">--unicode=no</if> + <if cond="WX_UNICODE=='1'">--unicode=yes</if> + </set> + <set var="WX_CONFIG_SHARED_FLAG"> + <if cond="WX_SHARED=='0'">--static=yes</if> + <if cond="WX_SHARED=='1'">--static=no</if> + </set> + <set var="WX_CONFIG_PORT_FLAG"> + --toolkit=$(WX_PORT) + </set> + <set var="WX_CONFIG_VERSION_FLAG"> + --version=$(WX_VERSION_MAJOR).$(WX_VERSION_MINOR) + </set> + + <set var="WX_CONFIG_FLAGS" make_var="1"> + $(WX_CONFIG_UNICODE_FLAG) $(WX_CONFIG_SHARED_FLAG) + $(WX_CONFIG_PORT_FLAG) $(WX_CONFIG_VERSION_FLAG) + </set> + + <set var="DEFAULT_CXX">`$(DOLLAR)(WX_CONFIG) --cxx`</set> + <set var="WX_CFLAGS">`$(DOLLAR)(WX_CONFIG) --cflags $(WX_CONFIG_FLAGS)`</set> + <set var="WX_CXXFLAGS">`$(DOLLAR)(WX_CONFIG) --cxxflags $(WX_CONFIG_FLAGS)`</set> + <set var="WX_CPPFLAGS">`$(DOLLAR)(WX_CONFIG) --cppflags $(WX_CONFIG_FLAGS)`</set> + <set var="WX_RESCOMP">`$(DOLLAR)(WX_CONFIG) --rescomp $(WX_CONFIG_FLAGS)`</set> + + <!-- + VERY IMPORTANT: before starting to build all targets of the generated makefile, + we need to check if the selected wxWidgets build exists; we do + that simply creating the following target; if it fails the make + program will halt with the wx-config error message... + --> + <if cond="WX_TEST_FOR_SELECTED_WXBUILD=='1'"> + <action id="test_for_selected_wxbuild"> + <dependency-of>all</dependency-of> + + <!-- Use @ to hide to the user that we're running wx-config... --> + <command>@$(DOLLAR)(WX_CONFIG) $(WX_CONFIG_FLAGS)</command> + </action> + </if> + + <!-- we need these vars but the trick used in the default values above prevents bakefile from detecting it: --> - <set var="FORMAT_OUTPUT_VARIABLES" append="1">WX_CONFIG</set> + <set var="FORMAT_OUTPUT_VARIABLES" append="1">WX_CONFIG WX_VERSION</set> + + + <!-- VERY IMPORTANT: <wx-lib>base</wx-lib> must be the last wx-lib tag + in all your bakefiles !! + --> + <define-tag name="wx-lib" rules="exe,dll,module"> + <if cond="value=='base'"> + <!-- all wx libraries should have been already specified, thus + $(__liblist) should contain the full list of required wxlibs... --> + <set var="__liblist" append="1">base</set> + <ldlibs>`$(WX_CONFIG) $(WX_CONFIG_FLAGS) --libs $(','.join(__liblist.split()))`</ldlibs> + </if> + <if cond="value!='base'"> + <set var="__liblist" append="1">$(value)</set> + </if> + <if cond="value not in WX_LIB_LIST.split()"> + <error>Unknown wxWidgets library given in the wx-lib tag</error> + </if> + </define-tag> </if> <!-- ============================================================== --> @@ -110,27 +249,4 @@ --> </template> - <!-- VERY IMPORTANT: <wx-lib>base</wx-lib> must be the last wx-lib tag - in all your bakefiles !! - --> - <define-tag name="wx-lib" rules="exe,dll,module"> - <if cond="FORMAT=='autoconf' and value=='base'"> - <!-- all wx-dependent libraries should have been already listed - thus we can now add WX_LIBS to the linker line --> - <ldflags>$(WX_LIBS)</ldflags> - </if> - <if cond="FORMAT=='gnu' and value=='base'"> - <!-- all wx libraries should have been already specified, thus - $(__liblist) should contain the full list... --> - <set var="__liblist" append="1">base</set> - <ldflags>`$(WX_CONFIG) --libs $(','.join(__liblist.split()))`</ldflags> - </if> - <if cond="FORMAT=='gnu' and value!='base'"> - <set var="__liblist" append="1">$(value)</set> - </if> - <if cond="value not in ALLLIB_LIST.split()"> - <error>Unknown wxWidgets library given in the wx-lib tag</error> - </if> - </define-tag> - </makefile> Modified: trunk/mmex/build/bakefiles/presets/wx_win32.bkl =================================================================== --- trunk/mmex/build/bakefiles/presets/wx_win32.bkl 2013-05-28 03:15:07 UTC (rev 4008) +++ trunk/mmex/build/bakefiles/presets/wx_win32.bkl 2013-05-28 03:53:51 UTC (rev 4009) @@ -1,5 +1,5 @@ -<?xml version="1.0" ?> -<!-- $Id: wx_win32.bkl 46375 2007-06-08 18:25:40Z KO $ --> +<?xml version="1.0" ?> +<!-- $Id$ --> <!-- Original source: http://wiki.wxwidgets.org/wiki.pl?Bakefile --> <!-- Modified by: Francesco Montorsi <fr...@us...> --> @@ -7,124 +7,73 @@ into Bakefile's presets --> <!-- Creation date: 6/9/2004 --> <!-- Last revision: 22/1/2005 off-CVS --> -<!-- $Id: wx_win32.bkl 46375 2007-06-08 18:25:40Z KO $ --> +<!-- $Id$ --> -<!-- - -FIXME: this template has (at least) the following bugs: - - * it's MSW-only, the port is assumed to be wxMSW unconditionally - - * multiple wx configurations (CFG variable set when building the - library) are not supported - ---> - -<!-- makefile tag signifies the beginning of the bakefile --> <makefile> - <requires version="0.1.5"/> + <!-- --> <!-- OPTIONS --> <!-- --> - <!-- These are essentially the configurations you --> - <!-- want in bakefile. --> - <!-- --> - <!-- In MSVC these are the different build --> - <!-- configurations you can have (in the build menu), --> - <!-- and in autoconf is enabled with enable-xxx=xx. --> - <!-- For other compilers a separate configuration --> - <!-- file is created (such as config.gcc on gcc) --> - <!-- which has several options a user can modify. --> - <!-- --> - <!-- Note that the above only happens if an option --> - <!-- is not constant, i.e. if it cannot be determined --> - <!-- by bakefile itself. --> - <!-- Presets for limited dmars make.exe format: --> - <if cond="FORMAT=='dmars'"> - <set var="WX_UNICODE">0</set> - <set var="WX_DEBUG">1</set> - <set var="WX_SHARED">0</set> - <set var="WX_PYTHON">0</set> - </if> - - + <set var="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_NORMAL"> + <!-- 'NORMAL' here refers to the fact that the formats for which + FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_NORMAL==1 only need + additional compiler and/or linker flags (see e.g. WXMACHINE_FLAG) + --> + <if cond="FORMAT in ['msvc']">1</if> + <if cond="FORMAT not in ['msvc']">0</if> + </set> + <set var="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_VIA_MSVS_PLATFORMS"> + <!-- the formats for which FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_VIA_MSVS_PLATFORMS==1 + need special handling: see the docs of the MSVS_PLATFORMS variable in Bakefile docs. + --> + <if cond="FORMAT in ['msvs2005prj','msvs2008prj']">1</if> + <if cond="FORMAT not in ['msvs2005prj','msvs2008prj']">0</if> + </set> + <set var="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES"> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_NORMAL=='1'">1</if> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_VIA_MSVS_PLATFORMS=='1'">1</if> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_NORMAL=='0' and FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_VIA_MSVS_PLATFORMS=='0'">0</if> + </set> + <!-- This is a standard option that determines --> - <!-- whether the user wants to build this library as --> - <!-- a dll or as a static library. --> - <if cond="not isdefined('WX_SHARED')"> - <set var="WX_SHARED_DEFAULT" overwrite="0">0</set> - <option name="WX_SHARED"> - <values>0,1</values> - <values-description>,DLL</values-description> - <default-value>$(WX_SHARED_DEFAULT)</default-value> + <!-- the architecture for which the lib/exe/dll later --> + <!-- declared are meant. --> + <if cond="not isdefined('TARGET_CPU') and FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_NORMAL=='1'"> + <set var="TARGET_CPU_DEFAULT" overwrite="0">X86</set> + <option name="TARGET_CPU"> + <values>X86,AMD64,IA64</values> + <values-description>i386-compatible,AMD 64 bit,Itanium 64 bit</values-description> + <default-value>$(TARGET_CPU_DEFAULT)</default-value> <description> - Use DLL build of wx library to use? + Architecture of the CPU for which to build the executables and libraries </description> </option> </if> - - <!-- Configuration for building the bakefile with --> - <!-- unicode strings or not (unicode or ansi). --> - <if cond="not isdefined('WX_UNICODE')"> - <set var="WX_UNICODE_DEFAULT" overwrite="0">0</set> - <option name="WX_UNICODE"> - <values>0,1</values> - <values-description>,Unicode</values-description> - <default-value>$(WX_UNICODE_DEFAULT)</default-value> - <description> - Compile Unicode build of wxWidgets? - </description> - </option> + <if cond="not isdefined('TARGET_CPU') and FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_VIA_MSVS_PLATFORMS=='1'"> + <!-- defining TARGET_CPU also for the formats using the MSVS_PLATFORM variable allows to write + easier tests in user bakefiles; e.g.: + + <set var="MY_ARCH_DEPENDENT_VARIABLE"> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES=='0'">value1</if> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES=='1' and TARGET_CPU=='X86'">value2</if> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES=='1' and TARGET_CPU=='AMD64'">value3</if> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES=='1' and TARGET_CPU=='IA64'">value4</if> + </set> + --> + <set var="TARGET_CPU"> + <if cond="MSVS_PLATFORM=='win32'">X86</if> + <if cond="MSVS_PLATFORM=='win64'">AMD64</if> + <if cond="MSVS_PLATFORM=='ia64'">IA64</if> + <!-- MSVS_PLATFORM currently does not support ia64 but this line is still needed by bakefile + to correctly set the TARGET_CPU variable --> + </set> </if> - <if cond="not isdefined('WX_DEBUG')"> - <set var="WX_DEBUG_DEFAULT" overwrite="0">1</set> - <option name="WX_DEBUG"> - <values>0,1</values> - <values-description>Release,Debug</values-description> - <default-value>$(WX_DEBUG_DEFAULT)</default-value> - <description> - Use debug build of wxWidgets (define __WXDEBUG__)? - </description> - </option> - </if> - <if cond="not isdefined('WX_VERSION')"> - <set var="WX_VERSION_DEFAULT" overwrite="0">29</set> - <option name="WX_VERSION"> - <default-value>$(WX_VERSION_DEFAULT)</default-value> - <description> - Version of the wx library to build against. - </description> - </option> - </if> - <if cond="not isdefined('WX_MONOLITHIC')"> - <set var="WX_MONOLITHIC_DEFAULT" overwrite="0">0</set> - <option name="WX_MONOLITHIC"> - <values>0,1</values> - <values-description>Multilib,Monolithic</values-description> - <default-value>$(WX_MONOLITHIC_DEFAULT)</default-value> - <description> - Use monolithic build of wxWidgets? - </description> - </option> - </if> - - <!-- set this to 1 to use specific settings for wxPython --> - <if cond="not isdefined('WX_PYTHON')"> - <option name="WX_PYTHON" category="path"> - <values>0,1</values> - <default-value>0</default-value> - <description> - Whether or not we're building against wxPython libraries. - </description> - </option> - </if> - <!-- HELPER VARIABLES --> <!-- --> @@ -140,41 +89,44 @@ <!-- The debug define we need with win32 compilers --> <!-- (on Linux, the wx-config program is used). --> <set var="WXDEBUG_DEFINE"> - <if cond="WX_PYTHON=='1'">__WXDEBUG__</if> - <if cond="WX_PYTHON=='0' and WX_DEBUG=='1'">__WXDEBUG__</if> + <if cond="WX_DEBUG=='1'">__WXDEBUG__</if> </set> <!-- These are handy ways of dealing with the --> <!-- extensions in the library names of the --> <!-- wxWindows library. --> - <set var="WXLIBPOSTFIX"> - <if cond="WX_PYTHON=='1' and WX_UNICODE=='1'">uh</if> - <if cond="WX_PYTHON=='1' and WX_UNICODE=='0'">h</if> - <if cond="WX_PYTHON=='0' and WX_DEBUG=='1' and WX_UNICODE=='1'">ud</if> - <if cond="WX_PYTHON=='0' and WX_DEBUG=='1' and WX_UNICODE=='0'">d</if> - <if cond="WX_PYTHON=='0' and WX_DEBUG=='0' and WX_UNICODE=='1'">u</if> - </set> <set var="WX3RDPARTYLIBPOSTFIX"> - <if cond="WX_PYTHON==0 and WX_DEBUG=='1'">d</if> - <if cond="WX_PYTHON==1">h</if> + <if cond="WX_DEBUG=='1'">d</if> </set> <set var="WXCPU"> <if cond="FORMAT=='msevc4prj'">_$(CPU)</if> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES=='1' and TARGET_CPU=='AMD64'">_x64</if> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES=='1' and TARGET_CPU=='IA64'">_ia64</if> </set> - + + <set var="WXMACHINE_FLAG"> + <!-- add the /MACHINE linker flag to formats with "normal" multiple-arch support when building in 64bit mode + (formats using the MSVS_PLATFORM variable don't need the /MACHINE linker flag!): --> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_NORMAL=='1' and TARGET_CPU=='AMD64'">/MACHINE:AMD64</if> + <if cond="FORMAT_SUPPORTS_MULTIPLE_ARCHITECTURES_NORMAL=='1' and TARGET_CPU=='IA64'">/MACHINE:IA64</if> + </set> + <set var="WXLIBPATH"> - <if cond="WX_SHARED=='0'">$(DIRSEP)lib$(DIRSEP)$(COMPILER)$(WXCPU)_lib</if> - <if cond="WX_SHARED=='1'">$(DIRSEP)lib$(DIRSEP)$(COMPILER)$(WXCPU)_dll</if> + <if cond="WX_SHARED=='0'">$(DIRSEP)lib$(DIRSEP)$(COMPILER_PREFIX)$(WXCPU)_lib</if> + <if cond="WX_SHARED=='1'">$(DIRSEP)lib$(DIRSEP)$(COMPILER_PREFIX)$(WXCPU)_dll</if> </set> - - <set var="WXPORT"> + + <!-- under Unix this is an option (detected at configure-time); + under Windows this is not an user option! --> + <set var="WX_PORT"> <if cond="FORMAT=='msevc4prj'">wince</if> <if cond="FORMAT!='msevc4prj'">msw</if> </set> - <set var="WXLIBINCLUDE">$(WXLIBPATH)$(DIRSEP)$(WXPORT)$(WXLIBPOSTFIX)</set> + <set var="WXLIBINCLUDE">$(WXLIBPATH)$(DIRSEP)$(WX_PORT)$(WXLIBPOSTFIX)</set> + <!-- All the possible mixes for the wx library names --> <set var="WXLIB_BASE_NAME"> <if cond="WX_MONOLITHIC=='0'">wxbase$(WX_VERSION)$(WXLIBPOSTFIX)</if> @@ -185,57 +137,49 @@ WX_MONOLITHIC=1, then the base library is translated to the monolithic library --> - <if cond="WX_MONOLITHIC=='1'">wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)</if> + <if cond="WX_MONOLITHIC=='1'">wx$(WX_PORT)$(WX_VERSION)$(WXLIBPOSTFIX)</if> </set> + <!-- Libraries whose name is prefixed with 'wxbase' --> - <set var="WXLIB_NET_NAME"> - <if cond="WX_MONOLITHIC=='0'">wxbase$(WX_VERSION)$(WXLIBPOSTFIX)_net</if> + <define-global-tag name="define-wxbase-lib-name"> + <set var="WXLIB_$(value.upper())_NAME"> + <if cond="WX_MONOLITHIC=='0'"> + wxbase$(WX_VERSION)$(WXLIBPOSTFIX)_$(value) + </if> </set> - <set var="WXLIB_XML_NAME"> - <if cond="WX_MONOLITHIC=='0'">wxbase$(WX_VERSION)$(WXLIBPOSTFIX)_xml</if> - </set> - <set var="WXLIB_ODBC_NAME"> - <if cond="WX_MONOLITHIC=='0'">wxbase$(WX_VERSION)$(WXLIBPOSTFIX)_odbc</if> - </set> + </define-global-tag> + <define-wxbase-lib-name>net</define-wxbase-lib-name> + <define-wxbase-lib-name>xml</define-wxbase-lib-name> + + <!-- Libraries whose name is prefixed with 'wx' only --> - <set var="WXLIB_CORE_NAME"> - <if cond="WX_MONOLITHIC=='0'">wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)_core</if> - </set> - <set var="WXLIB_MEDIA_NAME"> - <if cond="WX_MONOLITHIC=='0'">wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)_media</if> - </set> - <set var="WXLIB_XRC_NAME"> - <if cond="WX_MONOLITHIC=='0'">wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)_xrc</if> - </set> - <set var="WXLIB_HTML_NAME"> - <if cond="WX_MONOLITHIC=='0'">wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)_html</if> - </set> - <set var="WXLIB_ADV_NAME"> - <if cond="WX_MONOLITHIC=='0'">wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)_adv</if> - </set> - <set var="WXLIB_QA_NAME"> - <if cond="WX_MONOLITHIC=='0'">wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)_qa</if> - </set> - <set var="WXLIB_DBGRID_NAME"> - <if cond="WX_MONOLITHIC=='0'">wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)_dbgrid</if> - </set> - <set var="WXLIB_GL_NAME"> - <if cond="WX_MONOLITHIC=='0'">wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)_gl</if> - </set> - <set var="WXLIB_AUI_NAME"> - <if cond="WX_MONOLITHIC=='0'">wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)_aui</if> - </set> - <set var="WXLIB_RICHTEXT_NAME"> - <if cond="WX_MONOLITHIC=='0'">wx$(WXPORT)$(WX_VERSION)($WXLIBPOSTFIX)_richtext</if> - </set> + <define-global-tag name="define-wxlib-name"> + <set var="WXLIB_$(value.upper())_NAME"> + <if cond="WX_MONOLITHIC=='0'"> + wx$(WX_PORT)$(WX_VERSION)$(WXLIBPOSTFIX)_$(value) + </if> + </set> + </define-global-tag> + <define-wxlib-name>core</define-wxlib-name> + <define-wxlib-name>media</define-wxlib-name> + <define-wxlib-name>xrc</define-wxlib-name> + <define-wxlib-name>html</define-wxlib-name> + <define-wxlib-name>adv</define-wxlib-name> + <define-wxlib-name>qa</define-wxlib-name> + <define-wxlib-name>aui</define-wxlib-name> + <define-wxlib-name>ribbon</define-wxlib-name> + <define-wxlib-name>propgrid</define-wxlib-name> + <define-wxlib-name>stc</define-wxlib-name> + <define-wxlib-name>richtext</define-wxlib-name> + <define-wxlib-name>webview</define-wxlib-name> + <!-- NOTE: The GL lib is not part of the monolithic build; treat it as a contrib! --> - <!-- WX TEMPLATE --> <!-- --> <!-- --> @@ -261,25 +205,31 @@ <if cond="value=='net'"><sys-lib>$(WXLIB_NET_NAME)</sys-lib></if> <if cond="value=='xml'"><sys-lib>$(WXLIB_XML_NAME)</sys-lib></if> - <if cond="value=='odbc'"><sys-lib>$(WXLIB_ODBC_NAME)</sys-lib></if> <if cond="value=='media'"><sys-lib>$(WXLIB_MEDIA_NAME)</sys-lib></if> <if cond="value=='xrc'"><sys-lib>$(WXLIB_XRC_NAME)</sys-lib></if> <if cond="value=='html'"><sys-lib>$(WXLIB_HTML_NAME)</sys-lib></if> <if cond="value=='adv'"><sys-lib>$(WXLIB_ADV_NAME)</sys-lib></if> - <if cond="value=='gl'"><sys-lib>$(WXLIB_GL_NAME)</sys-lib></if> - <if cond="value=='dbgrid'"><sys-lib>$(WXLIB_DBGRID_NAME)</sys-lib></if> <if cond="value=='qa'"><sys-lib>$(WXLIB_QA_NAME)</sys-lib></if> <if cond="value=='aui'"><sys-lib>$(WXLIB_AUI_NAME)</sys-lib></if> + <if cond="value=='ribbon'"><sys-lib>$(WXLIB_RIBBON_NAME)</sys-lib></if> + <if cond="value=='propgrid'"><sys-lib>$(WXLIB_PROPGRID_NAME)</sys-lib></if> <if cond="value=='richtext'"><sys-lib>$(WXLIB_RICHTEXT_NAME)</sys-lib></if> + <if cond="value=='webview'"><sys-lib>$(WXLIB_WEBVIEW_NAME)</sys-lib></if> - <!-- wx-lib can be used also to link against contrib libraries - (which always have the same name, regardless of WX_MONOLITHIC value) --> - <if cond="value in CONTRIBLIB_LIST.split()"> - <sys-lib>wx$(WXPORT)$(WX_VERSION)$(WXLIBPOSTFIX)_$(value)</sys-lib> + <!-- The GL lib isn't part of the monolithic build, treat it as a contrib: --> + <if cond="value=='gl'"> + <sys-lib>wx$(WX_PORT)$(WX_VERSION)$(WXLIBPOSTFIX)_$(value)</sys-lib> </if> - <if cond="value not in ALLLIB_LIST.split()"> + <if cond="value=='stc'"> + <!-- wxSTC requires also the basic scintilla library + which is built as a separate 3rd party library --> + <sys-lib>$(WXLIB_STC_NAME)</sys-lib> + <sys-lib>wxscintilla$(WX3RDPARTYLIBPOSTFIX)</sys-lib> + </if> + + <if cond="value not in WX_LIB_LIST.split()"> <error>Unknown wxWidgets library given in the wx-lib tag</error> </if> </define-tag> @@ -301,12 +251,16 @@ <ldflags>-mthreads</ldflags> </if> + <define>$(substituteFromDict(WX_SHARED,{'1':'WXUSINGDLL','0':''}))</define> + <define>$(WXUNICODE_DEFINE)</define> <define>$(WXDEBUG_DEFINE)</define> <define>__WXMSW__</define> - <include>$(WX_DIR)$(WXLIBINCLUDE)</include> - <include>$(WX_DIR)/include</include> + <if cond="FORMAT!='xcode2'"> + <include>$(WX_DIR)$(WXLIBINCLUDE)</include> + <include>$(WX_DIR)/include</include> + </if> </template> @@ -329,7 +283,6 @@ <!-- If on borland, we don't need to do much --> <if cond="FORMAT=='borland'"> <sys-lib>ole2w32</sys-lib> - <sys-lib>odbc32</sys-lib> </if> <!-- Non-borland, on the other hand... --> @@ -348,7 +301,6 @@ <sys-lib>rpcrt4</sys-lib> <sys-lib>advapi32</sys-lib> <sys-lib>wsock32</sys-lib> - <sys-lib>odbc32</sys-lib> </if> <!-- Libs common to both borland and MSVC --> @@ -359,12 +311,44 @@ <!-- template for wx executables/dlls: --> <template id="wx" template="wx-lib"> - <lib-path>$(WX_DIR)$(WXLIBPATH)</lib-path> + <if cond="FORMAT!='xcode2'"> + <lib-path>$(WX_DIR)$(WXLIBPATH)</lib-path> + </if> + <ldflags>$(WXMACHINE_FLAG)</ldflags> + <!-- wx libs must come before 3rd party and sys libs, this is the place where the hack explained above is carried on: --> <__wx-libs-point/> <__wx-syslibs/> </template> + <if cond="FORMAT_SUPPORTS_ACTIONS=='1' and WX_TEST_FOR_SELECTED_WXBUILD=='1'"> + + <!-- + VERY IMPORTANT: before starting to build all targets of the generated makefile, + we need to check if the selected wxWidgets build exists; we do + that simply creating the following target; if it fails the make + program will halt printing the following nice error message... + (much better than the 'could not find wx/*.h file') + --> + <action id="test_for_selected_wxbuild"> + <dependency-of>all</dependency-of> + + <!-- the @ is to hide these actions from the user --> + <command> + @if not exist $(WX_DIR)$(WXLIBINCLUDE)$(DIRSEP)wx$(DIRSEP)setup.h \ + echo ---------------------------------------------------------------------------- + @if not exist $(WX_DIR)$(WXLIBINCLUDE)$(DIRSEP)wx$(DIRSEP)setup.h \ + echo The selected wxWidgets build is not available! + @if not exist $(WX_DIR)$(WXLIBINCLUDE)$(DIRSEP)wx$(DIRSEP)setup.h \ + echo Please use the options prefixed with WX_ to select another wxWidgets build. + @if not exist $(WX_DIR)$(WXLIBINCLUDE)$(DIRSEP)wx$(DIRSEP)setup.h \ + echo ---------------------------------------------------------------------------- + @if not exist $(WX_DIR)$(WXLIBINCLUDE)$(DIRSEP)wx$(DIRSEP)setup.h \ + exit 1 + </command> + </action> + </if> + </makefile> Modified: trunk/mmex/build/msw/config.gcc =================================================================== --- trunk/mmex/build/msw/config.gcc 2013-05-28 03:15:07 UTC (rev 4008) +++ trunk/mmex/build/msw/config.gcc 2013-05-28 03:53:51 UTC (rev 4009) @@ -40,16 +40,13 @@ # Standard linker flags LDFLAGS ?= -# The directory where wxWidgets library is installed -WX_DIR ?= $(WXWIN) - -# Use DLL build of wx library to use? [0,1] +# Use DLL build of wx library? [0,1] WX_SHARED ?= 0 -# Compile Unicode build of wxWidgets? [0,1] +# Use Unicode build of wxWidgets? [0,1] WX_UNICODE ?= 1 -# Use debug build of wxWidgets (define __WXDEBUG__)? [0,1] +# Use debug build of wxWidgets (linked with debug CRT)? [0,1] WX_DEBUG ?= 0 # Version of the wx library to build against. @@ -58,12 +55,129 @@ # Use monolithic build of wxWidgets? [0,1] WX_MONOLITHIC ?= 1 -# Whether or not we're building against wxPython libraries. [0,1] -WX_PYTHON ?= 0 +# The directory where wxWidgets library is installed +WX_DIR ?= $(WXWIN) -# The target processor architecture must be specified when it is not X86. -# This does not affect the compiler output, so you still need to make sure -# your environment is set up appropriately with the correct compiler in the -# PATH. Accepted values: AMD64, IA64. -TARGET_CPU ?= $(CPU) +# Path to find the wxrc executable. +WXRC ?= wxrc +# The C preprocessor +CPP ?= $(CC) -E + +# What type of library to build? [0,1] +SHARED ?= 0 + +# Used toolkit [MSW,GTK] +TOOLKIT ?= MSW + +# GTK+ toolkit version [,2] +TOOLKIT_VERSION ?= + +# Build wxUniversal instead of native port? [0,1] +WXUNIV ?= 0 + +# Compile Unicode build of wxWidgets? [0,1] +UNICODE ?= 1 + +# Use MSLU library when building Unicode version. [0,1] +MSLU ?= 0 + +# Type of compiled binaries [debug,release] +BUILD ?= debug + +# Should debugging info be included in the executables? The default value +# "default" means that debug info will be included if BUILD=debug +# and not included if BUILD=release. [0,1,default] +DEBUG_INFO ?= default + +# Value of wxDEBUG_LEVEL. The default value is the same as 1 and means that all +# but expensive a... [truncated message content] |
From: <gua...@us...> - 2013-05-28 09:10:57
|
Revision: 4016 http://sourceforge.net/p/moneymanagerex/code/4016 Author: guanlisheng Date: 2013-05-28 09:10:54 +0000 (Tue, 28 May 2013) Log Message: ----------- update bakefile Modified Paths: -------------- trunk/mmex/build/bakefiles/Bakefiles.bkgen Added Paths: ----------- trunk/mmex/build/bakefiles/mmex_tests.bkl Removed Paths: ------------- trunk/mmex/src/tests/mmex_tests.bkl Modified: trunk/mmex/build/bakefiles/Bakefiles.bkgen =================================================================== --- trunk/mmex/build/bakefiles/Bakefiles.bkgen 2013-05-28 09:04:08 UTC (rev 4015) +++ trunk/mmex/build/bakefiles/Bakefiles.bkgen 2013-05-28 09:10:54 UTC (rev 4016) @@ -54,13 +54,13 @@ -o../msw/mmex.sln </add-flags> - <add-flags files="../../src/tests/*.bkl" formats="mingw"> + <add-flags files="mmex_tests.bkl" formats="mingw"> -o../msw/tests/makefile.gcc </add-flags> - <add-flags files="../../src/tests/*.bkl" formats="msvc"> + <add-flags files="mmex_tests.bkl" formats="msvc"> -o../msw/tests/makefile.vc </add-flags> - <add-flags files="../../src/tests/*.bkl" formats="msvs2003prj"> + <add-flags files="mmex_tests.bkl" formats="msvs2003prj"> -o../msw/tests/mmex_tests.sln </add-flags> @@ -81,14 +81,14 @@ <add-flags files="mmex.bkl" formats="mingw"> -DOPTIONS_FILE=config.gcc </add-flags> - <add-flags files="../../src/tests/*.bkl" formats="mingw"> + <add-flags files="mmex_tests.bkl" formats="mingw"> -DOPTIONS_FILE=../config.gcc -DWRITE_OPTIONS_FILE=0 </add-flags> <add-flags files="mmex.bkl" formats="msvc"> -DOPTIONS_FILE=config.vc </add-flags> - <add-flags files="../../src/tests/*.bkl" formats="msvc"> + <add-flags files="mmex_tests.bkl" formats="msvc"> -DOPTIONS_FILE=../config.vc -DWRITE_OPTIONS_FILE=0 </add-flags> Copied: trunk/mmex/build/bakefiles/mmex_tests.bkl (from rev 4015, trunk/mmex/src/tests/mmex_tests.bkl) =================================================================== --- trunk/mmex/build/bakefiles/mmex_tests.bkl (rev 0) +++ trunk/mmex/build/bakefiles/mmex_tests.bkl 2013-05-28 09:10:54 UTC (rev 4016) @@ -0,0 +1,101 @@ +<?xml version="1.0" ?> + +<!-- + MMEX build scripts. + Copyright (C) 2009 VaDiM. + + MMEX Unit Tests application. +--> + +<makefile> + + <!-- Default root of sources is dir where output script will be created. + autoconf generates Makefile in trunk/mmex/src/tests but others in trunk/mmex/build/msw/tests. + --> + + <if cond="FORMAT=='autoconf'"> + <set-srcdir>../..</set-srcdir> + </if> + + <if cond="FORMAT!='autoconf'"> + <set-srcdir>../../..</set-srcdir> + </if> + + + <include file="../../build/bakefiles/common.bkl"/> + <include file="../../build/bakefiles/UnitTest++.bkl"/> + + + <!-- unit tests console application --> + + <exe id="mmex_tests" template="mmex_common"> + + <app-type>console</app-type> + <library>UnitTestPP</library> + + <include>$(SRCDIR)/src</include> + <include>$(SRCDIR)/lib/UnitTest++</include> + + + <!-- IMPLEMENT_APP(mmGUIApp) in mmex.cpp defines main() on Unixes, see wx\app.h. + But mmex_tests.cpp also defines main(). + --> + + <!-- relative to trunk/mmex --> + + <set var="SRC">src/tests</set> + + <headers>$(fileList(SRC + '/*.h'))</headers> + <sources>$(fileList(SRC + '/*.cpp'))</sources> + + <win32-res>$(SRC)/mmex_tests.rc</win32-res> + + </exe> + + + <!-- + make check + All formats expect MS VisualStudio projects. + --> + + <action id="check" cond="not FORMAT.endswith('prj')"> + + <depends>all</depends> + <is-phony>on</is-phony> + + <!-- "&&" is "&&" in XML --> + + <set var="COPY"> + <if cond="TOOLSET=='win32'">copy /Y</if> + <if cond="TOOLSET=='unix'">cp</if> + </set> + + <set var="MKDIR"> + <if cond="TOOLSET=='win32'">mkdir</if> + <if cond="TOOLSET=='unix'">mkdir -p</if> + </set> + + <set var="RES_DIR"> + <if cond="FORMAT!='autoconf'">$(BUILDDIR)/res</if> + <if cond="FORMAT=='autoconf'">$(BUILDDIR)/share/mmex/res</if> + </set> + + <command> + -$(MKDIR) $(nativePaths(RES_DIR)) + $(COPY) $(nativePaths(SRCDIR + '/resources/currency_seed.csv')) $(nativePaths(RES_DIR)) + </command> + + <command cond="FORMAT!='autoconf'"> + $(nativePaths(BUILDDIR + '/mmex_tests' + EXEEXT)) + </command> + + <command cond="FORMAT=='autoconf'"> + ./mmex_tests + </command> + + <clean-files>$(RES_DIR)/currency_seed.csv</clean-files> + + </action> + + +</makefile> Deleted: trunk/mmex/src/tests/mmex_tests.bkl =================================================================== --- trunk/mmex/src/tests/mmex_tests.bkl 2013-05-28 09:04:08 UTC (rev 4015) +++ trunk/mmex/src/tests/mmex_tests.bkl 2013-05-28 09:10:54 UTC (rev 4016) @@ -1,101 +0,0 @@ -<?xml version="1.0" ?> - -<!-- - MMEX build scripts. - Copyright (C) 2009 VaDiM. - - MMEX Unit Tests application. ---> - -<makefile> - - <!-- Default root of sources is dir where output script will be created. - autoconf generates Makefile in trunk/mmex/src/tests but others in trunk/mmex/build/msw/tests. - --> - - <if cond="FORMAT=='autoconf'"> - <set-srcdir>../..</set-srcdir> - </if> - - <if cond="FORMAT!='autoconf'"> - <set-srcdir>../../..</set-srcdir> - </if> - - - <include file="../../build/bakefiles/common.bkl"/> - <include file="../../build/bakefiles/UnitTest++.bkl"/> - - - <!-- unit tests console application --> - - <exe id="mmex_tests" template="mmex_common"> - - <app-type>console</app-type> - <library>UnitTestPP</library> - - <include>$(SRCDIR)/src</include> - <include>$(SRCDIR)/lib/UnitTest++</include> - - - <!-- IMPLEMENT_APP(mmGUIApp) in mmex.cpp defines main() on Unixes, see wx\app.h. - But mmex_tests.cpp also defines main(). - --> - - <!-- relative to trunk/mmex --> - - <set var="SRC">src/tests</set> - - <headers>$(fileList(SRC + '/*.h'))</headers> - <sources>$(fileList(SRC + '/*.cpp'))</sources> - - <win32-res>$(SRC)/mmex_tests.rc</win32-res> - - </exe> - - - <!-- - make check - All formats expect MS VisualStudio projects. - --> - - <action id="check" cond="not FORMAT.endswith('prj')"> - - <depends>all</depends> - <is-phony>on</is-phony> - - <!-- "&&" is "&&" in XML --> - - <set var="COPY"> - <if cond="TOOLSET=='win32'">copy /Y</if> - <if cond="TOOLSET=='unix'">cp</if> - </set> - - <set var="MKDIR"> - <if cond="TOOLSET=='win32'">mkdir</if> - <if cond="TOOLSET=='unix'">mkdir -p</if> - </set> - - <set var="RES_DIR"> - <if cond="FORMAT!='autoconf'">$(BUILDDIR)/res</if> - <if cond="FORMAT=='autoconf'">$(BUILDDIR)/share/mmex/res</if> - </set> - - <command> - -$(MKDIR) $(nativePaths(RES_DIR)) - $(COPY) $(nativePaths(SRCDIR + '/resources/currency_seed.csv')) $(nativePaths(RES_DIR)) - </command> - - <command cond="FORMAT!='autoconf'"> - $(nativePaths(BUILDDIR + '/mmex_tests' + EXEEXT)) - </command> - - <command cond="FORMAT=='autoconf'"> - ./mmex_tests - </command> - - <clean-files>$(RES_DIR)/currency_seed.csv</clean-files> - - </action> - - -</makefile> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <gua...@us...> - 2013-06-05 14:47:08
|
Revision: 4034 http://sourceforge.net/p/moneymanagerex/code/4034 Author: guanlisheng Date: 2013-06-05 14:47:05 +0000 (Wed, 05 Jun 2013) Log Message: ----------- include cajun Modified Paths: -------------- trunk/mmex/Makefile.in trunk/mmex/build/bakefiles/common.bkl trunk/mmex/build/msw/makefile.gcc trunk/mmex/build/msw/makefile.vc Added Paths: ----------- trunk/mmex/lib/cajun/ trunk/mmex/lib/cajun/Makefile trunk/mmex/lib/cajun/Readme.txt trunk/mmex/lib/cajun/ReleaseNotes.txt trunk/mmex/lib/cajun/json/ trunk/mmex/lib/cajun/json/elements.h trunk/mmex/lib/cajun/json/elements.inl trunk/mmex/lib/cajun/json/reader.h trunk/mmex/lib/cajun/json/reader.inl trunk/mmex/lib/cajun/json/visitor.h trunk/mmex/lib/cajun/json/writer.h trunk/mmex/lib/cajun/json/writer.inl trunk/mmex/lib/cajun/test.cpp trunk/mmex/lib/cajun/test8.vcproj trunk/mmex/lib/cajun/test9.vcproj Modified: trunk/mmex/Makefile.in =================================================================== --- trunk/mmex/Makefile.in 2013-06-05 07:11:11 UTC (rev 4033) +++ trunk/mmex/Makefile.in 2013-06-05 14:47:05 UTC (rev 4034) @@ -89,8 +89,8 @@ lua_lvm.o \ lua_lzio.o MMEX_CXXFLAGS = -I$(srcdir)/lib/sqlite -I$(srcdir)/lib/wxsqlite \ - -I$(srcdir)/lib/lua/src -DNOPCH $(WX_CXXFLAGS) $(PIC_FLAG) $(CPPFLAGS) \ - $(CXXFLAGS) + -I$(srcdir)/lib/lua/src -I$(srcdir)/lib -DNOPCH $(WX_CXXFLAGS) $(PIC_FLAG) \ + $(CPPFLAGS) $(CXXFLAGS) MMEX_OBJECTS = \ mmex_aboutdialog.o \ mmex_appstartdialog.o \ @@ -667,7 +667,7 @@ $(CXXC) -c -o $@ $(MMEX_CXXFLAGS) $(srcdir)/src/unix/platfdep.cpp mmex_resources_mmex_rc.o: $(srcdir)/resources/mmex.rc - $(WX_RESCOMP) -i$< -o$@ --include-dir $(srcdir)/lib/sqlite --include-dir $(srcdir)/lib/wxsqlite --include-dir $(srcdir)/lib/lua/src --define NOPCH + $(WX_RESCOMP) -i$< -o$@ --include-dir $(srcdir)/lib/sqlite --include-dir $(srcdir)/lib/wxsqlite --include-dir $(srcdir)/lib/lua/src --include-dir $(srcdir)/lib --define NOPCH # Include dependency info, if present: Modified: trunk/mmex/build/bakefiles/common.bkl =================================================================== --- trunk/mmex/build/bakefiles/common.bkl 2013-06-05 07:11:11 UTC (rev 4033) +++ trunk/mmex/build/bakefiles/common.bkl 2013-06-05 14:47:05 UTC (rev 4034) @@ -169,6 +169,7 @@ <include>$(SRCDIR)/lib/sqlite</include> <include>$(SRCDIR)/lib/wxsqlite</include> <include>$(SRCDIR)/lib/lua/src</include> + <include>$(SRCDIR)/lib</include> <!-- disable precompiled headers for wxWidgets --> <define>NOPCH</define> Modified: trunk/mmex/build/msw/makefile.gcc =================================================================== --- trunk/mmex/build/msw/makefile.gcc 2013-06-05 07:11:11 UTC (rev 4033) +++ trunk/mmex/build/msw/makefile.gcc 2013-06-05 14:47:05 UTC (rev 4034) @@ -90,8 +90,8 @@ $(__WXDEBUG_DEFINE_p) -D__WXMSW__ \ -I$(WX_DIR)$(WXLIBPATH)\msw$(WXLIBPOSTFIX) -I$(WX_DIR)\include -mthreads -W \ -Wall $(__DEBUGINFO) $(__OPTIMIZEFLAG) $(__DEBUG_DEFINE_p) \ - -I..\..\lib\sqlite -I..\..\lib\wxsqlite -I..\..\lib\lua\src -DNOPCH \ - $(CPPFLAGS) $(CXXFLAGS) + -I..\..\lib\sqlite -I..\..\lib\wxsqlite -I..\..\lib\lua\src -I..\..\lib \ + -DNOPCH $(CPPFLAGS) $(CXXFLAGS) MMEX_OBJECTS = \ mmex_aboutdialog.o \ mmex_appstartdialog.o \ @@ -762,7 +762,7 @@ $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< mmex_resources_mmex_rc.o: ../../resources/mmex.rc - windres --use-temp-file -i$< -o$@ --define HAVE_W32API_H $(____WX_SHARED_26_p_1) $(__WXUNICODE_DEFINE_p_2) $(__WXDEBUG_DEFINE_p_2) --define __WXMSW__ --include-dir $(WX_DIR)$(WXLIBPATH)\msw$(WXLIBPOSTFIX) --include-dir $(WX_DIR)/include $(__DEBUG_DEFINE_p_4) --include-dir ../../lib/sqlite --include-dir ../../lib/wxsqlite --include-dir ../../lib/lua/src --define NOPCH + windres --use-temp-file -i$< -o$@ --define HAVE_W32API_H $(____WX_SHARED_26_p_1) $(__WXUNICODE_DEFINE_p_2) $(__WXDEBUG_DEFINE_p_2) --define __WXMSW__ --include-dir $(WX_DIR)$(WXLIBPATH)\msw$(WXLIBPOSTFIX) --include-dir $(WX_DIR)/include $(__DEBUG_DEFINE_p_4) --include-dir ../../lib/sqlite --include-dir ../../lib/wxsqlite --include-dir ../../lib/lua/src --include-dir ../../lib --define NOPCH .PHONY: all install uninstall clean install_mmex uninstall_mmex po setup check Modified: trunk/mmex/build/msw/makefile.vc =================================================================== --- trunk/mmex/build/msw/makefile.vc 2013-06-05 07:11:11 UTC (rev 4033) +++ trunk/mmex/build/msw/makefile.vc 2013-06-05 14:47:05 UTC (rev 4034) @@ -91,8 +91,8 @@ /I$(WX_DIR)$(__WXLIBPATH_FILENAMES_1)\msw$(WXLIBPOSTFIX) \ /I$(WX_DIR)\include /W4 $(__DEBUGINFO) $(____DEBUGINFO) /Fdmmex.pdb \ $(__OPTIMIZEFLAG) $(__DEBUG_DEFINE_p) /I..\..\lib\sqlite \ - /I..\..\lib\wxsqlite /I..\..\lib\lua\src /DNOPCH /D_WINDOWS /EHsc /GR \ - $(__mmex_CL_FLAGS) $(CPPFLAGS) $(CXXFLAGS) + /I..\..\lib\wxsqlite /I..\..\lib\lua\src /I..\..\lib /DNOPCH /D_WINDOWS /EHsc \ + /GR $(__mmex_CL_FLAGS) $(CPPFLAGS) $(CXXFLAGS) MMEX_OBJECTS = \ mmex_aboutdialog.obj \ mmex_appstartdialog.obj \ @@ -895,5 +895,5 @@ $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\win\platfdep.cpp mmex_resources_mmex.res: ..\..\resources\mmex.rc - rc /fo$@ /d WIN32 $(____WX_SHARED_46_p_1) $(__WXUNICODE_DEFINE_p_2) $(__WXDEBUG_DEFINE_p_2) /d __WXMSW__ /i $(WX_DIR)$(__WXLIBPATH_FILENAMES_2)\msw$(WXLIBPOSTFIX) /i $(WX_DIR)\include $(____DEBUGINFO_55_p_1) $(__DEBUG_DEFINE_p_4) /i ..\..\lib\sqlite /i ..\..\lib\wxsqlite /i ..\..\lib\lua\src /d NOPCH /d _WINDOWS ..\..\resources\mmex.rc + rc /fo$@ /d WIN32 $(____WX_SHARED_46_p_1) $(__WXUNICODE_DEFINE_p_2) $(__WXDEBUG_DEFINE_p_2) /d __WXMSW__ /i $(WX_DIR)$(__WXLIBPATH_FILENAMES_2)\msw$(WXLIBPOSTFIX) /i $(WX_DIR)\include $(____DEBUGINFO_55_p_1) $(__DEBUG_DEFINE_p_4) /i ..\..\lib\sqlite /i ..\..\lib\wxsqlite /i ..\..\lib\lua\src /i ..\..\lib /d NOPCH /d _WINDOWS ..\..\resources\mmex.rc Added: trunk/mmex/lib/cajun/Makefile =================================================================== --- trunk/mmex/lib/cajun/Makefile (rev 0) +++ trunk/mmex/lib/cajun/Makefile 2013-06-05 14:47:05 UTC (rev 4034) @@ -0,0 +1,7 @@ +EXE_NAME = ./test.out + +$(EXE_NAME): test.cpp + g++ -o $@ $^ + +clean: + rm $(EXE_NAME) Property changes on: trunk/mmex/lib/cajun/Makefile ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: trunk/mmex/lib/cajun/Readme.txt =================================================================== --- trunk/mmex/lib/cajun/Readme.txt (rev 0) +++ trunk/mmex/lib/cajun/Readme.txt 2013-06-05 14:47:05 UTC (rev 4034) @@ -0,0 +1,14 @@ +CAJUN* is a C++ API for the JSON object interchange format. JSON is like XML, except it doesn't suck**. It is specifically designed for representing (in plain text format) structures familiar to software engineers: booleans, numerics, strings, arrays, and objects (i.e. name/value pairs, associative array, etc.); it humbly leaves text markup to XML. It is ideal for storing persistent application data, such as configuration or user data files. + +Too many JSON parsers I've seen suffer from overly complex designs and confusing interfaces, so in true software engineer form, I thought I could do better. The goal of JSON was to create an simple, "minimalist" interface while sacrificing absolutely no power or flexibility. The STL containers, while not without their violations of that spirit, served as an inspiration. The end result is (IMHO) an interface that should be immediately intuitive to anyone familiar with C++ and the Standard Library containers. It can best be described as working with an "element", where an element may consist of: +* String (mimics std::string) +* Numeric (double) +* Boolean (bool) +* Array (std::vector<UnknownElement>) +* Object (unsorted std::map<std::string, UnknownElement>) +* UnknownElement - like boost::any, but restricted to types below. Used to aggregate elements within Objects & Arrays, and for reading documents of unknown structure + +As with any design, sacrifices were made with CAJUN. Most situations I've encountered where JSON is well-suited (reading & writing application configuration and data files) are not typically performance bottlenecks, so simplicity, safety & flexibility were favored over raw speed. The end result is a library with simple, typesafe classes, no memory-management burden on the user, and exception-based error reporting. + +* C++ API for JSON. A pint on me for who ever comes up with a good meaning for "UN". +** To be fair, XML doesn't suck intentionally, it is just often used inappropriately. \ No newline at end of file Property changes on: trunk/mmex/lib/cajun/Readme.txt ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: trunk/mmex/lib/cajun/ReleaseNotes.txt =================================================================== --- trunk/mmex/lib/cajun/ReleaseNotes.txt (rev 0) +++ trunk/mmex/lib/cajun/ReleaseNotes.txt 2013-06-05 14:47:05 UTC (rev 4034) @@ -0,0 +1,42 @@ +2.0.2 (12/04/2011) +* Fixed exception text construction bug (pointer + offset, instead of std::string + std::string) +* Fixed crash in UnknownElement::operator= +* Fixed bug where object member names couldn't contain special characters +* Fixed crash when parsing an incomplete document +* Cosmetic changes to parser +* Added proper BSD license text + +2.0.1 (11/17/2009) +* A couple of Reader functions not inlined, sometimes resulting in linker duplicate symbols. Oops. + +2.0.0 (11/14/2009) +* Redesign/simplicification of the element class relationships: + * Element/Element_T base class or *Imp classes eliminated. Originally necessary for aggregation by Object/Array, but now unnecessary with UnknownElement type + * json_cast<> functions eliminated. Static type safety relaxed, allowing more concise document data extraction code (dynamic type safety still completely maintained). + * Quick-Interpreter/-Builder classes eliminated. Equivalent functionality now in "UnknownElement", but now more accessible + In summary, simpler design, less code in library, less code necessary to utilize library. See test app for many more new examples. +* Entire library is now inlined. Bound to be controversial, but... + * Modern compilers should eliminate redundant object code + * Fixes problems associated with different runtime libraries, library debug information, security & debug iterator compile-time options under MSVC++, among other things. + * Simply include the appropriate file & go - no linker settings to mess with. +* Added 64-bit build targets for MSVC 8/9 test app, just because. +* Scan/Parse exceptions moved into Reader class scope, and Parse exceptions fixed to always include bad token string +* A few more random bug fixes +* Tested under: + * MSVC++ 2005 + * MSVC++ 2008 + * GCC 4.4.0 + +1.1.0 (08/30/2009) +* Implemented operator == for all element types +* Added makefile for building with g++ (thanks George Morgan). +* Fixed a few compiler errors on non-Visual Studio compilers (my C++ wasn't as ANSI as I thought...) +* Support for (non-standard) comments REMOVED +* Support for Visual Studio 7.1 (2003) REMOVED +* Fixed the "Unexpected token..." exception string (was gibberish) +* Improvements to the QuickInterpreter & QuickBuilder interfaces +* Elements now sanity-check themselves during operations and throw an exception accordingly, for example if an Object gets tricked into thinking it's an Array (reinterpret_cast, reading a document with an Array root element into an Object, etc) +* Other random minor bug fixes & general cleanup + +1.0.0 (01/31/2009) +* Initial release! Remaining work: better documentation, better test/sample app, yada yada Property changes on: trunk/mmex/lib/cajun/ReleaseNotes.txt ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: trunk/mmex/lib/cajun/json/elements.h =================================================================== --- trunk/mmex/lib/cajun/json/elements.h (rev 0) +++ trunk/mmex/lib/cajun/json/elements.h 2013-06-05 14:47:05 UTC (rev 4034) @@ -0,0 +1,299 @@ +/****************************************************************************** + +Copyright (c) 2009-2010, Terry Caton +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the projecct nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +#pragma once + +#include <deque> +#include <list> +#include <string> +#include <stdexcept> + +/* + +TODO: +* better documentation (doxygen?) +* Unicode support +* parent element accessors + +*/ + +namespace json +{ + +namespace Version +{ + enum { MAJOR = 2 }; + enum { MINOR = 0 }; + enum {ENGINEERING = 2 }; +} + +///////////////////////////////////////////////// +// forward declarations (more info further below) + + +class Visitor; +class ConstVisitor; + +template <typename ValueTypeT> +class TrivialType_T; + +typedef TrivialType_T<double> Number; +typedef TrivialType_T<bool> Boolean; +typedef TrivialType_T<std::string> String; + +class Object; +class Array; +class Null; + + + +///////////////////////////////////////////////////////////////////////// +// Exception - base class for all JSON-related runtime errors + +class Exception : public std::runtime_error +{ +public: + Exception(const std::string& sMessage); +}; + + + + +///////////////////////////////////////////////////////////////////////// +// UnknownElement - provides a typesafe surrogate for any of the JSON- +// sanctioned element types. This class allows the Array and Object +// class to effectively contain a heterogeneous set of child elements. +// The cast operators provide convenient implicit downcasting, while +// preserving dynamic type safety by throwing an exception during a +// a bad cast. +// The object & array element index operators (operators [std::string] +// and [size_t]) provide convenient, quick access to child elements. +// They are a logical extension of the cast operators. These child +// element accesses can be chained together, allowing the following +// (when document structure is well-known): +// String str = objInvoices[1]["Customer"]["Company"]; + + +class UnknownElement +{ +public: + UnknownElement(); + UnknownElement(const UnknownElement& unknown); + UnknownElement(const Object& object); + UnknownElement(const Array& array); + UnknownElement(const Number& number); + UnknownElement(const Boolean& boolean); + UnknownElement(const String& string); + UnknownElement(const Null& null); + + ~UnknownElement(); + + UnknownElement& operator = (const UnknownElement& unknown); + + // implicit cast to actual element type. throws on failure + operator const Object& () const; + operator const Array& () const; + operator const Number& () const; + operator const Boolean& () const; + operator const String& () const; + operator const Null& () const; + + // implicit cast to actual element type. *converts* on failure, and always returns success + operator Object& (); + operator Array& (); + operator Number& (); + operator Boolean& (); + operator String& (); + operator Null& (); + + // provides quick access to children when real element type is object + UnknownElement& operator[] (const std::string& key); + const UnknownElement& operator[] (const std::string& key) const; + + // provides quick access to children when real element type is array + UnknownElement& operator[] (size_t index); + const UnknownElement& operator[] (size_t index) const; + + // implements visitor pattern + void Accept(ConstVisitor& visitor) const; + void Accept(Visitor& visitor); + + // tests equality. first checks type, then value if possible + bool operator == (const UnknownElement& element) const; + +private: + class Imp; + + template <typename ElementTypeT> + class Imp_T; + + class CastVisitor; + class ConstCastVisitor; + + template <typename ElementTypeT> + class CastVisitor_T; + + template <typename ElementTypeT> + class ConstCastVisitor_T; + + template <typename ElementTypeT> + const ElementTypeT& CastTo() const; + + template <typename ElementTypeT> + ElementTypeT& ConvertTo(); + + Imp* m_pImp; +}; + + +///////////////////////////////////////////////////////////////////////////////// +// Array - mimics std::deque<UnknownElement>. The array contents are effectively +// heterogeneous thanks to the ElementUnknown class. push_back has been replaced +// by more generic insert functions. + +class Array +{ +public: + typedef std::deque<UnknownElement> Elements; + typedef Elements::iterator iterator; + typedef Elements::const_iterator const_iterator; + + iterator Begin(); + iterator End(); + const_iterator Begin() const; + const_iterator End() const; + + iterator Insert(const UnknownElement& element, iterator itWhere); + iterator Insert(const UnknownElement& element); + iterator Erase(iterator itWhere); + void Resize(size_t newSize); + void Clear(); + + size_t Size() const; + bool Empty() const; + + UnknownElement& operator[] (size_t index); + const UnknownElement& operator[] (size_t index) const; + + bool operator == (const Array& array) const; + +private: + Elements m_Elements; +}; + + +///////////////////////////////////////////////////////////////////////////////// +// Object - mimics std::map<std::string, UnknownElement>. The member value +// contents are effectively heterogeneous thanks to the UnknownElement class + +class Object +{ +public: + struct Member { + Member(const std::string& nameIn = std::string(), const UnknownElement& elementIn = UnknownElement()); + + bool operator == (const Member& member) const; + + std::string name; + UnknownElement element; + }; + + typedef std::list<Member> Members; // map faster, but does not preserve order + typedef Members::iterator iterator; + typedef Members::const_iterator const_iterator; + + bool operator == (const Object& object) const; + + iterator Begin(); + iterator End(); + const_iterator Begin() const; + const_iterator End() const; + + size_t Size() const; + bool Empty() const; + + iterator Find(const std::string& name); + const_iterator Find(const std::string& name) const; + + iterator Insert(const Member& member); + iterator Insert(const Member& member, iterator itWhere); + iterator Erase(iterator itWhere); + void Clear(); + + UnknownElement& operator [](const std::string& name); + const UnknownElement& operator [](const std::string& name) const; + +private: + class Finder; + + Members m_Members; +}; + + +///////////////////////////////////////////////////////////////////////////////// +// TrivialType_T - class template for encapsulates a simple data type, such as +// a string, number, or boolean. Provides implicit const & noncost cast operators +// for that type, allowing "DataTypeT type = trivialType;" + + +template <typename DataTypeT> +class TrivialType_T +{ +public: + TrivialType_T(const DataTypeT& t = DataTypeT()); + + operator DataTypeT&(); + operator const DataTypeT&() const; + + DataTypeT& Value(); + const DataTypeT& Value() const; + + bool operator == (const TrivialType_T<DataTypeT>& trivial) const; + +private: + DataTypeT m_tValue; +}; + + + +///////////////////////////////////////////////////////////////////////////////// +// Null - doesn't do much of anything but satisfy the JSON spec. It is the default +// element type of UnknownElement + +class Null +{ +public: + bool operator == (const Null& trivial) const; +}; + + +} // End namespace + + +#include "elements.inl" Property changes on: trunk/mmex/lib/cajun/json/elements.h ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: trunk/mmex/lib/cajun/json/elements.inl =================================================================== --- trunk/mmex/lib/cajun/json/elements.inl (rev 0) +++ trunk/mmex/lib/cajun/json/elements.inl 2013-06-05 14:47:05 UTC (rev 4034) @@ -0,0 +1,442 @@ +/****************************************************************************** + +Copyright (c) 2009-2010, Terry Caton +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the projecct nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +#include "visitor.h" +#include "reader.h" +#include <cassert> +#include <algorithm> +#include <map> + +/* + +TODO: +* better documentation + +*/ + +namespace json +{ + + +inline Exception::Exception(const std::string& sMessage) : + std::runtime_error(sMessage) {} + + +///////////////////////// +// UnknownElement members + +class UnknownElement::Imp +{ +public: + virtual ~Imp() {} + virtual Imp* Clone() const = 0; + + virtual bool Compare(const Imp& imp) const = 0; + + virtual void Accept(ConstVisitor& visitor) const = 0; + virtual void Accept(Visitor& visitor) = 0; +}; + + +template <typename ElementTypeT> +class UnknownElement::Imp_T : public UnknownElement::Imp +{ +public: + Imp_T(const ElementTypeT& element) : m_Element(element) {} + virtual Imp* Clone() const { return new Imp_T<ElementTypeT>(*this); } + + virtual void Accept(ConstVisitor& visitor) const { visitor.Visit(m_Element); } + virtual void Accept(Visitor& visitor) { visitor.Visit(m_Element); } + + virtual bool Compare(const Imp& imp) const + { + ConstCastVisitor_T<ElementTypeT> castVisitor; + imp.Accept(castVisitor); + return castVisitor.m_pElement && + m_Element == *castVisitor.m_pElement; + } + +private: + ElementTypeT m_Element; +}; + + +class UnknownElement::ConstCastVisitor : public ConstVisitor +{ + virtual void Visit(const Array& array) {} + virtual void Visit(const Object& object) {} + virtual void Visit(const Number& number) {} + virtual void Visit(const String& string) {} + virtual void Visit(const Boolean& boolean) {} + virtual void Visit(const Null& null) {} +}; + +template <typename ElementTypeT> +class UnknownElement::ConstCastVisitor_T : public ConstCastVisitor +{ +public: + ConstCastVisitor_T() : m_pElement(0) {} + virtual void Visit(const ElementTypeT& element) { m_pElement = &element; } // we don't know what this is, but it overrides one of the base's no-op functions + const ElementTypeT* m_pElement; +}; + + +class UnknownElement::CastVisitor : public Visitor +{ + virtual void Visit(Array& array) {} + virtual void Visit(Object& object) {} + virtual void Visit(Number& number) {} + virtual void Visit(String& string) {} + virtual void Visit(Boolean& boolean) {} + virtual void Visit(Null& null) {} +}; + +template <typename ElementTypeT> +class UnknownElement::CastVisitor_T : public CastVisitor +{ +public: + CastVisitor_T() : m_pElement(0) {} + virtual void Visit(ElementTypeT& element) { m_pElement = &element; } // we don't know what this is, but it overrides one of the base's no-op functions + ElementTypeT* m_pElement; +}; + + + + +inline UnknownElement::UnknownElement() : m_pImp( new Imp_T<Null>( Null() ) ) {} +inline UnknownElement::UnknownElement(const UnknownElement& unknown) : m_pImp( unknown.m_pImp->Clone()) {} +inline UnknownElement::UnknownElement(const Object& object) : m_pImp( new Imp_T<Object>(object) ) {} +inline UnknownElement::UnknownElement(const Array& array) : m_pImp( new Imp_T<Array>(array) ) {} +inline UnknownElement::UnknownElement(const Number& number) : m_pImp( new Imp_T<Number>(number) ) {} +inline UnknownElement::UnknownElement(const Boolean& boolean) : m_pImp( new Imp_T<Boolean>(boolean) ) {} +inline UnknownElement::UnknownElement(const String& string) : m_pImp( new Imp_T<String>(string) ) {} +inline UnknownElement::UnknownElement(const Null& null) : m_pImp( new Imp_T<Null>(null) ) {} + +inline UnknownElement::~UnknownElement() { delete m_pImp; } + +inline UnknownElement::operator const Object& () const { return CastTo<Object>(); } +inline UnknownElement::operator const Array& () const { return CastTo<Array>(); } +inline UnknownElement::operator const Number& () const { return CastTo<Number>(); } +inline UnknownElement::operator const Boolean& () const { return CastTo<Boolean>(); } +inline UnknownElement::operator const String& () const { return CastTo<String>(); } +inline UnknownElement::operator const Null& () const { return CastTo<Null>(); } + +inline UnknownElement::operator Object& () { return ConvertTo<Object>(); } +inline UnknownElement::operator Array& () { return ConvertTo<Array>(); } +inline UnknownElement::operator Number& () { return ConvertTo<Number>(); } +inline UnknownElement::operator Boolean& () { return ConvertTo<Boolean>(); } +inline UnknownElement::operator String& () { return ConvertTo<String>(); } +inline UnknownElement::operator Null& () { return ConvertTo<Null>(); } + +inline UnknownElement& UnknownElement::operator = (const UnknownElement& unknown) +{ + // always check for this + if (&unknown != this) + { + // we might be copying from a subtree of ourselves. delete the old imp + // only after the clone operation is complete. yes, this could be made + // more efficient, but isn't worth the complexity + Imp* pOldImp = m_pImp; + m_pImp = unknown.m_pImp->Clone(); + delete pOldImp; + } + + return *this; +} + +inline UnknownElement& UnknownElement::operator[] (const std::string& key) +{ + // the people want an object. make us one if we aren't already + Object& object = ConvertTo<Object>(); + return object[key]; +} + +inline const UnknownElement& UnknownElement::operator[] (const std::string& key) const +{ + // throws if we aren't an object + const Object& object = CastTo<Object>(); + return object[key]; +} + +inline UnknownElement& UnknownElement::operator[] (size_t index) +{ + // the people want an array. make us one if we aren't already + Array& array = ConvertTo<Array>(); + return array[index]; +} + +inline const UnknownElement& UnknownElement::operator[] (size_t index) const +{ + // throws if we aren't an array + const Array& array = CastTo<Array>(); + return array[index]; +} + + +template <typename ElementTypeT> +const ElementTypeT& UnknownElement::CastTo() const +{ + ConstCastVisitor_T<ElementTypeT> castVisitor; + m_pImp->Accept(castVisitor); + if (castVisitor.m_pElement == 0) + throw Exception("Bad cast"); + return *castVisitor.m_pElement; +} + + + +template <typename ElementTypeT> +ElementTypeT& UnknownElement::ConvertTo() +{ + CastVisitor_T<ElementTypeT> castVisitor; + m_pImp->Accept(castVisitor); + if (castVisitor.m_pElement == 0) + { + // we're not the right type. fix it & try again + *this = ElementTypeT(); + m_pImp->Accept(castVisitor); + } + + return *castVisitor.m_pElement; +} + + +inline void UnknownElement::Accept(ConstVisitor& visitor) const { m_pImp->Accept(visitor); } +inline void UnknownElement::Accept(Visitor& visitor) { m_pImp->Accept(visitor); } + + +inline bool UnknownElement::operator == (const UnknownElement& element) const +{ + return m_pImp->Compare(*element.m_pImp); +} + + + +////////////////// +// Object members + + +inline Object::Member::Member(const std::string& nameIn, const UnknownElement& elementIn) : + name(nameIn), element(elementIn) {} + +inline bool Object::Member::operator == (const Member& member) const +{ + return name == member.name && + element == member.element; +} + +class Object::Finder : public std::unary_function<Object::Member, bool> +{ +public: + Finder(const std::string& name) : m_name(name) {} + bool operator () (const Object::Member& member) { + return member.name == m_name; + } + +private: + std::string m_name; +}; + + + +inline Object::iterator Object::Begin() { return m_Members.begin(); } +inline Object::iterator Object::End() { return m_Members.end(); } +inline Object::const_iterator Object::Begin() const { return m_Members.begin(); } +inline Object::const_iterator Object::End() const { return m_Members.end(); } + +inline size_t Object::Size() const { return m_Members.size(); } +inline bool Object::Empty() const { return m_Members.empty(); } + +inline Object::iterator Object::Find(const std::string& name) +{ + return std::find_if(m_Members.begin(), m_Members.end(), Finder(name)); +} + +inline Object::const_iterator Object::Find(const std::string& name) const +{ + return std::find_if(m_Members.begin(), m_Members.end(), Finder(name)); +} + +inline Object::iterator Object::Insert(const Member& member) +{ + return Insert(member, End()); +} + +inline Object::iterator Object::Insert(const Member& member, iterator itWhere) +{ + iterator it = Find(member.name); + if (it != m_Members.end()) + throw Exception(std::string("Object member already exists: ") + member.name); + + it = m_Members.insert(itWhere, member); + return it; +} + +inline Object::iterator Object::Erase(iterator itWhere) +{ + return m_Members.erase(itWhere); +} + +inline UnknownElement& Object::operator [](const std::string& name) +{ + + iterator it = Find(name); + if (it == m_Members.end()) + { + Member member(name); + it = Insert(member, End()); + } + return it->element; +} + +inline const UnknownElement& Object::operator [](const std::string& name) const +{ + const_iterator it = Find(name); + if (it == End()) + throw Exception(std::string("Object member not found: ") + name); + return it->element; +} + +inline void Object::Clear() +{ + m_Members.clear(); +} + +inline bool Object::operator == (const Object& object) const +{ + return m_Members == object.m_Members; +} + + +///////////////// +// Array members + +inline Array::iterator Array::Begin() { return m_Elements.begin(); } +inline Array::iterator Array::End() { return m_Elements.end(); } +inline Array::const_iterator Array::Begin() const { return m_Elements.begin(); } +inline Array::const_iterator Array::End() const { return m_Elements.end(); } + +inline Array::iterator Array::Insert(const UnknownElement& element, iterator itWhere) +{ + return m_Elements.insert(itWhere, element); +} + +inline Array::iterator Array::Insert(const UnknownElement& element) +{ + return Insert(element, End()); +} + +inline Array::iterator Array::Erase(iterator itWhere) +{ + return m_Elements.erase(itWhere); +} + +inline void Array::Resize(size_t newSize) +{ + m_Elements.resize(newSize); +} + +inline size_t Array::Size() const { return m_Elements.size(); } +inline bool Array::Empty() const { return m_Elements.empty(); } + +inline UnknownElement& Array::operator[] (size_t index) +{ + size_t nMinSize = index + 1; // zero indexed + if (m_Elements.size() < nMinSize) + m_Elements.resize(nMinSize); + return m_Elements[index]; +} + +inline const UnknownElement& Array::operator[] (size_t index) const +{ + if (index >= m_Elements.size()) + throw Exception("Array out of bounds"); + return m_Elements[index]; +} + +inline void Array::Clear() { + m_Elements.clear(); +} + +inline bool Array::operator == (const Array& array) const +{ + return m_Elements == array.m_Elements; +} + + +//////////////////////// +// TrivialType_T members + +template <typename DataTypeT> +TrivialType_T<DataTypeT>::TrivialType_T(const DataTypeT& t) : + m_tValue(t) {} + +template <typename DataTypeT> +TrivialType_T<DataTypeT>::operator DataTypeT&() +{ + return Value(); +} + +template <typename DataTypeT> +TrivialType_T<DataTypeT>::operator const DataTypeT&() const +{ + return Value(); +} + +template <typename DataTypeT> +DataTypeT& TrivialType_T<DataTypeT>::Value() +{ + return m_tValue; +} + +template <typename DataTypeT> +const DataTypeT& TrivialType_T<DataTypeT>::Value() const +{ + return m_tValue; +} + +template <typename DataTypeT> +bool TrivialType_T<DataTypeT>::operator == (const TrivialType_T<DataTypeT>& trivial) const +{ + return m_tValue == trivial.m_tValue; +} + + + +////////////////// +// Null members + +inline bool Null::operator == (const Null& trivial) const +{ + return true; +} + + + +} // End namespace Property changes on: trunk/mmex/lib/cajun/json/elements.inl ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: trunk/mmex/lib/cajun/json/reader.h =================================================================== --- trunk/mmex/lib/cajun/json/reader.h (rev 0) +++ trunk/mmex/lib/cajun/json/reader.h 2013-06-05 14:47:05 UTC (rev 4034) @@ -0,0 +1,148 @@ +/****************************************************************************** + +Copyright (c) 2009-2010, Terry Caton +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the projecct nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + + + +#pragma once + +#include "elements.h" +#include <iostream> +#include <vector> + +namespace json +{ + +class Reader +{ +public: + // this structure will be reported in one of the exceptions defined below + struct Location + { + Location(); + + unsigned int m_nLine; // document line, zero-indexed + unsigned int m_nLineOffset; // character offset from beginning of line, zero indexed + unsigned int m_nDocOffset; // character offset from entire document, zero indexed + }; + + // thrown during the first phase of reading. generally catches low-level problems such + // as errant characters or corrupt/incomplete documents + class ScanException : public Exception + { + public: + ScanException(const std::string& sMessage, const Reader::Location& locError) : + Exception(sMessage), + m_locError(locError) {} + + Reader::Location m_locError; + }; + + // thrown during the second phase of reading. generally catches higher-level problems such + // as missing commas or brackets + class ParseException : public Exception + { + public: + ParseException(const std::string& sMessage, const Reader::Location& locTokenBegin, const Reader::Location& locTokenEnd) : + Exception(sMessage), + m_locTokenBegin(locTokenBegin), + m_locTokenEnd(locTokenEnd) {} + + Reader::Location m_locTokenBegin; + Reader::Location m_locTokenEnd; + }; + + + // if you know what the document looks like, call one of these... + static void Read(Object& object, std::istream& istr); + static void Read(Array& array, std::istream& istr); + static void Read(String& string, std::istream& istr); + static void Read(Number& number, std::istream& istr); + static void Read(Boolean& boolean, std::istream& istr); + static void Read(Null& null, std::istream& istr); + + // ...otherwise, if you don't know, call this & visit it + static void Read(UnknownElement& elementRoot, std::istream& istr); + +private: + struct Token + { + enum Type + { + TOKEN_OBJECT_BEGIN, // { + TOKEN_OBJECT_END, // } + TOKEN_ARRAY_BEGIN, // [ + TOKEN_ARRAY_END, // ] + TOKEN_NEXT_ELEMENT, // , + TOKEN_MEMBER_ASSIGN, // : + TOKEN_STRING, // "xxx" + TOKEN_NUMBER, // [+/-]000.000[e[+/-]000] + TOKEN_BOOLEAN, // true -or- false + TOKEN_NULL, // null + }; + + Type nType; + std::string sValue; + + // for malformed file debugging + Reader::Location locBegin; + Reader::Location locEnd; + }; + + class InputStream; + class TokenStream; + typedef std::vector<Token> Tokens; + + template <typename ElementTypeT> + static void Read_i(ElementTypeT& element, std::istream& istr); + + // scanning istream into token sequence + void Scan(Tokens& tokens, InputStream& inputStream); + + void EatWhiteSpace(InputStream& inputStream); + std::string MatchString(InputStream& inputStream); + std::string MatchNumber(InputStream& inputStream); + std::string MatchExpectedString(InputStream& inputStream, const std::string& sExpected); + + // parsing token sequence into element structure + void Parse(UnknownElement& element, TokenStream& tokenStream); + void Parse(Object& object, TokenStream& tokenStream); + void Parse(Array& array, TokenStream& tokenStream); + void Parse(String& string, TokenStream& tokenStream); + void Parse(Number& number, TokenStream& tokenStream); + void Parse(Boolean& boolean, TokenStream& tokenStream); + void Parse(Null& null, TokenStream& tokenStream); + + const std::string& MatchExpectedToken(Token::Type nExpected, TokenStream& tokenStream); +}; + + +} // End namespace + + +#include "reader.inl" \ No newline at end of file Property changes on: trunk/mmex/lib/cajun/json/reader.h ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: trunk/mmex/lib/cajun/json/reader.inl =================================================================== --- trunk/mmex/lib/cajun/json/reader.inl (rev 0) +++ trunk/mmex/lib/cajun/json/reader.inl 2013-06-05 14:47:05 UTC (rev 4034) @@ -0,0 +1,533 @@ +/****************************************************************************** + +Copyright (c) 2009-2010, Terry Caton +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the projecct nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +#include <cassert> +#include <set> +#include <sstream> + +/* + +TODO: +* better documentation +* unicode character decoding + +*/ + +namespace json +{ + +inline std::istream& operator >> (std::istream& istr, UnknownElement& elementRoot) { + Reader::Read(elementRoot, istr); + return istr; +} + +inline Reader::Location::Location() : + m_nLine(0), + m_nLineOffset(0), + m_nDocOffset(0) +{} + + +////////////////////// +// Reader::InputStream + +class Reader::InputStream // would be cool if we could inherit from std::istream & override "get" +{ +public: + InputStream(std::istream& iStr) : + m_iStr(iStr) {} + + // protect access to the input stream, so we can keeep track of document/line offsets + char Get(); // big, define outside + char Peek() { + assert(m_iStr.eof() == false); // enforce reading of only valid stream data + return m_iStr.peek(); + } + + bool EOS() { + m_iStr.peek(); // apparently eof flag isn't set until a character read is attempted. whatever. + return m_iStr.eof(); + } + + const Location& GetLocation() const { return m_Location; } + +private: + std::istream& m_iStr; + Location m_Location; +}; + + +inline char Reader::InputStream::Get() +{ + assert(m_iStr.eof() == false); // enforce reading of only valid stream data + char c = m_iStr.get(); + + ++m_Location.m_nDocOffset; + if (c == '\n') { + ++m_Location.m_nLine; + m_Location.m_nLineOffset = 0; + } + else { + ++m_Location.m_nLineOffset; + } + + return c; +} + + + +////////////////////// +// Reader::TokenStream + +class Reader::TokenStream +{ +public: + TokenStream(const Tokens& tokens); + + const Token& Peek(); + const Token& Get(); + + bool EOS() const; + +private: + const Tokens& m_Tokens; + Tokens::const_iterator m_itCurrent; +}; + + +inline Reader::TokenStream::TokenStream(const Tokens& tokens) : + m_Tokens(tokens), + m_itCurrent(tokens.begin()) +{} + +inline const Reader::Token& Reader::TokenStream::Peek() { + if (EOS()) + { + const Token& lastToken = *m_Tokens.rbegin(); + std::string sMessage = "Unexpected end of token stream"; + throw ParseException(sMessage, lastToken.locBegin, lastToken.locEnd); // nowhere to point to + } + return *(m_itCurrent); +} + +inline const Reader::Token& Reader::TokenStream::Get() { + const Token& token = Peek(); + ++m_itCurrent; + return token; +} + +inline bool Reader::TokenStream::EOS() const { + return m_itCurrent == m_Tokens.end(); +} + +/////////////////// +// Reader (finally) + + +inline void Reader::Read(Object& object, std::istream& istr) { Read_i(object, istr); } +inline void Reader::Read(Array& array, std::istream& istr) { Read_i(array, istr); } +inline void Reader::Read(String& string, std::istream& istr) { Read_i(string, istr); } +inline void Reader::Read(Number& number, std::istream& istr) { Read_i(number, istr); } +inline void Reader::Read(Boolean& boolean, std::istream& istr) { Read_i(boolean, istr); } +inline void Reader::Read(Null& null, std::istream& istr) { Read_i(null, istr); } +inline void Reader::Read(UnknownElement& unknown, std::istream& istr) { Read_i(unknown, istr); } + + +template <typename ElementTypeT> +void Reader::Read_i(ElementTypeT& element, std::istream& istr) +{ + Reader reader; + + Tokens tokens; + InputStream inputStream(istr); + reader.Scan(tokens, inputStream); + + TokenStream tokenStream(tokens); + reader.Parse(element, tokenStream); + + if (tokenStream.EOS() == false) + { + const Token& token = tokenStream.Peek(); + std::string sMessage = std::string("Expected End of token stream; found ") + token.sValue; + throw ParseException(sMessage, token.locBegin, token.locEnd); + } +} + + +inline void Reader::Scan(Tokens& tokens, InputStream& inputStream) +{ + while (EatWhiteSpace(inputStream), // ignore any leading white space... + inputStream.EOS() == false) // ...before checking for EOS + { + // if all goes well, we'll create a token each pass + Token token; + token.locBegin = inputStream.GetLocation(); + + // gives us null-terminated string + char sChar = inputStream.Peek(); + switch (sChar) + { + case '{': + token.sValue = MatchExpectedString(inputStream, "{"); + token.nType = Token::TOKEN_OBJECT_BEGIN; + break; + + case '}': + token.sValue = MatchExpectedString(inputStream, "}"); + token.nType = Token::TOKEN_OBJECT_END; + break; + + case '[': + token.sValue = MatchExpectedString(inputStream, "["); + token.nType = Token::TOKEN_ARRAY_BEGIN; + break; + + case ']': + token.sValue = MatchExpectedString(inputStream, "]"); + token.nType = Token::TOKEN_ARRAY_END; + break; + + case ',': + token.sValue = MatchExpectedString(inputStream, ","); + token.nType = Token::TOKEN_NEXT_ELEMENT; + break; + + case ':': + token.sValue = MatchExpectedString(inputStream, ":"); + token.nType = Token::TOKEN_MEMBER_ASSIGN; + break; + + case '"': + token.sValue = MatchString(inputStream); + token.nType = Token::TOKEN_STRING; + break; + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + token.sValue = MatchNumber(inputStream); + token.nType = Token::TOKEN_NUMBER; + break; + + case 't': + token.sValue = MatchExpectedString(inputStream, "true"); + token.nType = Token::TOKEN_BOOLEAN; + break; + + case 'f': + token.sValue = MatchExpectedString(inputStream, "false"); + token.nType = Token::TOKEN_BOOLEAN; + break; + + case 'n': + token.sValue = MatchExpectedString(inputStream, "null"); + token.nType = Token::TOKEN_NULL; + break; + + default: + { + std::string sErrorMessage = std::string("Unexpected character in stream: ") + sChar; + throw ScanException(sErrorMessage, inputStream.GetLocation()); + } + } + + token.locEnd = inputStream.GetLocation(); + tokens.push_back(token); + } +} + + +inline void Reader::EatWhiteSpace(InputStream& inputStream) +{ + while (inputStream.EOS() == false && + ::isspace(inputStream.Peek())) + inputStream.Get(); +} + +inline std::string Reader::MatchExpectedString(InputStream& inputStream, const std::string& sExpected) +{ + std::string::const_iterator it(sExpected.begin()), + itEnd(sExpected.end()); + for ( ; it != itEnd; ++it) { + if (inputStream.EOS() || // did we reach the end before finding what we're looking for... + inputStream.Get() != *it) // ...or did we find something different? + { + std::string sMessage = std::string("Expected string: ") + sExpected; + throw ScanException(sMessage, inputStream.GetLocation()); + } + } + + // all's well if we made it here + return sExpected; +} + + +inline std::string Reader::MatchString(InputStream& inputStream) +{ + MatchExpectedString(inputStream, "\""); + + std::string string; + while (inputStream.EOS() == false && + inputStream.Peek() != '"') + { + char c = inputStream.Get(); + + // escape? + if (c == '\\' && + inputStream.EOS() == false) // shouldn't have reached the end yet + { + c = inputStream.Get(); + switch (c) { + case '/': string.push_back('/'); break; + case '"': string.push_back('"'); break; + case '\\': string.push_back('\\'); break; + case 'b': string.push_back('\b'); break; + case 'f': string.push_back('\f'); break; + case 'n': string.push_back('\n'); break; + case 'r': string.push_back('\r'); break; + case 't': string.push_back('\t'); break; + case 'u': string.push_back('\u'); break; // TODO: what do we do with this? + default: { + std::string sMessage = std::string("Unrecognized escape sequence found in string: \\") + c; + throw ScanException(sMessage, inputStream.GetLocation()); + } + } + } + else { + string.push_back(c); + } + } + + // eat the last '"' that we just peeked + MatchExpectedString(inputStream, "\""); + + // all's well if we made it here + return string; +} + + +inline std::string Reader::MatchNumber(InputStream& inputStream) +{ + const char sNumericChars[] = "0123456789.eE-+"; + std::set<char> numericChars; + numericChars.insert(sNumericChars, sNumericChars + sizeof(sNumericChars)); + + std::string sNumber; + while (inputStream.EOS() == false && + numericChars.find(inputStream.Peek()) != numericChars.end()) + { + sNumber.push_back(inputStream.Get()); + } + + return sNumber; +} + + +inline void Reader::Parse(UnknownElement& element, Reader::TokenStream& tokenStream) +{ + const Token& token = tokenStream.Peek(); + switch (token.nType) { + case Token::TOKEN_OBJECT_BEGIN: + { + // implicit non-const cast will perform conversion for us (if necessary) + Object& object = element; + Parse(object, tokenStream); + break; + } + + case Token::TOKEN_ARRAY_BEGIN: + { + Array& array = element; + Parse(array, tokenStream); + break; + } + + case Token::TOKEN_STRING: + { + String& string = element; + Parse(string, tokenStream); + break; + } + + case Token::TOKEN_NUMBER: + { + Number& number = element; + Parse(number, tokenStream); + break; + } + + case Token::TOKEN_BOOLEAN: + { + Boolean& boolean = element; + Parse(boolean, tokenStream); + break; + } + + case Token::TOKEN_NULL: + { + Null& null = element; + Parse(null, tokenStream); + break; + } + + default: + { + std::string sMessage = std::string("Unexpected token: ") + token.sValue; + throw ParseException(sMessage, token.locBegin, token.locEnd); + } + } +} + + +inline void Reader::Parse(Object& object, Reader::TokenStream& tokenStream) +{ + MatchExpectedToken(Token::TOKEN_OBJECT_BEGIN, tokenStream); + + bool bContinue = (tokenStream.EOS() == false && + tokenStream.Peek().nType != Token::TOKEN_OBJECT_END); + while (bContinue) + { + Object::Member member; + + // first the member name. save the token in case we have to throw an exception + const Token& tokenName = tokenStream.Peek(); + member.name = MatchExpectedToken(Token::TOKEN_STRING, tokenStream); + + // ...then the key/value separator... + MatchExpectedToken(Token::TOKEN_MEMBER_ASSIGN, tokenStream); + + // ...then the value itself (can be anything). + Parse(member.element, tokenStream); + + // try adding it to the object (this could throw) + try + { + object.Insert(member); + } + catch (Exception&) + { + // must be a duplicate name + std::string sMessage = std::string("Duplicate object member token: ") + member.name; + throw ParseException(sMessage, tokenName.locBegin, tokenName.locEnd); + } + + bContinue = (tokenStream.EOS() == false && + tokenStream.Peek().nType == Token::TOKEN_NEXT_ELEMENT); + if (bContinue) + MatchExpectedToken(Token::TOKEN_NEXT_ELEMENT, tokenStream); + } + + MatchExpectedToken(Token::TOKEN_OBJECT_END, tokenStream); +} + + +inline void Reader::Parse(Array& array, Reader::TokenStream& tokenStream) +{ + MatchExpectedToken(Token::TOKEN_ARRAY_BEGIN, tokenStream); + + bool bContinue = (tokenStream.EOS() == false && + tokenStream.Peek().nType != Token::TOKEN_ARRAY_END); + while (bContinue) + { + // ...what's next? could be anything + Array::iterator itElement = array.Insert(UnknownElement()); + UnknownElement& element = *itElement; + Parse(element, tokenStream); + + bContinue = (tokenStream.EOS() == false && + tokenStream.Peek().nType == Token::TOKEN_NEXT_ELEMENT); + if (bContinue) + MatchExpectedToken(Token::TOKEN_NEXT_ELEMENT, tokenStream); + } + + MatchExpectedToken(Token::TOKEN_ARRAY_END, tokenStream); +} + + +inline void Reader::Parse(String& string, Reader::TokenStream& tokenStream) +{ + string = MatchExpectedToken(Token::TOKEN_STRING, tokenStream); +} + + +inline void Reader::Parse(Number& number, Reader::TokenStream& tokenStream) +{ + const Token& currentToken = tokenStream.Peek(); // might need this later for throwing exception + const std::string& sValue = MatchExpectedToken(Token::TOKEN_NUMBER, tokenStream); + + std::istringstream iStr(sValue); + double dValue; + iStr >> dValue; + + // did we consume all characters in the token? + if (iStr.eof() == false) + { + char c = iStr.peek(); + std::string sMessage = std::string("Unexpected character in NUMBER token: ") + c; + throw ParseException(sMessage, currentToken.locBegin, currentToken.locEnd); + } + + number = dValue; +} + + +inline void Reader::Parse(Boolean& boolean, Reader::TokenStream& tokenStream) +{ + const std::string& sValue = MatchExpectedToken(Token::TOKEN_BOOLEAN, tokenStream); + boolean = (sValue == "true" ? true : false); +} + + +inline void Reader::Parse(Null&, Reader::TokenStream& tokenStream) +{ + MatchExpectedToken(Token::TOKEN_NULL, tokenStream); +} + + +inline const std::string& Reader::MatchExpectedToken(Token::Type nExpected, Reader::TokenStream& tokenStream) +{ + const Token& token = tokenStream.Get(); + if (token.nType != nExpected) + { + std::string sMessage = std::string("Unexpected token: ") + token.sValue; + throw ParseException(sMessage, token.locBegin, token.locEnd); + } + + return token.sValue; +} + +} // End namespace Property changes on: trunk/mmex/lib/cajun/json/reader.inl ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: trunk/mmex/lib/cajun/json/visitor.h =================================================================== --- trunk/mmex/lib/cajun/json/visitor.h (rev 0) +++ trunk/mmex/lib/cajun/json/visitor.h 2013-06-05 14:47:05 UTC (rev 4034) @@ -0,0 +1,65 @@ +/****************************************************************************** + +Copyright (c) 2009-2010, Terry Caton +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the projecct nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +#pragma once + +#include "elements.h" + +namespace json +{ + + +class Visitor +{ +public: + virtual ~Visitor() {} + + virtual void Visit(Array& array) = 0; + virtual void Visit(Object& object) = 0; + virtual void Visit(Number& number) = 0; + virtual void Visit(String... [truncated message content] |
From: <ste...@us...> - 2013-06-09 00:35:39
|
Revision: 4051 http://sourceforge.net/p/moneymanagerex/code/4051 Author: stef145g Date: 2013-06-09 00:35:36 +0000 (Sun, 09 Jun 2013) Log Message: ----------- Lua Update: Version 5.2.2 Modified Paths: -------------- trunk/mmex/lib/lua/doc/contents.html trunk/mmex/lib/lua/doc/lua.css trunk/mmex/lib/lua/doc/manual.css trunk/mmex/lib/lua/doc/manual.html trunk/mmex/lib/lua/doc/readme.html trunk/mmex/lib/lua/src/Makefile trunk/mmex/lib/lua/src/lapi.c trunk/mmex/lib/lua/src/lauxlib.c trunk/mmex/lib/lua/src/lbaselib.c trunk/mmex/lib/lua/src/lbitlib.c trunk/mmex/lib/lua/src/lcode.c trunk/mmex/lib/lua/src/lcorolib.c trunk/mmex/lib/lua/src/ldebug.c trunk/mmex/lib/lua/src/ldo.c trunk/mmex/lib/lua/src/lfunc.c trunk/mmex/lib/lua/src/lgc.c trunk/mmex/lib/lua/src/lgc.h trunk/mmex/lib/lua/src/liolib.c trunk/mmex/lib/lua/src/llex.c trunk/mmex/lib/lua/src/llimits.h trunk/mmex/lib/lua/src/lmathlib.c trunk/mmex/lib/lua/src/lmem.h trunk/mmex/lib/lua/src/lobject.c trunk/mmex/lib/lua/src/lobject.h trunk/mmex/lib/lua/src/loslib.c trunk/mmex/lib/lua/src/lparser.c trunk/mmex/lib/lua/src/lstate.c trunk/mmex/lib/lua/src/lstate.h trunk/mmex/lib/lua/src/lstring.c trunk/mmex/lib/lua/src/lstrlib.c trunk/mmex/lib/lua/src/ltable.c trunk/mmex/lib/lua/src/ltablib.c trunk/mmex/lib/lua/src/lua.c trunk/mmex/lib/lua/src/lua.h trunk/mmex/lib/lua/src/luaconf.h trunk/mmex/lib/lua/src/lvm.c trunk/mmex/lib/lua/src/lvm.h trunk/mmex/src/constants.cpp Modified: trunk/mmex/lib/lua/doc/contents.html =================================================================== --- trunk/mmex/lib/lua/doc/contents.html 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/doc/contents.html 2013-06-09 00:35:36 UTC (rev 4051) @@ -23,7 +23,7 @@ <P> The reference manual is the official definition of the Lua language. For a complete introduction to Lua programming, see the book -<A HREF="http://www.lua.org/docs.html#books">Programming in Lua</A>. +<A HREF="http://www.lua.org/pil/">Programming in Lua</A>. <P> <A HREF="manual.html">start</A> @@ -33,7 +33,7 @@ <A HREF="#index">index</A> <HR> <SMALL> -Copyright © 2011–2012 Lua.org, PUC-Rio. +Copyright © 2011–2013 Lua.org, PUC-Rio. Freely available under the terms of the <A HREF="http://www.lua.org/license.html">Lua license</A>. </SMALL> @@ -149,8 +149,8 @@ <A HREF="manual.html#pdf-error">error</A><BR> <A HREF="manual.html#pdf-getmetatable">getmetatable</A><BR> <A HREF="manual.html#pdf-ipairs">ipairs</A><BR> +<A HREF="manual.html#pdf-load">load</A><BR> <A HREF="manual.html#pdf-loadfile">loadfile</A><BR> -<A HREF="manual.html#pdf-load">load</A><BR> <A HREF="manual.html#pdf-next">next</A><BR> <A HREF="manual.html#pdf-pairs">pairs</A><BR> <A HREF="manual.html#pdf-pcall">pcall</A><BR> @@ -385,6 +385,7 @@ <A HREF="manual.html#lua_pushcclosure">lua_pushcclosure</A><BR> <A HREF="manual.html#lua_pushcfunction">lua_pushcfunction</A><BR> <A HREF="manual.html#lua_pushfstring">lua_pushfstring</A><BR> +<A HREF="manual.html#lua_pushglobaltable">lua_pushglobaltable</A><BR> <A HREF="manual.html#lua_pushinteger">lua_pushinteger</A><BR> <A HREF="manual.html#lua_pushlightuserdata">lua_pushlightuserdata</A><BR> <A HREF="manual.html#lua_pushliteral">lua_pushliteral</A><BR> @@ -393,15 +394,16 @@ <A HREF="manual.html#lua_pushnumber">lua_pushnumber</A><BR> <A HREF="manual.html#lua_pushstring">lua_pushstring</A><BR> <A HREF="manual.html#lua_pushthread">lua_pushthread</A><BR> +<A HREF="manual.html#lua_pushunsigned">lua_pushunsigned</A><BR> <A HREF="manual.html#lua_pushvalue">lua_pushvalue</A><BR> <A HREF="manual.html#lua_pushvfstring">lua_pushvfstring</A><BR> <A HREF="manual.html#lua_rawequal">lua_rawequal</A><BR> <A HREF="manual.html#lua_rawget">lua_rawget</A><BR> <A HREF="manual.html#lua_rawgeti">lua_rawgeti</A><BR> +<A HREF="manual.html#lua_rawgetp">lua_rawgetp</A><BR> <A HREF="manual.html#lua_rawlen">lua_rawlen</A><BR> <A HREF="manual.html#lua_rawset">lua_rawset</A><BR> <A HREF="manual.html#lua_rawseti">lua_rawseti</A><BR> -<A HREF="manual.html#lua_rawgetp">lua_rawgetp</A><BR> <A HREF="manual.html#lua_rawsetp">lua_rawsetp</A><BR> <A HREF="manual.html#lua_register">lua_register</A><BR> <A HREF="manual.html#lua_remove">lua_remove</A><BR> @@ -460,8 +462,8 @@ <A HREF="manual.html#luaL_buffinitsize">luaL_buffinitsize</A><BR> <A HREF="manual.html#luaL_callmeta">luaL_callmeta</A><BR> <A HREF="manual.html#luaL_checkany">luaL_checkany</A><BR> +<A HREF="manual.html#luaL_checkint">luaL_checkint</A><BR> <A HREF="manual.html#luaL_checkinteger">luaL_checkinteger</A><BR> -<A HREF="manual.html#luaL_checkint">luaL_checkint</A><BR> <A HREF="manual.html#luaL_checklong">luaL_checklong</A><BR> <A HREF="manual.html#luaL_checklstring">luaL_checklstring</A><BR> <A HREF="manual.html#luaL_checknumber">luaL_checknumber</A><BR> @@ -492,8 +494,8 @@ <A HREF="manual.html#luaL_newmetatable">luaL_newmetatable</A><BR> <A HREF="manual.html#luaL_newstate">luaL_newstate</A><BR> <A HREF="manual.html#luaL_openlibs">luaL_openlibs</A><BR> +<A HREF="manual.html#luaL_optint">luaL_optint</A><BR> <A HREF="manual.html#luaL_optinteger">luaL_optinteger</A><BR> -<A HREF="manual.html#luaL_optint">luaL_optint</A><BR> <A HREF="manual.html#luaL_optlong">luaL_optlong</A><BR> <A HREF="manual.html#luaL_optlstring">luaL_optlstring</A><BR> <A HREF="manual.html#luaL_optnumber">luaL_optnumber</A><BR> @@ -521,10 +523,10 @@ <HR> <SMALL CLASS="footer"> Last update: -Sat May 26 08:52:25 BRT 2012 +Tue Mar 12 11:22:18 BRT 2013 </SMALL> <!-- -Last change: revised for Lua 5.2.1 +Last change: revised for Lua 5.2.2 --> </BODY> Modified: trunk/mmex/lib/lua/doc/lua.css =================================================================== --- trunk/mmex/lib/lua/doc/lua.css 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/doc/lua.css 2013-06-09 00:35:36 UTC (rev 4051) @@ -16,10 +16,10 @@ h2 { padding-top: 0.4em ; padding-bottom: 0.4em ; - padding-left: 30px ; - padding-right: 30px ; - margin-left: -30px ; + padding-left: 1em ; + padding-right: 1em ; background-color: #E0E0FF ; + border-radius: 8px ; } h3 { Modified: trunk/mmex/lib/lua/doc/manual.css =================================================================== --- trunk/mmex/lib/lua/doc/manual.css 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/doc/manual.css 2013-06-09 00:35:36 UTC (rev 4051) @@ -18,7 +18,9 @@ p+h1, ul+h1 { padding-top: 0.4em ; padding-bottom: 0.4em ; - padding-left: 30px ; - margin-left: -30px ; + padding-left: 24px ; + margin-left: -24px ; background-color: #E0E0FF ; + border-radius: 8px ; } + Modified: trunk/mmex/lib/lua/doc/manual.html =================================================================== --- trunk/mmex/lib/lua/doc/manual.html 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/doc/manual.html 2013-06-09 00:35:36 UTC (rev 4051) @@ -19,7 +19,7 @@ by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes <p> <small> -Copyright © 2011–2012 Lua.org, PUC-Rio. +Copyright © 2011–2013 Lua.org, PUC-Rio. Freely available under the terms of the <a href="http://www.lua.org/license.html">Lua license</a>. </small> @@ -33,7 +33,7 @@ <!-- ====================================================================== --> <p> -<!-- $Id: manual.of,v 1.99 2012/06/08 15:30:20 roberto Exp $ --> +<!-- $Id: manual.of,v 1.103 2013/03/14 18:51:56 roberto Exp $ --> @@ -424,7 +424,6 @@ <pre> rawget(getmetatable(obj) or {}, event) </pre><p> - This means that the access to a metamethod does not invoke other metamethods, and access to objects with no metatables does not fail (it simply results in <b>nil</b>). @@ -915,7 +914,7 @@ <p> When you close a state (see <a href="#lua_close"><code>lua_close</code></a>), -Lua calls the finalizers of all objects marked for collection, +Lua calls the finalizers of all objects marked for finalization, following the reverse order that they were marked. If any finalizer marks new objects for collection during that phase, these new objects will not be finalized. @@ -1255,8 +1254,7 @@ <p> -When parsing a from a string source, -any byte in a literal string not +Any byte in a literal string not explicitly affected by the previous rules represents itself. However, Lua opens files for parsing in text mode, and the system file functions may have problems with @@ -1410,6 +1408,35 @@ </pre> <p> +Function calls and assignments +can start with an open parenthesis. +This possibility leads to an ambiguity in Lua's grammar. +Consider the following fragment: + +<pre> + a = b + c + (print or io.write)('done') +</pre><p> +The grammar could see it in two ways: + +<pre> + a = b + c(print or io.write)('done') + + a = b + c; (print or io.write)('done') +</pre><p> +The current parser always sees such constructions +in the first way, +interpreting the open parenthesis +as the start of the arguments to a call. +To avoid this ambiguity, +it is a good practice to always precede with a semicolon +statements that start with a parenthesis: + +<pre> + ;(print or io.write)('done') +</pre> + +<p> A block can be explicitly delimited to produce a single statement: <pre> @@ -1428,7 +1455,7 @@ <h3>3.3.2 – <a name="3.3.2">Chunks</a></h3> <p> -The unit of execution of Lua is called a <em>chunk</em>. +The unit of compilation of Lua is called a <em>chunk</em>. Syntactically, a chunk is simply a block: @@ -1859,7 +1886,8 @@ (unless the expression is enclosed in parentheses). In all other contexts, Lua adjusts the result list to one element, -discarding all values except the first one. +either discarding all values except the first one +or adding a single <b>nil</b> if there are no values. <p> @@ -2559,32 +2587,35 @@ <p> A <em>valid index</em> is an index that refers to a -valid position within the stack, that is, -it lies between 1 and the stack top +real position within the stack, that is, +its position lies between 1 and the stack top (<code>1 ≤ abs(index) ≤ top</code>). -Usually, functions that need a specific stack position -(e.g., <a href="#lua_remove"><code>lua_remove</code></a>) require valid indices. +Usually, functions that can modify the value at an index +require valid indices. <p> +Unless otherwise noted, +any function that accepts valid indices also accepts <em>pseudo-indices</em>, +which represent some Lua values that are accessible to C code +but which are not in the stack. +Pseudo-indices are used to access the registry +and the upvalues of a C function (see <a href="#4.4">§4.4</a>). + + +<p> Functions that do not need a specific stack position, but only a value in the stack (e.g., query functions), can be called with acceptable indices. -An <em>acceptable index</em> refers to a position within -the space allocated for the stack, +An <em>acceptable index</em> can be any valid index, +including the pseudo-indices, +but it also can be any positive index after the stack top +within the space allocated for the stack, that is, indices up to the stack size. -More formally, we define an acceptable index -as follows: - -<pre> - (index < 0 && abs(index) <= top) || - (index > 0 && index <= stack size) -</pre><p> (Note that 0 is never an acceptable index.) -When a function is called, -its stack size is <code>top + LUA_MINSTACK</code>. -You can change its stack size through function <a href="#lua_checkstack"><code>lua_checkstack</code></a>. +Except when noted otherwise, +functions in the API work with acceptable indices. <p> @@ -2598,21 +2629,13 @@ <p> For functions that can be called with acceptable indices, any non-valid index is treated as if it -contains a value of a virtual type <a name="pdf-LUA_TNONE"><code>LUA_TNONE</code></a>. +contains a value of a virtual type <a name="pdf-LUA_TNONE"><code>LUA_TNONE</code></a>, +which behaves like a nil value. -<p> -Unless otherwise noted, -any function that accepts valid indices also accepts <em>pseudo-indices</em>, -which represent some Lua values that are accessible to C code -but which are not in the stack. -Pseudo-indices are used to access the registry -and the upvalues of a C function (see <a href="#4.4">§4.4</a>). - - <h2>4.4 – <a name="4.4">C Closures</a></h2> <p> @@ -2628,13 +2651,13 @@ Whenever a C function is called, its upvalues are located at specific pseudo-indices. These pseudo-indices are produced by the macro -<a name="lua_upvalueindex"><code>lua_upvalueindex</code></a>. +<a href="#lua_upvalueindex"><code>lua_upvalueindex</code></a>. The first value associated with a function is at position <code>lua_upvalueindex(1)</code>, and so on. Any access to <code>lua_upvalueindex(<em>n</em>)</code>, where <em>n</em> is greater than the number of upvalues of the current function (but not greater than 256), -produces an acceptable (but invalid) index. +produces an acceptable but invalid index. @@ -2647,7 +2670,8 @@ a predefined table that can be used by any C code to store whatever Lua values it needs to store. The registry table is always located at pseudo-index -<a name="pdf-LUA_REGISTRYINDEX"><code>LUA_REGISTRYINDEX</code></a>. +<a name="pdf-LUA_REGISTRYINDEX"><code>LUA_REGISTRYINDEX</code></a>, +which is a valid index. Any C library can store data into this table, but it should take care to choose keys that are different from those used @@ -2692,8 +2716,8 @@ <p> Internally, Lua uses the C <code>longjmp</code> facility to handle errors. -(You can also choose to use exceptions if you use C++; -see file <code>luaconf.h</code>.) +(You can also choose to use exceptions if you compile Lua as C++; +search for <code>LUAI_THROW</code> in the source code.) When Lua faces any error (such as a memory allocation error, type errors, syntax errors, and runtime errors) @@ -3136,8 +3160,8 @@ <p> Compares two Lua values. -Returns 1 if the value at acceptable index <code>index1</code> satisfies <code>op</code> -when compared with the value at acceptable index <code>index2</code>, +Returns 1 if the value at index <code>index1</code> satisfies <code>op</code> +when compared with the value at index <code>index2</code>, following the semantics of the corresponding Lua operator (that is, it may call metamethods). Otherwise returns 0. @@ -3180,7 +3204,7 @@ <pre>void lua_copy (lua_State *L, int fromidx, int toidx);</pre> <p> -Moves the element at the valid index <code>fromidx</code> +Moves the element at index <code>fromidx</code> into the valid index <code>toidx</code> without shifting any element (therefore replacing the value at that position). @@ -3390,7 +3414,7 @@ <p> Pushes onto the stack the value <code>t[k]</code>, -where <code>t</code> is the value at the given valid index. +where <code>t</code> is the value at the given index. As in Lua, this function may trigger a metamethod for the "index" event (see <a href="#2.4">§2.4</a>). @@ -3414,8 +3438,7 @@ <pre>int lua_getmetatable (lua_State *L, int index);</pre> <p> -Pushes onto the stack the metatable of the value at the given -acceptable index. +Pushes onto the stack the metatable of the value at the given index. If the value does not have a metatable, the function returns 0 and pushes nothing on the stack. @@ -3429,7 +3452,7 @@ <p> Pushes onto the stack the value <code>t[k]</code>, -where <code>t</code> is the value at the given valid index +where <code>t</code> is the value at the given index and <code>k</code> is the value at the top of the stack. @@ -3477,7 +3500,7 @@ <p> Moves the top element into the given valid index, shifting up the elements above this index to open space. -Cannot be called with a pseudo-index, +This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. @@ -3505,7 +3528,7 @@ <pre>int lua_isboolean (lua_State *L, int index);</pre> <p> -Returns 1 if the value at the given acceptable index is a boolean, +Returns 1 if the value at the given index is a boolean, and 0 otherwise. @@ -3517,7 +3540,7 @@ <pre>int lua_iscfunction (lua_State *L, int index);</pre> <p> -Returns 1 if the value at the given acceptable index is a C function, +Returns 1 if the value at the given index is a C function, and 0 otherwise. @@ -3529,7 +3552,7 @@ <pre>int lua_isfunction (lua_State *L, int index);</pre> <p> -Returns 1 if the value at the given acceptable index is a function +Returns 1 if the value at the given index is a function (either C or Lua), and 0 otherwise. @@ -3541,7 +3564,7 @@ <pre>int lua_islightuserdata (lua_State *L, int index);</pre> <p> -Returns 1 if the value at the given acceptable index is a light userdata, +Returns 1 if the value at the given index is a light userdata, and 0 otherwise. @@ -3553,7 +3576,7 @@ <pre>int lua_isnil (lua_State *L, int index);</pre> <p> -Returns 1 if the value at the given acceptable index is <b>nil</b>, +Returns 1 if the value at the given index is <b>nil</b>, and 0 otherwise. @@ -3565,8 +3588,7 @@ <pre>int lua_isnone (lua_State *L, int index);</pre> <p> -Returns 1 if the given acceptable index is not valid -(that is, it refers to an element outside the current stack), +Returns 1 if the given index is not valid, and 0 otherwise. @@ -3578,8 +3600,7 @@ <pre>int lua_isnoneornil (lua_State *L, int index);</pre> <p> -Returns 1 if the given acceptable index is not valid -(that is, it refers to an element outside the current stack) +Returns 1 if the given index is not valid or if the value at this index is <b>nil</b>, and 0 otherwise. @@ -3592,7 +3613,7 @@ <pre>int lua_isnumber (lua_State *L, int index);</pre> <p> -Returns 1 if the value at the given acceptable index is a number +Returns 1 if the value at the given index is a number or a string convertible to a number, and 0 otherwise. @@ -3605,7 +3626,7 @@ <pre>int lua_isstring (lua_State *L, int index);</pre> <p> -Returns 1 if the value at the given acceptable index is a string +Returns 1 if the value at the given index is a string or a number (which is always convertible to a string), and 0 otherwise. @@ -3618,7 +3639,7 @@ <pre>int lua_istable (lua_State *L, int index);</pre> <p> -Returns 1 if the value at the given acceptable index is a table, +Returns 1 if the value at the given index is a table, and 0 otherwise. @@ -3630,7 +3651,7 @@ <pre>int lua_isthread (lua_State *L, int index);</pre> <p> -Returns 1 if the value at the given acceptable index is a thread, +Returns 1 if the value at the given index is a thread, and 0 otherwise. @@ -3642,7 +3663,7 @@ <pre>int lua_isuserdata (lua_State *L, int index);</pre> <p> -Returns 1 if the value at the given acceptable index is a userdata +Returns 1 if the value at the given index is a userdata (either full or light), and 0 otherwise. @@ -3654,7 +3675,7 @@ <pre>void lua_len (lua_State *L, int index);</pre> <p> -Returns the "length" of the value at the given acceptable index; +Returns the "length" of the value at the given index; it is equivalent to the '<code>#</code>' operator in Lua (see <a href="#3.4.6">§3.4.6</a>). The result is pushed on the stack. @@ -3719,6 +3740,12 @@ <p> +<code>lua_load</code> uses the stack internally, +so the reader function should always leave the stack +unmodified when returning. + + +<p> If the resulting function has one upvalue, this upvalue is set to the value of the global environment stored at index <code>LUA_RIDX_GLOBALS</code> in the registry (see <a href="#4.5">§4.5</a>). @@ -4038,7 +4065,7 @@ <p> Pushes onto the stack a formatted string and returns a pointer to this string. -It is similar to the C function <code>sprintf</code>, +It is similar to the ANSI C function <code>sprintf</code>, but has some important differences: <ul> @@ -4066,6 +4093,17 @@ +<hr><h3><a name="lua_pushglobaltable"><code>lua_pushglobaltable</code></a></h3><p> +<span class="apii">[-0, +1, –]</span> +<pre>void lua_pushglobaltable (lua_State *L);</pre> + +<p> +Pushes the global environment onto the stack. + + + + + <hr><h3><a name="lua_pushinteger"><code>lua_pushinteger</code></a></h3><p> <span class="apii">[-0, +1, –]</span> <pre>void lua_pushinteger (lua_State *L, lua_Integer n);</pre> @@ -4189,12 +4227,23 @@ +<hr><h3><a name="lua_pushunsigned"><code>lua_pushunsigned</code></a></h3><p> +<span class="apii">[-0, +1, –]</span> +<pre>void lua_pushunsigned (lua_State *L, lua_Unsigned n);</pre> + +<p> +Pushes a number with value <code>n</code> onto the stack. + + + + + <hr><h3><a name="lua_pushvalue"><code>lua_pushvalue</code></a></h3><p> <span class="apii">[-0, +1, –]</span> <pre>void lua_pushvalue (lua_State *L, int index);</pre> <p> -Pushes a copy of the element at the given valid index +Pushes a copy of the element at the given index onto the stack. @@ -4220,7 +4269,7 @@ <pre>int lua_rawequal (lua_State *L, int index1, int index2);</pre> <p> -Returns 1 if the two values in acceptable indices <code>index1</code> and +Returns 1 if the two values in indices <code>index1</code> and <code>index2</code> are primitively equal (that is, without calling metamethods). Otherwise returns 0. @@ -4248,7 +4297,7 @@ <p> Pushes onto the stack the value <code>t[n]</code>, -where <code>t</code> is the table at the given valid index. +where <code>t</code> is the table at the given index. The access is raw; that is, it does not invoke metamethods. @@ -4262,7 +4311,7 @@ <p> Pushes onto the stack the value <code>t[k]</code>, -where <code>t</code> is the table at the given valid index and +where <code>t</code> is the table at the given index and <code>k</code> is the pointer <code>p</code> represented as a light userdata. The access is raw; that is, it does not invoke metamethods. @@ -4276,7 +4325,7 @@ <pre>size_t lua_rawlen (lua_State *L, int index);</pre> <p> -Returns the raw "length" of the value at the given acceptable index: +Returns the raw "length" of the value at the given index: for strings, this is the string length; for tables, this is the result of the length operator ('<code>#</code>') with no metamethods; @@ -4306,7 +4355,7 @@ <p> Does the equivalent of <code>t[n] = v</code>, -where <code>t</code> is the table at the given valid index +where <code>t</code> is the table at the given index and <code>v</code> is the value at the top of the stack. @@ -4325,7 +4374,7 @@ <p> Does the equivalent of <code>t[k] = v</code>, -where <code>t</code> is the table at the given valid index, +where <code>t</code> is the table at the given index, <code>k</code> is the pointer <code>p</code> represented as a light userdata, and <code>v</code> is the value at the top of the stack. @@ -4384,7 +4433,7 @@ <p> Removes the element at the given valid index, shifting down the elements above this index to fill the gap. -Cannot be called with a pseudo-index, +This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. @@ -4396,9 +4445,9 @@ <pre>void lua_replace (lua_State *L, int index);</pre> <p> -Moves the top element into the given position +Moves the top element into the given valid index without shifting any element -(therefore replacing the value at the given position), +(therefore replacing the value at the given index), and then pops the top element. @@ -4436,7 +4485,9 @@ <p> -To resume a coroutine, you put on its stack only the values to +To resume a coroutine, +you remove any results from the last <a href="#lua_yield"><code>lua_yield</code></a>, +put on its stack only the values to be passed as results from <code>yield</code>, and then call <a href="#lua_resume"><code>lua_resume</code></a>. @@ -4468,7 +4519,7 @@ <p> Does the equivalent to <code>t[k] = v</code>, -where <code>t</code> is the value at the given valid index +where <code>t</code> is the value at the given index and <code>v</code> is the value at the top of the stack. @@ -4499,8 +4550,7 @@ <p> Pops a table from the stack and -sets it as the new metatable for the value at the given -acceptable index. +sets it as the new metatable for the value at the given index. @@ -4512,7 +4562,7 @@ <p> Does the equivalent to <code>t[k] = v</code>, -where <code>t</code> is the value at the given valid index, +where <code>t</code> is the value at the given index, <code>v</code> is the value at the top of the stack, and <code>k</code> is the value just below the top. @@ -4531,7 +4581,7 @@ <pre>void lua_settop (lua_State *L, int index);</pre> <p> -Accepts any acceptable index, or 0, +Accepts any index, or 0, and sets the stack top to this index. If the new top is larger than the old one, then the new elements are filled with <b>nil</b>. @@ -4603,13 +4653,12 @@ <pre>int lua_toboolean (lua_State *L, int index);</pre> <p> -Converts the Lua value at the given acceptable index to a C boolean +Converts the Lua value at the given index to a C boolean value (0 or 1). Like all tests in Lua, <a href="#lua_toboolean"><code>lua_toboolean</code></a> returns true for any Lua value different from <b>false</b> and <b>nil</b>; otherwise it returns false. -It also returns false when called with a non-valid index. (If you want to accept only actual boolean values, use <a href="#lua_isboolean"><code>lua_isboolean</code></a> to test the value's type.) @@ -4622,7 +4671,7 @@ <pre>lua_CFunction lua_tocfunction (lua_State *L, int index);</pre> <p> -Converts a value at the given acceptable index to a C function. +Converts a value at the given index to a C function. That value must be a C function; otherwise, returns <code>NULL</code>. @@ -4646,7 +4695,7 @@ <pre>lua_Integer lua_tointegerx (lua_State *L, int index, int *isnum);</pre> <p> -Converts the Lua value at the given acceptable index +Converts the Lua value at the given index to the signed integral type <a href="#lua_Integer"><code>lua_Integer</code></a>. The Lua value must be a number or a string convertible to a number (see <a href="#3.4.2">§3.4.2</a>); @@ -4672,7 +4721,7 @@ <pre>const char *lua_tolstring (lua_State *L, int index, size_t *len);</pre> <p> -Converts the Lua value at the given acceptable index to a C string. +Converts the Lua value at the given index to a C string. If <code>len</code> is not <code>NULL</code>, it also sets <code>*len</code> with the string length. The Lua value must be a string or a number; @@ -4714,7 +4763,7 @@ <pre>lua_Number lua_tonumberx (lua_State *L, int index, int *isnum);</pre> <p> -Converts the Lua value at the given acceptable index +Converts the Lua value at the given index to the C type <a href="#lua_Number"><code>lua_Number</code></a> (see <a href="#lua_Number"><code>lua_Number</code></a>). The Lua value must be a number or a string convertible to a number (see <a href="#3.4.2">§3.4.2</a>); @@ -4735,7 +4784,7 @@ <pre>const void *lua_topointer (lua_State *L, int index);</pre> <p> -Converts the value at the given acceptable index to a generic +Converts the value at the given index to a generic C pointer (<code>void*</code>). The value can be a userdata, a table, a thread, or a function; otherwise, <code>lua_topointer</code> returns <code>NULL</code>. @@ -4766,7 +4815,7 @@ <pre>lua_State *lua_tothread (lua_State *L, int index);</pre> <p> -Converts the value at the given acceptable index to a Lua thread +Converts the value at the given index to a Lua thread (represented as <code>lua_State*</code>). This value must be a thread; otherwise, the function returns <code>NULL</code>. @@ -4791,7 +4840,7 @@ <pre>lua_Unsigned lua_tounsignedx (lua_State *L, int index, int *isnum);</pre> <p> -Converts the Lua value at the given acceptable index +Converts the Lua value at the given index to the unsigned integral type <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>. The Lua value must be a number or a string convertible to a number (see <a href="#3.4.2">§3.4.2</a>); @@ -4820,7 +4869,7 @@ <pre>void *lua_touserdata (lua_State *L, int index);</pre> <p> -If the value at the given acceptable index is a full userdata, +If the value at the given index is a full userdata, returns its block address. If the value is a light userdata, returns its pointer. @@ -4835,8 +4884,8 @@ <pre>int lua_type (lua_State *L, int index);</pre> <p> -Returns the type of the value in the given acceptable index, -or <code>LUA_TNONE</code> for a non-valid index. +Returns the type of the value in the given valid index, +or <code>LUA_TNONE</code> for a non-valid (but acceptable) index. The types returned by <a href="#lua_type"><code>lua_type</code></a> are coded by the following constants defined in <code>lua.h</code>: <a name="pdf-LUA_TNIL"><code>LUA_TNIL</code></a>, @@ -4882,6 +4931,18 @@ +<hr><h3><a name="lua_upvalueindex"><code>lua_upvalueindex</code></a></h3><p> +<span class="apii">[-0, +0, –]</span> +<pre>int lua_upvalueindex (int i);</pre> + +<p> +Returns the pseudo-index that represents the <code>i</code>-th upvalue of +the running function (see <a href="#4.4">§4.4</a>). + + + + + <hr><h3><a name="lua_version"><code>lua_version</code></a></h3><p> <span class="apii">[-0, +0, <em>v</em>]</span> <pre>const lua_Number *lua_version (lua_State *L);</pre> @@ -6095,7 +6156,7 @@ <p> Ensures that the value <code>t[fname]</code>, -where <code>t</code> is the value at the valid index <code>idx</code>, +where <code>t</code> is the value at index <code>idx</code>, is a table, and pushes that table onto the stack. Returns true if it finds a previous table there @@ -6127,7 +6188,7 @@ <pre>int luaL_len (lua_State *L, int index);</pre> <p> -Returns the "length" of the value at the given acceptable index +Returns the "length" of the value at the given index as a number; it is equivalent to the '<code>#</code>' operator in Lua (see <a href="#3.4.6">§3.4.6</a>). Raises an error if the result of the operation is not a number. @@ -6242,7 +6303,7 @@ <hr><h3><a name="luaL_newlib"><code>luaL_newlib</code></a></h3><p> <span class="apii">[-0, +1, <em>e</em>]</span> -<pre>int luaL_newlib (lua_State *L, const luaL_Reg *l);</pre> +<pre>void luaL_newlib (lua_State *L, const luaL_Reg *l);</pre> <p> Creates a new table and registers there @@ -6258,7 +6319,7 @@ <hr><h3><a name="luaL_newlibtable"><code>luaL_newlibtable</code></a></h3><p> <span class="apii">[-0, +1, <em>e</em>]</span> -<pre>int luaL_newlibtable (lua_State *L, const luaL_Reg l[]);</pre> +<pre>void luaL_newlibtable (lua_State *L, const luaL_Reg l[]);</pre> <p> Creates a new table with a size optimized @@ -6622,7 +6683,7 @@ <pre>const char *luaL_tolstring (lua_State *L, int idx, size_t *len);</pre> <p> -Converts any Lua value at the given acceptable index to a C string +Converts any Lua value at the given index to a C string in a reasonable format. The resulting string is pushed onto the stack and also returned by the function. @@ -6986,11 +7047,14 @@ <p> If the resulting function has upvalues, -the first upvalue is set to the value of the -global environment or to <code>env</code>, -if that parameter is given. -When loading main chunks, -the first upvalue will be the <code>_ENV</code> variable (see <a href="#2.2">§2.2</a>). +the first upvalue is set to the value of <code>env</code>, +if that parameter is given, +or to the value of the global environment. +(When you load a main chunk, +the resulting function will always have exactly one upvalue, +the <code>_ENV</code> variable (see <a href="#2.2">§2.2</a>). +When you load a binary chunk created from a function (see <a href="#pdf-string.dump"><code>string.dump</code></a>), +the resulting function can have arbitrary upvalues.) <p> @@ -7510,7 +7574,6 @@ <p> - <hr><h3><a name="pdf-package.loaded"><code>package.loaded</code></a></h3> @@ -7546,7 +7609,8 @@ Otherwise, it looks for a function <code>funcname</code> inside the library and returns this function as a C function. -(So, <code>funcname</code> must follow the prototype <a href="#lua_CFunction"><code>lua_CFunction</code></a>). +So, <code>funcname</code> must follow the <a href="#lua_CFunction"><code>lua_CFunction</code></a> prototype +(see <a href="#lua_CFunction"><code>lua_CFunction</code></a>). <p> @@ -7842,7 +7906,7 @@ <p> Returns a formatted version of its variable number of arguments following the description given in its first argument (which must be a string). -The format string follows the same rules as the C function <code>sprintf</code>. +The format string follows the same rules as the ANSI C function <code>sprintf</code>. The only differences are that the options/modifiers <code>*</code>, <code>h</code>, <code>L</code>, <code>l</code>, <code>n</code>, and <code>p</code> are not supported @@ -8306,7 +8370,7 @@ <p> Given a list where all elements are strings or numbers, -returns <code>list[i]..sep..list[i+1] ··· sep..list[j]</code>. +returns the string <code>list[i]..sep..list[i+1] ··· sep..list[j]</code>. The default value for <code>sep</code> is the empty string, the default for <code>i</code> is 1, and the default for <code>j</code> is <code>#list</code>. @@ -8348,10 +8412,17 @@ <p> Removes from <code>list</code> the element at position <code>pos</code>, -shifting down the elements +returning the value of the removed element. +When <code>pos</code> is an integer between 1 and <code>#list</code>, +it shifts down the elements <code>list[pos+1], list[pos+2], ···, list[#list]</code> -and erasing element <code>list[#list]</code>. -Returns the value of the removed element. +and erases element <code>list[#list]</code>; +The index <code>pos</code> can also be 0 when <code>#list</code> is 0, +or <code>#list + 1</code>; +in those cases, the function erases the element <code>list[pos]</code>. + + +<p> The default value for <code>pos</code> is <code>#list</code>, so that a call <code>table.remove(t)</code> removes the last element of list <code>t</code>. @@ -8990,6 +9061,11 @@ (plus an error message as a second result and a system-dependent error code as a third result) and some value different from <b>nil</b> on success. +On non-Posix systems, +the computation of the error message and error code +in case of errors +may be not thread safe, +because they rely on the global C variable <code>errno</code>. <p> @@ -9410,7 +9486,7 @@ <p> If <code>format</code> is not "<code>*t</code>", then <code>date</code> returns the date as a string, -formatted according to the same rules as the C function <code>strftime</code>. +formatted according to the same rules as the ANSI C function <code>strftime</code>. <p> @@ -9421,8 +9497,9 @@ <p> -On some systems, -this function may be not thread safe. +On non-Posix systems, +this function may be not thread safe +because of its reliance on C function <code>gmtime</code> and C function <code>localtime</code>. @@ -9444,7 +9521,7 @@ <p> -This function is equivalent to the C function <code>system</code>. +This function is equivalent to the ANSI C function <code>system</code>. It passes <code>command</code> to be executed by an operating system shell. Its first result is <b>true</b> if the command terminated successfully, @@ -9479,7 +9556,7 @@ <p> -Calls the C function <code>exit</code> to terminate the host program. +Calls the ANSI C function <code>exit</code> to terminate the host program. If <code>code</code> is <b>true</b>, the returned status is <code>EXIT_SUCCESS</code>; if <code>code</code> is <b>false</b>, @@ -9560,8 +9637,13 @@ for the given category. +<p> +This function may be not thread safe +because of its reliance on C function <code>setlocale</code>. + + <p> <hr><h3><a name="pdf-os.time"><code>os.time ([table])</code></a></h3> @@ -9746,7 +9828,7 @@ <p> -Variable names starting with '<code>(</code>' (open parentheses) +Variable names starting with '<code>(</code>' (open parenthesis) represent internal variables (loop control variables, temporaries, varargs, and C function locals). @@ -10415,10 +10497,10 @@ <HR> <SMALL CLASS="footer"> Last update: -Fri Jun 8 16:13:40 BRT 2012 +Thu Mar 21 12:58:59 BRT 2013 </SMALL> <!-- -Last change: revised for Lua 5.2.1 +Last change: revised for Lua 5.2.2 --> </body></html> Modified: trunk/mmex/lib/lua/doc/readme.html =================================================================== --- trunk/mmex/lib/lua/doc/readme.html 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/doc/readme.html 2013-06-09 00:35:36 UTC (rev 4051) @@ -109,7 +109,7 @@ <OL> <LI> Open a terminal window and move to -the top-level directory, which is named <TT>lua-5.2.1</TT>. +the top-level directory, which is named <TT>lua-5.2.2</TT>. The Makefile there controls both the build process and the installation process. <P> <LI> @@ -140,6 +140,8 @@ <P> If you're running Linux and get compilation errors, make sure you have installed the <TT>readline</TT> development package. +If you get link errors after that, +then try "<KBD>make linux MYLIBS=-ltermcap</KBD>". <H3>Installing Lua</H3> <P> @@ -372,7 +374,7 @@ <A HREF="http://www.lua.org/license.html">this</A>. <BLOCKQUOTE STYLE="padding-bottom: 0em"> -Copyright © 1994–2012 Lua.org, PUC-Rio. +Copyright © 1994–2013 Lua.org, PUC-Rio. <P> Permission is hereby granted, free of charge, to any person obtaining a copy @@ -400,10 +402,10 @@ <HR> <SMALL CLASS="footer"> Last update: -Tue May 29 21:57:51 BRT 2012 +Fri Feb 22 09:24:20 BRT 2013 </SMALL> <!-- -Last change: revised for Lua 5.2.1 +Last change: revised for Lua 5.2.2 --> </BODY> Modified: trunk/mmex/lib/lua/src/Makefile =================================================================== --- trunk/mmex/lib/lua/src/Makefile 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/Makefile 2013-06-09 00:35:36 UTC (rev 4051) @@ -103,7 +103,7 @@ generic: $(ALL) linux: - $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline -lncurses" + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline" macosx: $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" Modified: trunk/mmex/lib/lua/src/lapi.c =================================================================== --- trunk/mmex/lib/lua/src/lapi.c 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/lapi.c 2013-06-09 00:35:36 UTC (rev 4051) @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.164 2012/06/08 15:14:04 roberto Exp $ +** $Id: lapi.c,v 2.171 2013/03/16 21:10:18 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ @@ -40,9 +40,18 @@ /* corresponding test */ #define isvalid(o) ((o) != luaO_nilobject) -#define api_checkvalidindex(L, i) api_check(L, isvalid(i), "invalid index") +/* test for pseudo index */ +#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) +/* test for valid but not pseudo index */ +#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) +#define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index") + +#define api_checkstackindex(L, i, o) \ + api_check(L, isstackindex(i, o), "index not in the stack") + + static TValue *index2addr (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { @@ -51,7 +60,7 @@ if (o >= L->top) return NONVALIDVALUE; else return o; } - else if (idx > LUA_REGISTRYINDEX) { + else if (!ispseudo(idx)) { /* negative index */ api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); return L->top + idx; } @@ -142,7 +151,7 @@ ** convert an acceptable stack index into an absolute index */ LUA_API int lua_absindex (lua_State *L, int idx) { - return (idx > 0 || idx <= LUA_REGISTRYINDEX) + return (idx > 0 || ispseudo(idx)) ? idx : cast_int(L->top - L->ci->func + idx); } @@ -174,7 +183,7 @@ StkId p; lua_lock(L); p = index2addr(L, idx); - api_checkvalidindex(L, p); + api_checkstackindex(L, idx, p); while (++p < L->top) setobjs2s(L, p-1, p); L->top--; lua_unlock(L); @@ -186,8 +195,9 @@ StkId q; lua_lock(L); p = index2addr(L, idx); - api_checkvalidindex(L, p); - for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); + api_checkstackindex(L, idx, p); + for (q = L->top; q > p; q--) /* use L->top as a temporary */ + setobjs2s(L, q, q - 1); setobjs2s(L, p, L->top); lua_unlock(L); } @@ -217,7 +227,6 @@ TValue *fr; lua_lock(L); fr = index2addr(L, fromidx); - api_checkvalidindex(L, fr); moveto(L, fr, toidx); lua_unlock(L); } @@ -281,7 +290,7 @@ } -LUA_API void lua_arith (lua_State *L, int op) { +LUA_API void lua_arith (lua_State *L, int op) { StkId o1; /* 1st operand */ StkId o2; /* 2nd operand */ lua_lock(L); @@ -295,7 +304,7 @@ o1 = L->top - 2; o2 = L->top - 1; if (ttisnumber(o1) && ttisnumber(o2)) { - changenvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); + setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); } else luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD)); @@ -611,7 +620,6 @@ StkId t; lua_lock(L); t = index2addr(L, idx); - api_checkvalidindex(L, t); luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); } @@ -621,7 +629,6 @@ StkId t; lua_lock(L); t = index2addr(L, idx); - api_checkvalidindex(L, t); setsvalue2s(L, L->top, luaS_new(L, k)); api_incr_top(L); luaV_gettable(L, t, L->top - 1, L->top - 1); @@ -709,7 +716,6 @@ StkId o; lua_lock(L); o = index2addr(L, idx); - api_checkvalidindex(L, o); api_check(L, ttisuserdata(o), "userdata expected"); if (uvalue(o)->env) { sethvalue(L, L->top, uvalue(o)->env); @@ -743,7 +749,6 @@ lua_lock(L); api_checknelems(L, 2); t = index2addr(L, idx); - api_checkvalidindex(L, t); luaV_settable(L, t, L->top - 2, L->top - 1); L->top -= 2; /* pop index and value */ lua_unlock(L); @@ -755,7 +760,6 @@ lua_lock(L); api_checknelems(L, 1); t = index2addr(L, idx); - api_checkvalidindex(L, t); setsvalue2s(L, L->top++, luaS_new(L, k)); luaV_settable(L, t, L->top - 1, L->top - 2); L->top -= 2; /* pop value and key */ @@ -811,7 +815,6 @@ lua_lock(L); api_checknelems(L, 1); obj = index2addr(L, objindex); - api_checkvalidindex(L, obj); if (ttisnil(L->top - 1)) mt = NULL; else { @@ -821,9 +824,10 @@ switch (ttypenv(obj)) { case LUA_TTABLE: { hvalue(obj)->metatable = mt; - if (mt) + if (mt) { luaC_objbarrierback(L, gcvalue(obj), mt); luaC_checkfinalizer(L, gcvalue(obj), mt); + } break; } case LUA_TUSERDATA: { @@ -850,7 +854,6 @@ lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); - api_checkvalidindex(L, o); api_check(L, ttisuserdata(o), "userdata expected"); if (ttisnil(L->top - 1)) uvalue(o)->env = NULL; @@ -937,7 +940,7 @@ func = 0; else { StkId o = index2addr(L, errfunc); - api_checkvalidindex(L, o); + api_checkstackindex(L, errfunc, o); func = savestack(L, o); } c.func = L->top - (nargs+1); /* function to be called */ @@ -1006,7 +1009,7 @@ } -LUA_API int lua_status (lua_State *L) { +LUA_API int lua_status (lua_State *L) { return L->status; } @@ -1103,7 +1106,7 @@ lua_lock(L); api_checknelems(L, 1); luaG_errormsg(L); - lua_unlock(L); + /* code unreachable; will unlock when control actually leaves the kernel */ return 0; /* to avoid warnings */ } Modified: trunk/mmex/lib/lua/src/lauxlib.c =================================================================== --- trunk/mmex/lib/lua/src/lauxlib.c 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/lauxlib.c 2013-06-09 00:35:36 UTC (rev 4051) @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.244 2012/05/31 20:28:45 roberto Exp $ +** $Id: lauxlib.c,v 1.248 2013/03/21 13:54:57 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -84,7 +84,7 @@ if (*ar->namewhat != '\0') /* is there a name? */ lua_pushfstring(L, "function " LUA_QS, ar->name); else if (*ar->what == 'm') /* main? */ - lua_pushfstring(L, "main chunk"); + lua_pushliteral(L, "main chunk"); else if (*ar->what == 'C') { if (pushglobalfuncname(L, ar)) { lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); @@ -158,7 +158,8 @@ if (strcmp(ar.namewhat, "method") == 0) { narg--; /* do not count `self' */ if (narg == 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling " LUA_QS " on bad self", ar.name); + return luaL_error(L, "calling " LUA_QS " on bad self (%s)", + ar.name, extramsg); } if (ar.name == NULL) ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; @@ -214,7 +215,7 @@ if (fname) lua_pushfstring(L, "%s: %s", fname, strerror(en)); else - lua_pushfstring(L, "%s", strerror(en)); + lua_pushstring(L, strerror(en)); lua_pushinteger(L, en); return 3; } @@ -438,7 +439,7 @@ if (B->size - B->n < sz) { /* not enough space? */ char *newbuff; size_t newsize = B->size * 2; /* double buffer size */ - if (newsize - B->n < sz) /* not bit enough? */ + if (newsize - B->n < sz) /* not big enough? */ newsize = B->n + sz; if (newsize < B->n || newsize - B->n < sz) luaL_error(L, "buffer too large"); @@ -598,7 +599,7 @@ lf->n = 0; do { c = getc(lf->f); - if (c == EOF || c != *(unsigned char *)p++) return c; + if (c == EOF || c != *(const unsigned char *)p++) return c; lf->buff[lf->n++] = c; /* to be read by the parser */ } while (*p != '\0'); lf->n = 0; /* prefix matched; discard it */ Modified: trunk/mmex/lib/lua/src/lbaselib.c =================================================================== --- trunk/mmex/lib/lua/src/lbaselib.c 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/lbaselib.c 2013-06-09 00:35:36 UTC (rev 4051) @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.274 2012/04/27 14:13:19 roberto Exp $ +** $Id: lbaselib.c,v 1.276 2013/02/21 13:44:53 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -242,10 +242,16 @@ } -static int load_aux (lua_State *L, int status) { - if (status == LUA_OK) +static int load_aux (lua_State *L, int status, int envidx) { + if (status == LUA_OK) { + if (envidx != 0) { /* 'env' parameter? */ + lua_pushvalue(L, envidx); /* environment for loaded function */ + if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ + lua_pop(L, 1); /* remove 'env' if not used by previous call */ + } return 1; - else { + } + else { /* error (message is on top of the stack) */ lua_pushnil(L); lua_insert(L, -2); /* put before error message */ return 2; /* return nil plus error message */ @@ -256,13 +262,9 @@ static int luaB_loadfile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); const char *mode = luaL_optstring(L, 2, NULL); - int env = !lua_isnone(L, 3); /* 'env' parameter? */ + int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ int status = luaL_loadfilex(L, fname, mode); - if (status == LUA_OK && env) { /* 'env' parameter? */ - lua_pushvalue(L, 3); - lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */ - } - return load_aux(L, status); + return load_aux(L, status, env); } @@ -307,9 +309,9 @@ static int luaB_load (lua_State *L) { int status; size_t l; - int top = lua_gettop(L); const char *s = lua_tolstring(L, 1, &l); const char *mode = luaL_optstring(L, 3, "bt"); + int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ if (s != NULL) { /* loading a string? */ const char *chunkname = luaL_optstring(L, 2, s); status = luaL_loadbufferx(L, s, l, chunkname, mode); @@ -320,11 +322,7 @@ lua_settop(L, RESERVEDSLOT); /* create reserved slot */ status = lua_load(L, generic_reader, NULL, chunkname, mode); } - if (status == LUA_OK && top >= 4) { /* is there an 'env' argument */ - lua_pushvalue(L, 4); /* environment for loaded function */ - lua_setupvalue(L, -2, 1); /* set it as 1st upvalue */ - } - return load_aux(L, status); + return load_aux(L, status, env); } /* }====================================================== */ @@ -338,7 +336,8 @@ static int luaB_dofile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); lua_settop(L, 1); - if (luaL_loadfile(L, fname) != LUA_OK) lua_error(L); + if (luaL_loadfile(L, fname) != LUA_OK) + return lua_error(L); lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); return dofilecont(L); } Modified: trunk/mmex/lib/lua/src/lbitlib.c =================================================================== --- trunk/mmex/lib/lua/src/lbitlib.c 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/lbitlib.c 2013-06-09 00:35:36 UTC (rev 4051) @@ -1,5 +1,5 @@ /* -** $Id: lbitlib.c,v 1.16 2011/06/20 16:35:23 roberto Exp $ +** $Id: lbitlib.c,v 1.18 2013/03/19 13:19:12 roberto Exp $ ** Standard library for bitwise operations ** See Copyright Notice in lua.h */ @@ -147,7 +147,9 @@ /* ** get field and width arguments for field-manipulation functions, -** checking whether they are valid +** checking whether they are valid. +** ('luaL_error' called without 'return' to avoid later warnings about +** 'width' being used uninitialized.) */ static int fieldargs (lua_State *L, int farg, int *width) { int f = luaL_checkint(L, farg); Modified: trunk/mmex/lib/lua/src/lcode.c =================================================================== --- trunk/mmex/lib/lua/src/lcode.c 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/lcode.c 2013-06-09 00:35:36 UTC (rev 4051) @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.60 2011/08/30 16:26:41 roberto Exp $ +** $Id: lcode.c,v 2.62 2012/08/16 17:34:28 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -330,10 +330,9 @@ setnvalue(&o, r); if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ /* use raw representation as key to avoid numeric problems */ - setsvalue(L, L->top, luaS_newlstr(L, (char *)&r, sizeof(r))); - incr_top(L); - n = addk(fs, L->top - 1, &o); - L->top--; + setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); + n = addk(fs, L->top - 1, &o); + L->top--; } else n = addk(fs, &o, &o); /* regular case */ @@ -426,7 +425,7 @@ luaK_nil(fs, reg, 1); break; } - case VFALSE: case VTRUE: { + case VFALSE: case VTRUE: { luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); break; } Modified: trunk/mmex/lib/lua/src/lcorolib.c =================================================================== --- trunk/mmex/lib/lua/src/lcorolib.c 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/lcorolib.c 2013-06-09 00:35:36 UTC (rev 4051) @@ -1,5 +1,5 @@ /* -** $Id: lcorolib.c,v 1.4 2012/04/27 18:59:04 roberto Exp $ +** $Id: lcorolib.c,v 1.5 2013/02/21 13:44:53 roberto Exp $ ** Coroutine Library ** See Copyright Notice in lua.h */ @@ -73,7 +73,7 @@ lua_insert(L, -2); lua_concat(L, 2); } - lua_error(L); /* propagate error */ + return lua_error(L); /* propagate error */ } return r; } Modified: trunk/mmex/lib/lua/src/ldebug.c =================================================================== --- trunk/mmex/lib/lua/src/ldebug.c 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/ldebug.c 2013-06-09 00:35:36 UTC (rev 4051) @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.89 2012/01/20 22:05:50 roberto Exp $ +** $Id: ldebug.c,v 2.90 2012/08/16 17:34:28 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -196,7 +196,7 @@ static void collectvalidlines (lua_State *L, Closure *f) { if (noLuaClosure(f)) { setnilvalue(L->top); - incr_top(L); + api_incr_top(L); } else { int i; @@ -204,7 +204,7 @@ int *lineinfo = f->l.p->lineinfo; Table *t = luaH_new(L); /* new table to store active lines */ sethvalue(L, L->top, t); /* push it on stack */ - incr_top(L); + api_incr_top(L); setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ @@ -285,7 +285,7 @@ status = auxgetinfo(L, what, ar, cl, ci); if (strchr(what, 'f')) { setobjs2s(L, L->top, func); - incr_top(L); + api_incr_top(L); } if (strchr(what, 'L')) collectvalidlines(L, cl); @@ -563,7 +563,7 @@ if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); setobjs2s(L, L->top, L->top - 1); /* move argument */ setobjs2s(L, L->top - 1, errfunc); /* push function */ - incr_top(L); + L->top++; luaD_call(L, L->top - 2, 1, 0); /* call it */ } luaD_throw(L, LUA_ERRRUN); Modified: trunk/mmex/lib/lua/src/ldo.c =================================================================== --- trunk/mmex/lib/lua/src/ldo.c 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/ldo.c 2013-06-09 00:35:36 UTC (rev 4051) @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.105 2012/06/08 15:14:04 roberto Exp $ +** $Id: ldo.c,v 2.108 2012/10/01 14:05:04 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -311,6 +311,7 @@ ci->top = L->top + LUA_MINSTACK; lua_assert(ci->top <= L->stack_last); ci->callstatus = 0; + luaC_checkGC(L); /* stack grow uses memory */ if (L->hookmask & LUA_MASKCALL) luaD_hook(L, LUA_HOOKCALL, -1); lua_unlock(L); @@ -338,6 +339,7 @@ ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus = CIST_LUA; L->top = ci->top; + luaC_checkGC(L); /* stack grow uses memory */ if (L->hookmask & LUA_MASKCALL) callhook(L, ci); return 0; @@ -393,7 +395,6 @@ luaV_execute(L); /* call it */ if (!allowyield) L->nny--; L->nCcalls--; - luaC_checkGC(L); } @@ -402,7 +403,11 @@ int n; lua_assert(ci->u.c.k != NULL); /* must have a continuation */ lua_assert(L->nny == 0); - /* finish 'lua_callk' */ + if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ + ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */ + L->errfunc = ci->u.c.old_errfunc; + } + /* finish 'lua_callk'/'lua_pcall' */ adjustresults(L, ci->nresults); /* call continuation function */ if (!(ci->callstatus & CIST_STAT)) /* no call status? */ @@ -473,7 +478,7 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { L->top = firstArg; /* remove args from the stack */ setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ - incr_top(L); + api_incr_top(L); luaD_throw(L, -1); /* jump back to 'lua_resume' */ } @@ -558,7 +563,7 @@ api_checknelems(L, nresults); if (L->nny > 0) { if (L != G(L)->mainthread) - luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); + luaG_runerror(L, "attempt to yield across a C-call boundary"); else luaG_runerror(L, "attempt to yield from outside a coroutine"); } Modified: trunk/mmex/lib/lua/src/lfunc.c =================================================================== --- trunk/mmex/lib/lua/src/lfunc.c 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/lfunc.c 2013-06-09 00:35:36 UTC (rev 4051) @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 2.29 2012/05/08 13:53:33 roberto Exp $ +** $Id: lfunc.c,v 2.30 2012/10/03 12:36:46 roberto Exp $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -52,12 +52,12 @@ while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { GCObject *o = obj2gco(p); lua_assert(p->v != &p->u.value); + lua_assert(!isold(o) || isold(obj2gco(L))); if (p->v == level) { /* found a corresponding upvalue? */ if (isdead(g, o)) /* is it dead? */ changewhite(o); /* resurrect it */ return p; } - resetoldbit(o); /* may create a newer upval after this one */ pp = &p->next; } /* not found: create a new one */ Modified: trunk/mmex/lib/lua/src/lgc.c =================================================================== --- trunk/mmex/lib/lua/src/lgc.c 2013-06-09 00:30:34 UTC (rev 4050) +++ trunk/mmex/lib/lua/src/lgc.c 2013-06-09 00:35:36 UTC (rev 4051) @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.133 2012/05/31 21:28:59 roberto Exp $ +** $Id: lgc.c,v 2.140 2013/03/16 21:10:18 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -43,24 +43,15 @@ */ #define STEPMULADJ 200 + /* ** macro to adjust 'pause': 'pause' is actually used like ** 'pause / PAUSEADJ' (value chosen by tests) */ -#define PAUSEADJ 200 +#define PAUSEADJ 100 - - /* -** standard negative debt for GC; a reasonable "time" to wait before -** starting a new cycle -*/ -#define stddebtest(g,e) (-cast(l_mem, (e)/PAUSEADJ) * g->gcpause) -#define stddebt(g) stddebtest(g, gettotalbytes(g)) - - -/* ** 'makewhite' erases all color bits plus the old bit and then ** sets only the current white bit */ @@ -144,9 +135,9 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { global_State *g = G(L); lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - lua_assert(isgenerational(g) || g->gcstate != GCSpause); + lua_assert(g->gcstate != GCSpause); lua_assert(gch(o)->tt != LUA_TTABLE); - if (keepinvariant(g)) /* must keep invariant? */ + if (keepinvariantout(g)) /* must keep invariant? */ reallymarkobject(g, v); /* restore invariant */ else { /* sweep phase */ lua_assert(issweepphase(g)); @@ -343,7 +334,7 @@ ** mark root set and reset all gray lists, to start a new ** incremental (or full) collection */ -static void markroot (global_State *g) { +static void restartcollection (global_State *g) { g->gray = g->grayagain = NULL; g->weak = g->allweak = g->ephemeron = NULL; markobject(g, g->mainthread); @@ -459,7 +450,7 @@ else /* not weak */ traversestrongtable(g, h); return sizeof(Table) + sizeof(TValue) * h->sizearray + - sizeof(Node) * sizenode(h); + sizeof(Node) * cast(size_t, sizenode(h)); } @@ -796,7 +787,7 @@ g->allgc = o; resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ lua_assert(!isold(o)); /* see MOVE OLD rule */ - if (!keepinvariant(g)) /* not keeping invariant? */ + if (!keepinvariantout(g)) /* not keeping invariant? */ makewhite(g, o); /* "sweep" object */ return o; } @@ -855,7 +846,7 @@ while ((curr = *p) != NULL) { /* traverse all finalizable objects */ lua_assert(!isfinalized(curr)); lua_assert(testbit(gch(curr)->marked, SEPARATED)); - if (!(all || iswhite(curr))) /* not being collected? */ + if (!(iswhite(curr) || all)) /* not being collected? */ p = &gch(curr)->next; /* don't bother with it */ else { l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ @@ -891,7 +882,7 @@ ho->next = g->finobj; /* link it in list 'finobj' */ g->finobj = o; l_setbit(ho->marked, SEPARATED); /* mark it as such */ - if (!keepinvariant(g)) /* not keeping invariant? */ + if (!keepinvariantout(g)) /* not keeping invariant? */ makewhite(g, o); /* "sweep" object */ else resetoldbit(o); /* see MOVE OLD rule */ @@ -908,6 +899,21 @@ */ +/* +** set a reasonable "time" to wait before starting a new GC cycle; +** cycle will start when memory use hits threshold +*/ +static void setpause (global_State *g, l_mem estimate) { + l_mem debt, threshold; + estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ + threshold = (g->gcpause < MAX_LMEM / esti... [truncated message content] |
From: <ste...@us...> - 2013-06-09 02:01:48
|
Revision: 4052 http://sourceforge.net/p/moneymanagerex/code/4052 Author: stef145g Date: 2013-06-09 02:01:45 +0000 (Sun, 09 Jun 2013) Log Message: ----------- Update to SQLite3: Version 3.7.17 wxSQLite3: Version 3.0.3 Modified Paths: -------------- trunk/mmex/lib/readme.txt trunk/mmex/lib/sqlite/sqlite3.c trunk/mmex/lib/sqlite/sqlite3.def trunk/mmex/lib/sqlite/sqlite3.h trunk/mmex/lib/sqlite/sqlite3ext.h trunk/mmex/lib/wxsqlite/Readme.txt trunk/mmex/src/constants.cpp Modified: trunk/mmex/lib/readme.txt =================================================================== --- trunk/mmex/lib/readme.txt 2013-06-09 00:35:36 UTC (rev 4051) +++ trunk/mmex/lib/readme.txt 2013-06-09 02:01:45 UTC (rev 4052) @@ -1,25 +1,29 @@ External libraries' sources here. -wxSQLite3 and sqlite3 sources from wxSQLite3 +wxSQLite3 and sqlite3 sources from: +http://svn.code.sf.net/p/wxcode/code/trunk/wxCode/components/wxsqlite3/ + (ensures wxSQLite3 and sqlite3 are in sync) -------------------------------------------- -Current versions: wxSQLite3 Version: 3.0.2 - SQLite Version: 3.7.16 +Current versions: wxSQLite3 Version: 3.0.3 + SQLite Version: 3.7.17 =============================================================================== -Copy all files From: wxsqlite3\src - to : MoneyManagerEX\trunk\mmex\lib\wxsqlite +Copy file +from: wxsqlite3\Readme.txt +to : MoneyManagerEX\trunk\mmex\lib\wxsqlite\Readme.txt -Copy all files From: wxsqlite3\include\wx - to : MoneyManagerEX\trunk\mmex\lib\wxsqlite\wx +Copy all files +From: wxsqlite3\src +to : MoneyManagerEX\trunk\mmex\lib\wxsqlite -Copy all files from: wxsqlite3\sqlite3\secure\src - to : MoneyManagerEX\trunk\mmex\lib\sqlite +From: wxsqlite3\include\wx +to : MoneyManagerEX\trunk\mmex\lib\wxsqlite\wx -Copy file from: wxsqlite3\Readme.txt - to : MoneyManagerEX\trunk\mmex\lib\wxsqlite\Readme.txt +from: wxsqlite3\sqlite3\secure\src +to : MoneyManagerEX\trunk\mmex\lib\sqlite =============================================================================== -Source files for: wxSQLite3 Version 3.0.2 +Source files for: wxSQLite3 Version 3.0.3 wxsqlite3.cpp Headers of for: wxSQLite3 - wx: @@ -40,7 +44,7 @@ sqlite3secure.c sqlite3.def -Source files for: sqlite3 Version 3.7.16 +Source files for: sqlite3 Version 3.7.17 sqlite3.c sqlite3.h sqlite3ext.h Modified: trunk/mmex/lib/sqlite/sqlite3.c =================================================================== --- trunk/mmex/lib/sqlite/sqlite3.c 2013-06-09 00:35:36 UTC (rev 4051) +++ trunk/mmex/lib/sqlite/sqlite3.c 2013-06-09 02:01:45 UTC (rev 4052) @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.7.16.2. By combining all the individual C code files into this +** version 3.7.17. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -362,12 +362,12 @@ ** We support that for legacy. */ #if !defined(SQLITE_THREADSAFE) -#if defined(THREADSAFE) -# define SQLITE_THREADSAFE THREADSAFE -#else -# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ +# if defined(THREADSAFE) +# define SQLITE_THREADSAFE THREADSAFE +# else +# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ +# endif #endif -#endif /* ** Powersafe overwrite is on by default. But can be turned off using @@ -678,9 +678,9 @@ ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.7.16.2" -#define SQLITE_VERSION_NUMBER 3007016 -#define SQLITE_SOURCE_ID "2013-04-12 11:52:43 cbea02d93865ce0e06789db95fd9168ebac970c7" +#define SQLITE_VERSION "3.7.17" +#define SQLITE_VERSION_NUMBER 3007017 +#define SQLITE_SOURCE_ID "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -996,6 +996,8 @@ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ #define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */ +#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */ #define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ /* end-of-error-codes */ @@ -1046,6 +1048,7 @@ #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) +#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) @@ -1065,6 +1068,8 @@ #define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8)) #define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8)) #define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8)) +#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8)) +#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations @@ -1304,6 +1309,9 @@ void (*xShmBarrier)(sqlite3_file*); int (*xShmUnmap)(sqlite3_file*, int deleteFlag); /* Methods above are valid for version 2 */ + int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); + int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p); + /* Methods above are valid for version 3 */ /* Additional methods may be added in future releases */ }; @@ -1440,7 +1448,8 @@ ** it is able to override built-in [PRAGMA] statements. ** ** <li>[[SQLITE_FCNTL_BUSYHANDLER]] -** ^This file-control may be invoked by SQLite on the database file handle +** ^The [SQLITE_FCNTL_BUSYHANDLER] +** file-control may be invoked by SQLite on the database file handle ** shortly after it is opened in order to provide a custom VFS with access ** to the connections busy-handler callback. The argument is of type (void **) ** - an array of two (void *) values. The first (void *) actually points @@ -1451,13 +1460,24 @@ ** current operation. ** ** <li>[[SQLITE_FCNTL_TEMPFILENAME]] -** ^Application can invoke this file-control to have SQLite generate a +** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control +** to have SQLite generate a ** temporary filename using the same algorithm that is followed to generate ** temporary filenames for TEMP tables and other internal uses. The ** argument should be a char** which will be filled with the filename ** written into memory obtained from [sqlite3_malloc()]. The caller should ** invoke [sqlite3_free()] on the result to avoid a memory leak. ** +** <li>[[SQLITE_FCNTL_MMAP_SIZE]] +** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the +** maximum number of bytes that will be used for memory-mapped I/O. +** The argument is a pointer to a value of type sqlite3_int64 that +** is an advisory maximum number of bytes in the file to memory map. The +** pointer is overwritten with the old value. The limit is not changed if +** the value originally pointed to is negative, and so the current limit +** can be queried by passing in a pointer to a negative number. This +** file-control is used internally to implement [PRAGMA mmap_size]. +** ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -1476,6 +1496,7 @@ #define SQLITE_FCNTL_PRAGMA 14 #define SQLITE_FCNTL_BUSYHANDLER 15 #define SQLITE_FCNTL_TEMPFILENAME 16 +#define SQLITE_FCNTL_MMAP_SIZE 18 /* ** CAPI3REF: Mutex Handle @@ -2142,7 +2163,9 @@ ** page cache implementation into that object.)^ </dd> ** ** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt> -** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a +** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite +** global [error log]. +** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a ** function with a call signature of void(*)(void*,int,const char*), ** and a pointer to void. ^If the function pointer is not NULL, it is ** invoked by [sqlite3_log()] to process each logging event. ^If the @@ -2188,12 +2211,12 @@ ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. -** </dl> +** </dd> ** ** [[SQLITE_CONFIG_SQLLOG]] ** <dt>SQLITE_CONFIG_SQLLOG ** <dd>This option is only available if sqlite is compiled with the -** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should +** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should ** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int). ** The second should be of type (void*). The callback is invoked by the library ** in three separate circumstances, identified by the value passed as the @@ -2203,7 +2226,23 @@ ** fourth parameter is 1, then the SQL statement that the third parameter ** points to has just been executed. Or, if the fourth parameter is 2, then ** the connection being passed as the second parameter is being closed. The -** third parameter is passed NULL In this case. +** third parameter is passed NULL In this case. An example of using this +** configuration option can be seen in the "test_sqllog.c" source file in +** the canonical SQLite source tree.</dd> +** +** [[SQLITE_CONFIG_MMAP_SIZE]] +** <dt>SQLITE_CONFIG_MMAP_SIZE +** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values +** that are the default mmap size limit (the default setting for +** [PRAGMA mmap_size]) and the maximum allowed mmap size limit. +** The default setting can be overridden by each database connection using +** either the [PRAGMA mmap_size] command, or by using the +** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size +** cannot be changed at run-time. Nor may the maximum allowed mmap size +** exceed the compile-time maximum mmap size set by the +** [SQLITE_MAX_MMAP_SIZE] compile-time option. +** If either argument to this option is negative, then that argument is +** changed to its compile-time default. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -2227,6 +2266,7 @@ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ +#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ /* ** CAPI3REF: Database Connection Configuration Options @@ -3060,6 +3100,9 @@ ** as each triggered subprogram is entered. The callbacks for triggers ** contain a UTF-8 SQL comment that identifies the trigger.)^ ** +** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit +** the length of [bound parameter] expansion in the output of sqlite3_trace(). +** ** ^The callback function registered by sqlite3_profile() is invoked ** as each SQL statement finishes. ^The profile callback contains ** the original statement text and an estimate of wall-clock time @@ -3598,7 +3641,8 @@ ** <li> ** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it ** always used to do, [sqlite3_step()] will automatically recompile the SQL -** statement and try to run it again. +** statement and try to run it again. As many as [SQLITE_MAX_SCHEMA_RETRY] +** retries will occur before sqlite3_step() gives up and returns an error. ** </li> ** ** <li> @@ -3802,6 +3846,9 @@ ** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). ** ** ^The third argument is the value to bind to the parameter. +** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16() +** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter +** is ignored and the end result is the same as sqlite3_bind_null(). ** ** ^(In those routines that have a fourth argument, its value is the ** number of bytes in the parameter. To be clear: the value is the @@ -4758,7 +4805,7 @@ ** the content before returning. ** ** The typedef is necessary to work around problems in certain -** C++ compilers. See ticket #2191. +** C++ compilers. */ typedef void (*sqlite3_destructor_type)(void*); #define SQLITE_STATIC ((sqlite3_destructor_type)0) @@ -5557,11 +5604,20 @@ ** ^This interface loads an SQLite extension library from the named file. ** ** ^The sqlite3_load_extension() interface attempts to load an -** SQLite extension library contained in the file zFile. +** [SQLite extension] library contained in the file zFile. If +** the file cannot be loaded directly, attempts are made to load +** with various operating-system specific extensions added. +** So for example, if "samplelib" cannot be loaded, then names like +** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might +** be tried also. ** ** ^The entry point is zProc. -** ^zProc may be 0, in which case the name of the entry point -** defaults to "sqlite3_extension_init". +** ^(zProc may be 0, in which case SQLite will try to come up with an +** entry point name on its own. It first tries "sqlite3_extension_init". +** If that does not work, it constructs a name "sqlite3_X_init" where the +** X is consists of the lower-case equivalent of all ASCII alphabetic +** characters in the filename from the last "/" to the first following +** "." and omitting any initial "lib".)^ ** ^The sqlite3_load_extension() interface returns ** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. ** ^If an error occurs and pzErrMsg is not 0, then the @@ -5587,11 +5643,11 @@ ** CAPI3REF: Enable Or Disable Extension Loading ** ** ^So as not to open security holes in older applications that are -** unprepared to deal with extension loading, and as a means of disabling -** extension loading while evaluating user-entered SQL, the following API +** unprepared to deal with [extension loading], and as a means of disabling +** [extension loading] while evaluating user-entered SQL, the following API ** is provided to turn the [sqlite3_load_extension()] mechanism on and off. ** -** ^Extension loading is off by default. See ticket #1863. +** ^Extension loading is off by default. ** ^Call the sqlite3_enable_load_extension() routine with onoff==1 ** to turn extension loading on and call it with onoff==0 to turn ** it back off again. @@ -5603,7 +5659,7 @@ ** ** ^This interface causes the xEntryPoint() function to be invoked for ** each new [database connection] that is created. The idea here is that -** xEntryPoint() is the entry point for a statically linked SQLite extension +** xEntryPoint() is the entry point for a statically linked [SQLite extension] ** that is to be automatically loaded into all new database connections. ** ** ^(Even though the function prototype shows that xEntryPoint() takes @@ -7384,9 +7440,24 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* +** CAPI3REF: String Globbing +* +** ^The [sqlite3_strglob(P,X)] interface returns zero if string X matches +** the glob pattern P, and it returns non-zero if string X does not match +** the glob pattern P. ^The definition of glob pattern matching used in +** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the +** SQL dialect used by SQLite. ^The sqlite3_strglob(P,X) function is case +** sensitive. +** +** Note that this routine returns zero on a match and non-zero if the strings +** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()]. +*/ +SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr); + +/* ** CAPI3REF: Error Logging Interface ** -** ^The [sqlite3_log()] interface writes a message into the error log +** ^The [sqlite3_log()] interface writes a message into the [error log] ** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. ** ^If logging is enabled, the zFormat string and subsequent arguments are ** used with [sqlite3_snprintf()] to generate the final output string. @@ -8071,6 +8142,7 @@ */ #ifndef SQLITE_TEMP_STORE # define SQLITE_TEMP_STORE 1 +# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */ #endif /* @@ -8218,8 +8290,51 @@ # define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) #endif +/* +** Disable MMAP on platforms where it is known to not work +*/ +#if defined(__OpenBSD__) || defined(__QNXNTO__) +# undef SQLITE_MAX_MMAP_SIZE +# define SQLITE_MAX_MMAP_SIZE 0 +#endif /* +** Default maximum size of memory used by memory-mapped I/O in the VFS +*/ +#ifdef __APPLE__ +# include <TargetConditionals.h> +# if TARGET_OS_IPHONE +# undef SQLITE_MAX_MMAP_SIZE +# define SQLITE_MAX_MMAP_SIZE 0 +# endif +#endif +#ifndef SQLITE_MAX_MMAP_SIZE +# if defined(__linux__) \ + || defined(_WIN32) \ + || (defined(__APPLE__) && defined(__MACH__)) \ + || defined(__sun) +# define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */ +# else +# define SQLITE_MAX_MMAP_SIZE 0 +# endif +# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */ +#endif + +/* +** The default MMAP_SIZE is zero on all platforms. Or, even if a larger +** default MMAP_SIZE is specified at compile-time, make sure that it does +** not exceed the maximum mmap size. +*/ +#ifndef SQLITE_DEFAULT_MMAP_SIZE +# define SQLITE_DEFAULT_MMAP_SIZE 0 +# define SQLITE_DEFAULT_MMAP_SIZE_xc 1 /* Exclude from ctime.c */ +#endif +#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE +# undef SQLITE_DEFAULT_MMAP_SIZE +# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE +#endif + +/* ** An instance of the following structure is used to store the busy-handler ** callback for a given sqlite handle. ** @@ -8439,6 +8554,7 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64); SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); @@ -8515,6 +8631,7 @@ #define BTREE_TEXT_ENCODING 5 #define BTREE_USER_VERSION 6 #define BTREE_INCR_VACUUM 7 +#define BTREE_APPLICATION_ID 8 /* ** Values that may be OR'd together to form the second argument of an @@ -9140,6 +9257,12 @@ #define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ /* +** Flags that make up the mask passed to sqlite3PagerAcquire(). +*/ +#define PAGER_ACQUIRE_NOCONTENT 0x01 /* Do not load data from disk */ +#define PAGER_ACQUIRE_READONLY 0x02 /* Read-only page is acceptable */ + +/* ** The remainder of this file contains the declarations of the functions ** that make up the Pager sub-system API. See source code comments for ** a detailed description of each routine. @@ -9163,6 +9286,7 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64); SQLITE_PRIVATE void sqlite3PagerShrink(Pager*); SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int); SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); @@ -9309,6 +9433,8 @@ #define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */ #define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ +#define PGHDR_MMAP 0x040 /* This is an mmap page object */ + /* Initialize and shutdown the page cache subsystem */ SQLITE_PRIVATE int sqlite3PcacheInitialize(void); SQLITE_PRIVATE void sqlite3PcacheShutdown(void); @@ -9520,14 +9646,6 @@ # define SQLITE_OS_WINRT 0 #endif -/* -** When compiled for WinCE or WinRT, there is no concept of the current -** directory. - */ -#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT -# define SQLITE_CURDIR 1 -#endif - /* If the SET_FULLSYNC macro is not defined above, then make it ** a no-op */ @@ -9680,6 +9798,8 @@ SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int); SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id); SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int); +SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **); +SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *); /* @@ -9919,6 +10039,7 @@ int nDb; /* Number of backends currently in use */ int flags; /* Miscellaneous flags. See below */ i64 lastRowid; /* ROWID of most recent insert (see above) */ + i64 szMmap; /* Default mmap_size setting */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ @@ -11155,6 +11276,8 @@ #define NC_HasAgg 0x02 /* One or more aggregate functions seen */ #define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */ #define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */ +#define NC_AsMaybe 0x10 /* Resolve to AS terms of the result set only + ** if no other resolution is available */ /* ** An instance of the following structure contains all information @@ -11590,6 +11713,8 @@ void *pHeap; /* Heap storage space */ int nHeap; /* Size of pHeap[] */ int mnReq, mxReq; /* Min and max heap requests sizes */ + sqlite3_int64 szMmap; /* mmap() space per open file */ + sqlite3_int64 mxMmap; /* Maximum value for szMmap */ void *pScratch; /* Scratch memory */ int szScratch; /* Size of each scratch buffer */ int nScratch; /* Number of scratch buffers */ @@ -11624,6 +11749,7 @@ int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */ Parse *pParse; /* Parser context. */ int walkerDepth; /* Number of subqueries */ + u8 bSelectDepthFirst; /* Do subqueries first */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int i; /* Integer value */ @@ -12127,6 +12253,12 @@ SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n); SQLITE_PRIVATE u8 sqlite3HexToInt(int h); SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); + +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \ + defined(SQLITE_DEBUG_OS_TRACE) +SQLITE_PRIVATE const char *sqlite3ErrName(int); +#endif + SQLITE_PRIVATE const char *sqlite3ErrStr(int); SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); @@ -12611,6 +12743,8 @@ (void*)0, /* pHeap */ 0, /* nHeap */ 0, 0, /* mnHeap, mxHeap */ + SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */ + SQLITE_MAX_MMAP_SIZE, /* mxMmap */ (void*)0, /* pScratch */ 0, /* szScratch */ 0, /* nScratch */ @@ -12734,15 +12868,15 @@ #ifdef SQLITE_COVERAGE_TEST "COVERAGE_TEST", #endif -#ifdef SQLITE_CURDIR - "CURDIR", -#endif #ifdef SQLITE_DEBUG "DEBUG", #endif #ifdef SQLITE_DEFAULT_LOCKING_MODE "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE), #endif +#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc) + "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE), +#endif #ifdef SQLITE_DISABLE_DIRSYNC "DISABLE_DIRSYNC", #endif @@ -12833,6 +12967,9 @@ #ifdef SQLITE_LOCK_TRACE "LOCK_TRACE", #endif +#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc) + "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE), +#endif #ifdef SQLITE_MAX_SCHEMA_RETRY "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY), #endif @@ -12890,11 +13027,6 @@ #ifdef SQLITE_OMIT_CHECK "OMIT_CHECK", #endif -/* // redundant -** #ifdef SQLITE_OMIT_COMPILEOPTION_DIAGS -** "OMIT_COMPILEOPTION_DIAGS", -** #endif -*/ #ifdef SQLITE_OMIT_COMPLETE "OMIT_COMPLETE", #endif @@ -13036,13 +13168,13 @@ #ifdef SQLITE_TCL "TCL", #endif -#ifdef SQLITE_TEMP_STORE +#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc) "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE), #endif #ifdef SQLITE_TEST "TEST", #endif -#ifdef SQLITE_THREADSAFE +#if defined(SQLITE_THREADSAFE) "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE), #endif #ifdef SQLITE_USE_ALLOCA @@ -13068,8 +13200,11 @@ /* Since ArraySize(azCompileOpt) is normally in single digits, a ** linear search is adequate. No need for a binary search. */ for(i=0; i<ArraySize(azCompileOpt); i++){ - if( (sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0) - && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1; + if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0 + && sqlite3CtypeMap[(unsigned char)azCompileOpt[i][n]]==0 + ){ + return 1; + } } return 0; } @@ -13127,6 +13262,14 @@ #define _VDBEINT_H_ /* +** The maximum number of times that a statement will try to reparse +** itself before giving up and returning SQLITE_SCHEMA. +*/ +#ifndef SQLITE_MAX_SCHEMA_RETRY +# define SQLITE_MAX_SCHEMA_RETRY 50 +#endif + +/* ** SQL is translated into a sequence of instructions to be ** executed by a virtual machine. Each instruction is an instance ** of the following structure. @@ -15092,6 +15235,26 @@ return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp); } +#if SQLITE_MAX_MMAP_SIZE>0 +/* The real implementation of xFetch and xUnfetch */ +SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){ + DO_OS_MALLOC_TEST(id); + return id->pMethods->xFetch(id, iOff, iAmt, pp); +} +SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){ + return id->pMethods->xUnfetch(id, iOff, p); +} +#else +/* No-op stubs to use when memory-mapped I/O is disabled */ +SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){ + *pp = 0; + return SQLITE_OK; +} +SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){ + return SQLITE_OK; +} +#endif + /* ** The next group of routines are convenience wrappers around the ** VFS methods. @@ -22848,7 +23011,7 @@ /* #include <time.h> */ #include <sys/time.h> #include <errno.h> -#ifndef SQLITE_OMIT_WAL +#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 #include <sys/mman.h> #endif @@ -22947,6 +23110,11 @@ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ + int nFetchOut; /* Number of outstanding xFetch refs */ + sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ + sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */ + sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ + void *pMapRegion; /* Memory mapped region */ #ifdef __QNXNTO__ int sectorSize; /* Device sector size */ int deviceCharacteristics; /* Precomputed device characteristics */ @@ -22971,7 +23139,9 @@ unsigned char transCntrChng; /* True if the transaction counter changed */ unsigned char dbUpdate; /* True if any part of database file changed */ unsigned char inNormalWrite; /* True if in a normal write operation */ + #endif + #ifdef SQLITE_TEST /* In test mode, increase the size of this structure a bit so that ** it is larger than the struct CrashFile defined in test6.c. @@ -22995,6 +23165,7 @@ #define UNIXFILE_DELETE 0x20 /* Delete on close */ #define UNIXFILE_URI 0x40 /* Filename might have query parameters */ #define UNIXFILE_NOLOCK 0x80 /* Do no file locking */ +#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */ /* ** Include code that is common to all os_*.c files @@ -23237,6 +23408,17 @@ #endif /* +** HAVE_MREMAP defaults to true on Linux and false everywhere else. +*/ +#if !defined(HAVE_MREMAP) +# if defined(__linux__) && defined(_GNU_SOURCE) +# define HAVE_MREMAP 1 +# else +# define HAVE_MREMAP 0 +# endif +#endif + +/* ** Different Unix systems declare open() in different ways. Same use ** open(const char*,int,mode_t). Others use open(const char*,int,...). ** The difference is important when using a pointer to the function. @@ -23367,6 +23549,19 @@ { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) + { "mmap", (sqlite3_syscall_ptr)mmap, 0 }, +#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent) + + { "munmap", (sqlite3_syscall_ptr)munmap, 0 }, +#define osMunmap ((void*(*)(void*,size_t))aSyscall[22].pCurrent) + +#if HAVE_MREMAP + { "mremap", (sqlite3_syscall_ptr)mremap, 0 }, +#else + { "mremap", (sqlite3_syscall_ptr)0, 0 }, +#endif +#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent) + }; /* End of the overrideable system calls */ /* @@ -23698,7 +23893,6 @@ } - /****************************************************************************** ****************** Begin Unique File ID Utility Used By VxWorks *************** ** @@ -24034,7 +24228,6 @@ zErr = strerror(iErrno); #endif - assert( errcode!=SQLITE_OK ); if( zPath==0 ) zPath = ""; sqlite3_log(errcode, "os_unix.c:%d: (%d) %s(%s) - %s", @@ -24201,6 +24394,50 @@ /* +** Check a unixFile that is a database. Verify the following: +** +** (1) There is exactly one hard link on the file +** (2) The file is not a symbolic link +** (3) The file has not been renamed or unlinked +** +** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right. +*/ +static void verifyDbFile(unixFile *pFile){ + struct stat buf; + int rc; + if( pFile->ctrlFlags & UNIXFILE_WARNED ){ + /* One or more of the following warnings have already been issued. Do not + ** repeat them so as not to clutter the error log */ + return; + } + rc = osFstat(pFile->h, &buf); + if( rc!=0 ){ + sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; + return; + } + if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){ + sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; + return; + } + if( buf.st_nlink>1 ){ + sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; + return; + } + if( pFile->pInode!=0 + && ((rc = osStat(pFile->zPath, &buf))!=0 + || buf.st_ino!=pFile->pInode->fileId.ino) + ){ + sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath); + pFile->ctrlFlags |= UNIXFILE_WARNED; + return; + } +} + + +/* ** This routine checks if there is a RESERVED lock held on the specified ** file by this or any other process. If such a lock is held, set *pResOut ** to a non-zero value otherwise *pResOut is set to zero. The return value @@ -24730,9 +24967,13 @@ ** the requested locking level, this routine is a no-op. */ static int unixUnlock(sqlite3_file *id, int eFileLock){ + assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 ); return posixUnlock(id, eFileLock, 0); } +static int unixMapfile(unixFile *pFd, i64 nByte); +static void unixUnmapfile(unixFile *pFd); + /* ** This function performs the parts of the "close file" operation ** common to all locking schemes. It closes the directory and file @@ -24745,6 +24986,7 @@ */ static int closeUnixFile(sqlite3_file *id){ unixFile *pFile = (unixFile*)id; + unixUnmapfile(pFile); if( pFile->h>=0 ){ robust_close(pFile, pFile->h, __LINE__); pFile->h = -1; @@ -24771,6 +25013,7 @@ static int unixClose(sqlite3_file *id){ int rc = SQLITE_OK; unixFile *pFile = (unixFile *)id; + verifyDbFile(pFile); unixUnlock(id, NO_LOCK); unixEnterMutex(); @@ -26002,6 +26245,8 @@ unixFile *pFile = (unixFile *)id; int got; assert( id ); + assert( offset>=0 ); + assert( amt>0 ); /* If this is a database file (not a journal, master-journal or temp ** file), the bytes in the locking range should never be read or written. */ @@ -26012,6 +26257,23 @@ ); #endif +#if SQLITE_MAX_MMAP_SIZE>0 + /* Deal with as much of this read request as possible by transfering + ** data from the memory mapping using memcpy(). */ + if( offset<pFile->mmapSize ){ + if( offset+amt <= pFile->mmapSize ){ + memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); + return SQLITE_OK; + }else{ + int nCopy = pFile->mmapSize - offset; + memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy); + pBuf = &((u8 *)pBuf)[nCopy]; + amt -= nCopy; + offset += nCopy; + } + } +#endif + got = seekAndRead(pFile, offset, pBuf, amt); if( got==amt ){ return SQLITE_OK; @@ -26027,50 +26289,63 @@ } /* -** Seek to the offset in id->offset then read cnt bytes into pBuf. -** Return the number of bytes actually read. Update the offset. -** -** To avoid stomping the errno value on a failed write the lastErrno value -** is set before returning. +** Attempt to seek the file-descriptor passed as the first argument to +** absolute offset iOff, then attempt to write nBuf bytes of data from +** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise, +** return the actual number of bytes written (which may be less than +** nBuf). */ -static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ - int got; -#if (!defined(USE_PREAD) && !defined(USE_PREAD64)) - i64 newOffset; -#endif - assert( cnt==(cnt&0x1ffff) ); - cnt &= 0x1ffff; +static int seekAndWriteFd( + int fd, /* File descriptor to write to */ + i64 iOff, /* File offset to begin writing at */ + const void *pBuf, /* Copy data from this buffer to the file */ + int nBuf, /* Size of buffer pBuf in bytes */ + int *piErrno /* OUT: Error number if error occurs */ +){ + int rc = 0; /* Value returned by system call */ + + assert( nBuf==(nBuf&0x1ffff) ); + nBuf &= 0x1ffff; TIMER_START; + #if defined(USE_PREAD) - do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR ); + do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR ); #elif defined(USE_PREAD64) - do{ got = osPwrite64(id->h, pBuf, cnt, offset);}while( got<0 && errno==EINTR); + do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR); #else do{ - newOffset = lseek(id->h, offset, SEEK_SET); - SimulateIOError( newOffset-- ); - if( newOffset!=offset ){ - if( newOffset == -1 ){ - ((unixFile*)id)->lastErrno = errno; - }else{ - ((unixFile*)id)->lastErrno = 0; - } + i64 iSeek = lseek(fd, iOff, SEEK_SET); + SimulateIOError( iSeek-- ); + + if( iSeek!=iOff ){ + if( piErrno ) *piErrno = (iSeek==-1 ? errno : 0); return -1; } - got = osWrite(id->h, pBuf, cnt); - }while( got<0 && errno==EINTR ); + rc = osWrite(fd, pBuf, nBuf); + }while( rc<0 && errno==EINTR ); #endif + TIMER_END; - if( got<0 ){ - ((unixFile*)id)->lastErrno = errno; - } + OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED)); - OSTRACE(("WRITE %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED)); - return got; + if( rc<0 && piErrno ) *piErrno = errno; + return rc; } /* +** Seek to the offset in id->offset then read cnt bytes into pBuf. +** Return the number of bytes actually read. Update the offset. +** +** To avoid stomping the errno value on a failed write the lastErrno value +** is set before returning. +*/ +static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ + return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno); +} + + +/* ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ @@ -26116,6 +26391,23 @@ } #endif +#if SQLITE_MAX_MMAP_SIZE>0 + /* Deal with as much of this write request as possible by transfering + ** data from the memory mapping using memcpy(). */ + if( offset<pFile->mmapSize ){ + if( offset+amt <= pFile->mmapSize ){ + memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); + return SQLITE_OK; + }else{ + int nCopy = pFile->mmapSize - offset; + memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy); + pBuf = &((u8 *)pBuf)[nCopy]; + amt -= nCopy; + offset += nCopy; + } + } +#endif + while( amt>0 && (wrote = seekAndWrite(pFile, offset, pBuf, amt))>0 ){ amt -= wrote; offset += wrote; @@ -26398,6 +26690,14 @@ } #endif + /* If the file was just truncated to a size smaller than the currently + ** mapped region, reduce the effective mapping size as well. SQLite will + ** use read() and write() to access data beyond this point from now on. + */ + if( nByte<pFile->mmapSize ){ + pFile->mmapSize = nByte; + } + return SQLITE_OK; } } @@ -26486,6 +26786,19 @@ } } + if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){ + int rc; + if( pFile->szChunk<=0 ){ + if( robust_ftruncate(pFile->h, nByte) ){ + pFile->lastErrno = errno; + return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); + } + } + + rc = unixMapfile(pFile, nByte); + return rc; + } + return SQLITE_OK; } @@ -26553,6 +26866,18 @@ } return SQLITE_OK; } + case SQLITE_FCNTL_MMAP_SIZE: { + i64 newLimit = *(i64*)pArg; + if( newLimit>sqlite3GlobalConfig.mxMmap ){ + newLimit = sqlite3GlobalConfig.mxMmap; + } + *(i64*)pArg = pFile->mmapSizeMax; + if( newLimit>=0 ){ + pFile->mmapSizeMax = newLimit; + if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit; + } + return SQLITE_OK; + } #ifdef SQLITE_DEBUG /* The pager calls this method to signal that it has done ** a rollback and that the database is therefore unchanged and @@ -26865,7 +27190,7 @@ sqlite3_mutex_free(p->mutex); for(i=0; i<p->nRegion; i++){ if( p->h>=0 ){ - munmap(p->apRegion[i], p->szRegion); + osMunmap(p->apRegion[i], p->szRegion); }else{ sqlite3_free(p->apRegion[i]); } @@ -27105,24 +27430,32 @@ if( sStat.st_size<nByte ){ /* The requested memory region does not exist. If bExtend is set to ** false, exit early. *pp will be set to NULL and SQLITE_OK returned. - ** - ** Alternatively, if bExtend is true, use ftruncate() to allocate - ** the requested memory region. */ - if( !bExtend ) goto shmpage_out; -#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE - if( osFallocate(pShmNode->h, sStat.st_size, nByte)!=0 ){ - rc = unixLogError(SQLITE_IOERR_SHMSIZE, "fallocate", - pShmNode->zFilename); + if( !bExtend ){ goto shmpage_out; } -#else - if( robust_ftruncate(pShmNode->h, nByte) ){ - rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate", - pShmNode->zFilename); - goto shmpage_out; + + /* Alternatively, if bExtend is true, extend the file. Do this by + ** writing a single byte to the end of each (OS) page being + ** allocated or extended. Technically, we need only write to the + ** last page in order to extend the file. But writing to all new + ** pages forces the OS to allocate them immediately, which reduces + ** the chances of SIGBUS while accessing the mapped region later on. + */ + else{ + static const int pgsz = 4096; + int iPg; + + /* Write to the last byte of each newly allocated or extended page */ + assert( (nByte % pgsz)==0 ); + for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){ + if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, 0)!=1 ){ + const char *zFile = pShmNode->zFilename; + rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile); + goto shmpage_out; + } + } } -#endif } } @@ -27138,7 +27471,7 @@ while(pShmNode->nRegion<=iRegion){ void *pMem; if( pShmNode->h>=0 ){ - pMem = mmap(0, szRegion, + pMem = osMmap(0, szRegion, pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion ); @@ -27356,6 +27689,236 @@ #endif /* #ifndef SQLITE_OMIT_WAL */ /* +** If it is currently memory mapped, unmap file pFd. +*/ +static void unixUnmapfile(unixFile *pFd){ + assert( pFd->nFetchOut==0 ); +#if SQLITE_MAX_MMAP_SIZE>0 + if( pFd->pMapRegion ){ + osMunmap(pFd->pMapRegion, pFd->mmapSizeActual); + pFd->pMapRegion = 0; + pFd->mmapSize = 0; + pFd->mmapSizeActual = 0; + } +#endif +} + +#if SQLITE_MAX_MMAP_SIZE>0 +/* +** Return the system page size. +*/ +static int unixGetPagesize(void){ +#if HAVE_MREMAP + return 512; +#elif defined(_BSD_SOURCE) + return getpagesize(); +#else + return (int)sysconf(_SC_PAGESIZE); +#endif +} +#endif /* SQLITE_MAX_MMAP_SIZE>0 */ + +#if SQLITE_MAX_MMAP_SIZE>0 +/* +** Attempt to set the size of the memory mapping maintained by file +** descriptor pFd to nNew bytes. Any existing mapping is discarded. +** +** If successful, this function sets the following variables: +** +** unixFile.pMapRegion +** unixFile.mmapSize +** unixFile.mmapSizeActual +** +** If unsuccessful, an error message is logged via sqlite3_log() and +** the three variables above are zeroed. In this case SQLite should +** continue accessing the database using the xRead() and xWrite() +** methods. +*/ +static void unixRemapfile( + unixFile *pFd, /* File descriptor object */ + i64 nNew /* Required mapping size */ +){ + const char *zErr = "mmap"; + int h = pFd->h; /* File descriptor open on db file */ + u8 *pOrig = (u8 *)pFd->pMapRegion; /* Pointer to current file mapping */ + i64 nOrig = pFd->mmapSizeActual; /* Size of pOrig region in bytes */ + u8 *pNew = 0; /* Location of new mapping */ + int flags = PROT_READ; /* Flags to pass to mmap() */ + + assert( pFd->nFetchOut==0 ); + assert( nNew>pFd->mmapSize ); + assert( nNew<=pFd->mmapSizeMax ); + assert( nNew>0 ); + assert( pFd->mmapSizeActual>=pFd->mmapSize ); + assert( MAP_FAILED!=0 ); + + if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE; + + if( pOrig ){ + const int szSyspage = unixGetPagesize(); + i64 nReuse = (pFd->mmapSize & ~(szSyspage-1)); + u8 *pReq = &pOrig[nReuse]; + + /* Unmap any pages of the existing mapping that cannot be reused. */ + if( nReuse!=nOrig ){ + osMunmap(pReq, nOrig-nReuse); + } + +#if HAVE_MREMAP + pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE); + zErr = "mremap"; +#else + pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse); + if( pNew!=MAP_FAILED ){ + if( pNew!=pReq ){ + osMunmap(pNew, nNew - nReuse); + pNew = 0; + }else{ + pNew = pOrig; + } + } +#endif + + /* The attempt to extend the existing mapping failed. Free it. */ + if( pNew==MAP_FAILED || pNew==0 ){ + osMunmap(pOrig, nReuse); + } + } + + /* If pNew is still NULL, try to create an entirely new mapping. */ + if( pNew==0 ){ + pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0); + } + + if( pNew==MAP_FAILED ){ + pNew = 0; + nNew = 0; + unixLogError(SQLITE_OK, zErr, pFd->zPath); + + /* If the mmap() above failed, assume that all subsequent mmap() calls + ** will probably fail too. Fall back to using xRead/xWrite exclusively + ** in this case. */ + pFd->mmapSizeMax = 0; + } + pFd->pMapRegion = (void *)pNew; + pFd->mmapSize = pFd->mmapSizeActual = nNew; +} +#endif + +/* +** Memory map or remap the file opened by file-descriptor pFd (if the file +** is already mapped, the existing mapping is replaced by the new). Or, if +** there already exists a mapping for this file, and there are still +** outstanding xFetch() references to it, this function is a no-op. +** +** If parameter nByte is non-negative, then it is the requested size of +** the mapping to create. Otherwise, if nByte is less than zero, then the +** requested size is the size of the file on disk. The actual size of the +** created mapping is either the requested size or the value configured +** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller. +** +** SQLITE_OK is returned if no error occurs (even if the mapping is not +** recreated as a result of outstanding references) or an SQLite error +** code otherwise. +*/ +static int unixMapfile(unixFile *pFd, i64 nByte){ +#if SQLITE_MAX_MMAP_SIZE>0 + i64 nMap = nByte; + int rc; + + assert( nMap>=0 || pFd->nFetchOut==0 ); + if( pFd->nFetchOut>0 ) return SQLITE_OK; + + if( nMap<0 ){ + struct stat statbuf; /* Low-level file information */ + rc = osFstat(pFd->h, &statbuf); + if( rc!=SQLITE_OK ){ + return SQLITE_IOERR_FSTAT; + } + nMap = statbuf.st_size; + } + if( nMap>pFd->mmapSizeMax ){ + nMap = pFd->mmapSizeMax; + } + + if( nMap!=pFd->mmapSize ){ + if( nMap>0 ){ + unixRemapfile(pFd, nMap); + }else{ + unixUnmapfile(pFd); + } + } +#endif + + return SQLITE_OK; +} + +/* +** If possible, return a pointer to a mapping of file fd starting at offset +** iOff. The mapping must be valid for at least nAmt bytes. +** +** If such a pointer can be obtained, store it in *pp and return SQLITE_OK. +** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK. +** Finally, if an error does occur, return an SQLite error code. The final +** value of *pp is undefined in this case. +** +** If this function does return a pointer, the caller must eventually +** release the reference by calling unixUnfetch(). +*/ +static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ +#if SQLITE_MAX_MMAP_SIZE>0 + unixFile *pFd = (unixFile *)fd; /* The underlying database file */ +#endif + *pp = 0; + +#if SQLITE_MAX_MMAP_SIZE>0 + if( pFd->mmapSizeMax>0 ){ + if( pFd->pMapRegion==0 ){ + int rc = unixMapfile(pFd, -1); + if( rc!=SQLITE_OK ) return rc; + } + if( pFd->mmapSize >= iOff+nAmt ){ + *pp = &((u8 *)pFd->pMapRegion)[iOff]; + pFd->nFetchOut++; + } + } +#endif + return SQLITE_OK; +} + +/* +** If the third argument is non-NULL, then this function releases a +** reference obtained by an earlier call to unixFetch(). The second +** argument passed to this function must be the same as the corresponding +** argument that was passed to the unixFetch() invocation. +** +** Or, if the third argument is NULL, then this function is being called +** to inform the VFS layer that, according to POSIX, any existing mapping +** may now be invalid and should be unmapped. +*/ +static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){ + unixFile *pFd = (unixFile *)fd; /* The underlying database file */ + UNUSED_PARAMETER(iOff); + + /* If p==0 (unmap the entire file) then there must be no outstanding + ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), + ** then there must be at least one outstanding. */ + assert( (p==0)==(pFd->nFetchOut==0) ); + + /* If p!=0, it must match the iOff value. */ + assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] ); + + if( p ){ + pFd->nFetchOut--; + }else{ + unixUnmapfile(pFd); + } + + assert( pFd->nFetchOut>=0 ); + return SQLITE_OK; +} + +/* ** Here ends the implementation of all sqlite3_file methods. ** ********************** End sqlite3_file Methods ******************************* @@ -27413,7 +27976,9 @@ unixShmMap, /* xShmMap */ \ unixShmLock, /* xShmLock */ \ unixShmBarrier, /* xShmBarrier */ \ - unixShmUnmap /* xShmUnmap */ \ + unixShmUnmap, /* xShmUnmap */ \ + unixFetch, /* xFetch */ \ + unixUnfetch, /* xUnfetch */ \ }; \ static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \ UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \ @@ -27430,7 +27995,7 @@ IOMETHODS( posixIoFinder, /* Finder function name */ posixIoMethods, /* sqlite3_io_methods object name */ - 2, /* shared memory is enabled */ + 3, /* shared memory and mmap are enabled */ unixClose, /* xClose method */ unixLock, /* xLock method */ unixUnlock, /* xUnlock method */ @@ -27681,6 +28246,7 @@ pNew->pVfs = pVfs; pNew->zPath = zFilename; pNew->ctrlFlags = (u8)ctrlFlags; + pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap; if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0), "psow", SQLITE_POWERSAFE_OVERWRITE) ){ pNew->ctrlFlags |= UNIXFILE_PSOW; @@ -27816,15 +28382,15 @@ if( h>=0 ) robust_close(pNew, h, __LINE__); h = -1; osUnlink(zFilename); - isDelete = 0; + pNew->ctrlFlags |= UNIXFILE_DELETE; } - if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE; #endif if( rc!=SQLITE_OK ){ if( h>=0 ) robust_close(pNew, h, __LINE__); }else{ pNew->pMethod = pLockingStyle; OpenCounter(+1); + verifyDbFile(pNew); } return rc; } @@ -29918,7 +30484,7 @@ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==21 ); + assert( ArraySize(aSyscall)==24 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ @@ -30301,11 +30867,20 @@ winceLock local; /* Locks obtained by this instance of winFile */ winceLock *shared; /* Global shared lock memory for the file */ #endif +#if SQLITE_MAX_MMAP_SIZE>0 + int nFetchOut; /* Number of outstanding xFetch references */ + HANDLE hMap; /* Handle for accessing memory mapping */ + void *pMapRegion; /* Area memory mapped */ + sqlite3_int64 mmapSize; /* Usable size of mapped region */ + sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */ + sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ +#endif }; /* ** Allowed values for winFile.ctrlFlags */ +#define WINFILE_RDONLY 0x02 /* Connection is read only */ #define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ #define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ @@ -31665,7 +32240,7 @@ } #endif if( 0 == dwLen ){ - sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", lastErrno, lastErrno); + sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno); }else{ /* copy a maximum of nBuf chars to output buffer */ sqlite3_snprintf(nBuf, zBuf, "%s", zOut); @@ -31708,7 +32283,7 @@ for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){} zMsg[i] = 0; sqlite3_log(errcode, - "os_win.c:%d: (%d) %s(%s) - %s", + "os_win.c:%d: (%lu) %s(%s) - %s", iLine, lastErrno, zFunc, zPath, zMsg ); @@ -32169,6 +32744,8 @@ DWORD dwRet; /* Value returned by SetFilePointer() */ DWORD lastErrno; /* Value returned by GetLastError() */ + OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset)); + upperBits = (LONG)((iOffset>>32) & 0x7fffffff); lowerBits = (LONG)(iOffset & 0xffffffff); @@ -32186,9 +32763,11 @@ pFile->lastErrno = lastErrno; winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, "seekWinFile", pFile->zPath); + OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); return 1; } + OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); return 0; #else /* @@ -32205,13 +32784,20 @@ pFile->lastErrno = osGetLastError(); winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, "seekWinFile", pFile->zPath); + OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); return 1; } + OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); return 0; #endif } +#if SQLITE_MAX_MMAP_SIZE>0 +/* Forward references to VFS methods */ +static int winUnmapfile(winFile*); +#endif + /* ** Close a file. ** @@ -32231,8 +32817,14 @@ #ifndef SQLITE_OMIT_WAL assert( pFile->pShm==0 ); #endif - OSTRACE(("CLOSE %d\n", pFile->h)); assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); + OSTRACE(("CLOSE file=%p\n", pFile->h)); + +#if SQLITE_MAX_MMAP_SIZE>0 + rc = winUnmapfile(pFile); + if( rc!=SQLITE_OK ) return rc; +#endif + do{ rc = osCloseHandle(pFile->h); /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ @@ -32252,11 +32844,11 @@ sqlite3_free(pFile->zDeleteOnClose); } #endif - OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed")); if( rc ){ pFile->h = NULL; } OpenCounter(-1); + OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed")); return rc ? SQLITE_OK : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(), "winClose", pFile->zPath); @@ -32281,11 +32873,33 @@ int nRetry = 0; /* Number of retrys */ assert( id!=0 ); + assert( amt>0 ); + assert( offset>=0 ); SimulateIOError(return SQLITE_IOERR_READ); - OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype)); + OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n", + pFile->h, pBuf, amt, offset, pFile->locktype)); +#if SQLITE_MAX_MMAP_SIZE>0 + /* Deal with as much of this read request as possible by transfering + ** data from the memory mapping using memcpy(). */ + if( offset<pFile->mmapSize ){ + if( offset+amt <= pFile->mmapSize ){ + memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); + OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + }else{ + int nCopy = (int)(pFile->mmapSize - offset); + memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy); + pBuf = &((u8 *)pBuf)[nCopy]; + amt -= nCopy; + offset += nCopy; + } + } +#endif + #if SQLITE_OS_WINCE if( seekWinFile(pFile, offset) ){ + OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h)); return SQLITE_FULL; } while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ @@ -32299,6 +32913,7 @@ DWORD lastErrno; if( retryIoerr(&nRetry, &lastErrno) ) continue; pFile->lastErrno = lastErrno; + OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h)); return winLogError(SQLITE_IOERR_READ, pFile->lastErrno, "winRead", pFile->zPath); } @@ -32306,9 +32921,11 @@ if( nRead<(DWORD)amt ){ /* Unread parts of the buffer must be zero-filled */ memset(&((char*)pBuf)[nRead], 0, amt-nRead); + OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h)); return SQLITE_IOERR_SHORT_READ; } + OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } @@ -32331,8 +32948,27 @@ SimulateIOError(return SQLITE_IOERR_WRITE); SimulateDiskfullError(return SQLITE_FULL); - OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype)); + OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n", + pFile->h, pBuf, amt, offset, pFile->locktype)); +#if SQLITE_MAX_MMAP_SIZE>0 + /* Deal with as much of this write request as possible by transfering + ** data from the memory mapping using memcpy(). */ + if( offset<pFile->mmapSize ){ + if( offset+amt <= pFile->mmapSize ){ + memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); + OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; + }else{ + int nCopy = (int)(pFile->mmapSize - offset); + memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy); + pBuf = &((u8 *)pBuf)[nCopy]; + amt -= nCopy; + offset += nCopy; + } + } +#endif + #if SQLITE_OS_WINCE rc = seekWinFile(pFile, offset); if( rc==0 ){ @@ -32384,13 +33020,16 @@ if( rc ){ if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) || ( pFile->lastErrno==ERROR_DISK_FULL )){ + OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h)); return SQLITE_FULL; } + OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h)); return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno, "winWrite", pFile->zPath); }else{ logIoerr(nRetry); } + OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; } @@ -32400,11 +33039,12 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ winFile *pFile = (winFile*)id; /* File handle object */ int rc = SQLITE_OK; /* Return code for this function */ + DWORD lastErrno; assert( pFile ); - - OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte)); SimulateIOError(return SQLITE_IOERR_TRUNCATE); + OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n", + pFile->h, nByte, pFile->locktype)); /* If the user has configured a chunk-size for this file, truncate the ** file so that it consists of an integer number of chunks (i.e. the @@ -32418,14 +33058,25 @@ /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ if( seekWinFile(pFile, nByte) ){ rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, - "winTruncate1", pFile->zPath); - }else if( 0==osSetEndOfFile(pFile->h) ){ - pFile->lastErrno = osGetLastError(); + "winTruncate1", pFile->zPath); + }else if( 0==osSetEndOfFile(pFile->h) && + ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){ + pFile->lastErrno = lastErrno; rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, - "winTruncate2", pFile->zPath); + "winTruncate2", pFile->zPath); } - OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok")); +#if SQLITE_MAX_MMAP_SIZE>0 + /* If the file was truncated to a size smaller than the currently + ** mapped region, reduce the effective mapping size as well. SQLite will + ** use read() and write() to access data beyond this point from now on. + */ + if( pFile->pMapRegion && nByte<pFile->mmapSize ){ + pFile->mmapSize = nByte; + } +#endif + + OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); return rc; } @@ -32465,13 +33116,14 @@ || (flags&0x0F)==SQLITE_SYNC_FULL ); - OSTR... [truncated message content] |