diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5d4e04bd6..ffa7965e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,8 @@ name: STEPCODE -on: [push] +on: + workflow_dispatch: + pull_request: jobs: windows: @@ -46,7 +48,7 @@ jobs: linux: name: Ubuntu Latest GCC - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: true steps: @@ -88,7 +90,7 @@ jobs: linux_clang: name: Ubuntu Latest Clang - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: true steps: @@ -162,58 +164,64 @@ jobs: brlcad_linux: name: BRL-CAD Linux step-g Test - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: true steps: - name: Setup - CMake uses: lukka/get-cmake@latest - - name: Setup - Ninja - uses: seanmiddleditch/gha-setup-ninja@master - - name: Setup - System env: DEBIAN_FRONTEND: noninteractive run: | sudo apt-get update - # Install dev tools - sudo apt-get install re2c lemon + sudo apt-get install re2c astyle xsltproc libxml2-utils + sudo apt-get install xserver-xorg-dev libx11-dev libxi-dev libxext-dev libglu1-mesa-dev libfontconfig-dev + sudo apt-get install zlib1g-dev libpng-dev libjpeg-dev libtiff-dev libeigen3-dev libgdal-dev libassimp-dev libopencv-dev sudo apt-get clean - - name: Checkout + - name: Clone bext + run: | + git clone https://github.com/BRL-CAD/bext.git + cd bext/stepcode + cmake -E rm -r stepcode + git clone --depth 1 https://github.com/stepcode/stepcode.git -b develop + cd ../.. + + - name: Build bext run: | - git clone --depth 1 git://github.com/BRL-CAD/brlcad.git -b main - cd brlcad/src/other/ext && rm -rf stepcode - git clone --depth 1 git://github.com/stepcode/stepcode.git -b develop - # Ordinarily BRL-CAD keeps track of what files are supposed to be - # present in the repository. In this case we're not interested in - # updating the list to the working stepcode filelist, so use an empty - # list instead - echo "set(stepcode_ignore_files)" > stepcode.dist - cd ../../../../ + cmake -E make_directory bext_build + cmake -S bext -B bext_build -DCMAKE_BUILD_TYPE=Release -DUSE_GDAL=OFF -DUSE_TCL=OFF -DUSE_QT=OFF -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}\bext_output + cmake --build bext_build --config Release -j2 + # We only need the build ouputs (bext_output) after this point, so + # clean up to save space for the main BRL-CAD build. + cmake -E rm -rf bext + cmake -E rm -rf bext_build + - name: Checkout + run: | + git clone --depth 1 https://github.com/BRL-CAD/brlcad.git -b main + - name: Configure run: | - export PATH=$ENV{GITHUB_WORKSPACE}:$PATH - cd brlcad - cmake -S . -G Ninja -B build -DENABLE_ALL=ON -DCMAKE_BUILD_TYPE=Release -DEXT_BUILD_VERBOSE=ON + cmake -E make_directory brlcad_build + cd brlcad_build + cmake -S ../brlcad -DBRLCAD_EXT_DIR=${{ github.workspace }}\bext_output -DBRLCAD_ENABLE_GDAL=OFF -DBRLCAD_ENABLE_TCL=OFF -DBRLCAD_ENABLE_QT=OFF -G Ninja cd .. - name: Build run: | - export PATH=$ENV{GITHUB_WORKSPACE}:$PATH - cd brlcad - cmake --build build --config Release --target step-g + cd brlcad_build + cmake --build . --target step-g cd .. - name: Test run: | - export PATH=$ENV{GITHUB_WORKSPACE}:$PATH - cd brlcad/build - ./bin/step-g ../db/nist/NIST_MBE_PMI_3.stp -o nist3.g - cd ../.. + cd brlcad_build + ./bin/step-g ../brlcad/db/nist/NIST_MBE_PMI_3.stp -o nist3.g + cd .. brlcad_windows: @@ -225,9 +233,6 @@ jobs: - name: Setup - CMake uses: lukka/get-cmake@latest - - name: Setup - Ninja - uses: seanmiddleditch/gha-setup-ninja@master - - name: Add github workspace to path # https://github.community/t/deprecated-add-path/136621 run: echo "$ENV{GITHUB_WORKSPACE}" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8 @@ -238,38 +243,44 @@ jobs: - name: Add cl.exe to PATH uses: ilammy/msvc-dev-cmd@v1 - - name: Checkout + - name: Clone bext run: | - git clone --depth 1 git://github.com/BRL-CAD/brlcad.git -b main - cd brlcad/src/other/ext + git clone https://github.com/BRL-CAD/bext.git + cd bext/stepcode cmake -E rm -r stepcode - git clone --depth 1 git://github.com/stepcode/stepcode.git -b develop - # Ordinarily BRL-CAD keeps track of what files are supposed to be - # present in the repository. In this case we're not interested in - # updating the list to the working stepcode filelist, so use an empty - # list instead - echo "set(stepcode_ignore_files)" > stepcode.dist - cd ../../../../ + git clone --depth 1 https://github.com/stepcode/stepcode.git -b develop + cd ../.. + + - name: Build bext + shell: powershell + run: | + cmake -E make_directory bext_build + cmake -S bext -B bext_build -DCMAKE_BUILD_TYPE=Release -DUSE_GDAL=OFF -DUSE_TCL=OFF -DUSE_QT=OFF -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}\bext_output + cmake --build bext_build --config Release -j2 + # We only need the build ouputs (bext_output) after this point, so + # clean up to save space for the main BRL-CAD build. + cmake -E rm -rf bext + cmake -E rm -rf bext_build + + + - name: Checkout + run: | + git clone --depth 1 https://github.com/BRL-CAD/brlcad.git -b main - name: Configure run: | - cd brlcad && cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_CXX_COMPILER="cl.exe" -DSC_ENABLE_TESTING=ON - cd .. - # We do the following in order to help ensure files are "flushed" - # to disk before compilation is attempted - # https://superuser.com/a/1553374/1286142 - powershell Write-VolumeCache C - powershell Write-VolumeCache D + cmake -E make_directory brlcad_build + cmake -S brlcad -B brlcad_build -DCMAKE_BUILD_TYPE=Release -DBRLCAD_EXT_DIR=${{ github.workspace }}\bext_output -DBRLCAD_ENABLE_GDAL=OFF -DBRLCAD_ENABLE_TCL=OFF -DBRLCAD_ENABLE_QT=OFF -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_CXX_COMPILER="cl.exe" - name: Build run: | - cd brlcad/build - ninja -j1 -v step-g - cd ../.. + cd brlcad_build + cmake --build . --config Release --target step-g + cd .. - name: Test run: | - cd brlcad/build - ./bin/step-g.exe ../db/nist/NIST_MBE_PMI_3.stp -o nist3.g - cd ../.. + cd brlcad_build + ./bin/step-g.exe ../brlcad/db/nist/NIST_MBE_PMI_3.stp -o nist3.g + cd .. diff --git a/.gitignore b/.gitignore index 462bd78c4..1d9da5722 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,9 @@ # Common build directories used in the source tree /build +/build-* /.build + # Temporary files *~ \#*\# @@ -10,6 +12,7 @@ [._]*.sw[a-p] [._]s[a-v][a-z] [._]sw[a-p] +**/__pycache__/ # OS specific files .DS_Store diff --git a/AUTHORS b/AUTHORS index 0e6c2518a..998c16349 100644 --- a/AUTHORS +++ b/AUTHORS @@ -19,6 +19,7 @@ Paviot, Thomas (tpaviot) Pictor, Mark (mpictor) Reed, Nick (nickreed) Shah, Kesha (kesha, keshashah) +Sparks, Devon (devonsparks) Thomas, Dawn (homovulgaris, madant) Wouters, Dave (davyw) Yapp, Clifford (starseeker) diff --git a/CMakeLists.txt b/CMakeLists.txt index d27a53e05..bced0837b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,7 +120,6 @@ option(BUILD_STATIC_LIBS "Build static libraries" OFF) option(SC_PYTHON_GENERATOR "Compile exp2python" ON) option(SC_CPP_GENERATOR "Compile exp2cxx" ON) -option(SC_MEMMGR_ENABLE_CHECKS "Enable sc_memmgr's memory leak detection" OFF) option(SC_TRACE_FPRINTF "Enable extra comments in generated code so the code's source in exp2cxx may be located" OFF) option(SC_ENABLE_COVERAGE "Enable code coverage test" OFF) @@ -153,7 +152,7 @@ include(SC_Locale) # logic related to regenerating the lexer and parser source code include(SC_Regenerate) -# create config header sc_cf.h +# create config.h header include(SC_Config_Headers) if(NOT DEFINED SC_SDAI_ADDITIONAL_EXES_SRCS) @@ -174,10 +173,6 @@ if(NOT SC_IS_SUBBUILD) ".. Generating step can take a while if you are building several schemas.") endif(NOT SC_IS_SUBBUILD) -# create config headers sc_cf.h -include(SC_Config_Headers) - - ################ if(MSVC) @@ -193,7 +188,6 @@ include_directories( ${SC_BINARY_DIR}/include ) -add_subdirectory(src/base) add_subdirectory(src/express) add_subdirectory(src/exppp) add_subdirectory(src/exp2cxx) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b8d1f443e..62e9503db 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,9 +11,12 @@ We love contributions! * Encouraged but not enforced: each commit should stand alone, in the sense that the code should compile and run at that point. * One major topic per pull request. Commits that fix small things (typos, formatting) are perfectly acceptable in a PR fixing a bug or adding a feature. * Tests are good. Tests are required unless you're fixing something simple or that was obviously broken. + * Do not change EXPRESS schema definition without reference to an upstream change. * Make your changes and push them to your GitHub repo * Once your branch is pushed, submit a pull request. -* We'll look at the PR and either merge or add feedback. If there isn't any activity within several days, send a message to the mailing list - `scl-dev` AT `groups.google.com`. + - enable github option on each PR 'Allow edits from maintainers', refer to github help if necessary +* We'll look at the PR and either merge (possibly after rebase) or add feedback. + - If there isn't any activity within several days send a message to the mailing list - `scl-dev` AT `groups.google.com`. ## Coding Standards diff --git a/ChangeLog b/ChangeLog index 39c815bb2..c319eed22 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,7 +5,7 @@ This repo was moved and renamed in May 2012. Previously, it was at http://github.com/mpictor/StepClassLibrary Some are duplicates of changes recorded in the BRL-CAD repo: -http://brlcad.svn.sourceforge.net/viewvc/brlcad/brlcad/trunk/src/other/step/?view=log +https://github.com/BRL-CAD/brlcad/tree/158beae4556d94821938368951546384cba53107/src/other/ext/stepcode Pre-BRL-CAD changes: ************************************************************************ diff --git a/INSTALL b/INSTALL index 3060da905..7b61e14f9 100644 --- a/INSTALL +++ b/INSTALL @@ -51,7 +51,7 @@ Installation -DSC_BUILD_SCHEMAS=ALL - Added to make use of ctest easier. If SC_BUILD_SCHEMAS == ALL, then CMake adds each *.exp file found in data/. - -DSC_BUILD_TYPE=Release + -DCMAKE_BUILD_TYPE=Release - this causes binaries to be built without debugging information - without this, cmake defaults to a Debug build diff --git a/cmake/FindLEMON.cmake b/cmake/FindLEMON.cmake index 7ad58984e..83c63c487 100644 --- a/cmake/FindLEMON.cmake +++ b/cmake/FindLEMON.cmake @@ -141,7 +141,7 @@ if (LEMON_EXECUTABLE) # execute lemon add_custom_command( - OUTPUT ${_out_src_file} + OUTPUT ${_out_src_file} ${_basename}.h COMMAND ${LEMON_EXECUTABLE} -T${LEMON_TEMPLATE} ${LEMON_EXECUTABLE_opts} ${_in_y_file} DEPENDS ${Name}_input_cpy WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -152,7 +152,7 @@ if (LEMON_EXECUTABLE) add_custom_command( OUTPUT ${_out_hdr_file} COMMAND ${CMAKE_COMMAND} ARGS -E rename ${_basename}.h ${_out_hdr_file} - DEPENDS ${_out_src_file} + DEPENDS ${_out_src_file} ${_basename}.h WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) diff --git a/cmake/SC_CXX_schema_macros.cmake b/cmake/SC_CXX_schema_macros.cmake index 016450c2c..54e252c80 100644 --- a/cmake/SC_CXX_schema_macros.cmake +++ b/cmake/SC_CXX_schema_macros.cmake @@ -27,16 +27,16 @@ endmacro(P21_TESTS sfile) # create p21read_sdai_*, lazy_sdai_*, any exes listed in SC_SDAI_ADDITIONAL_EXES_SRCS macro(SCHEMA_EXES) RELATIVE_PATH_TO_TOPLEVEL(${CMAKE_CURRENT_SOURCE_DIR} RELATIVE_PATH_COMPONENT) - SC_ADDEXEC(p21read_${PROJECT_NAME} SOURCES "${RELATIVE_PATH_COMPONENT}/src/test/p21read/p21read.cc" LINK_LIBRARIES ${PROJECT_NAME} stepdai stepcore stepeditor steputils base TESTABLE) + SC_ADDEXEC(p21read_${PROJECT_NAME} SOURCES "${RELATIVE_PATH_COMPONENT}/src/test/p21read/p21read.cc;${RELATIVE_PATH_COMPONENT}/src/test/p21read/sc_benchmark.cc" LINK_LIBRARIES ${PROJECT_NAME} stepdai stepcore stepeditor steputils TESTABLE) if(NOT WIN32) - SC_ADDEXEC(lazy_${PROJECT_NAME} SOURCES "${RELATIVE_PATH_COMPONENT}/src/cllazyfile/lazy_test.cc" LINK_LIBRARIES ${PROJECT_NAME} steplazyfile stepdai stepcore stepeditor steputils base TESTABLE) + SC_ADDEXEC(lazy_${PROJECT_NAME} SOURCES "${RELATIVE_PATH_COMPONENT}/src/cllazyfile/lazy_test.cc;${RELATIVE_PATH_COMPONENT}/src/cllazyfile/sc_benchmark.cc" LINK_LIBRARIES ${PROJECT_NAME} steplazyfile stepdai stepcore stepeditor steputils TESTABLE) endif(NOT WIN32) #add user-defined executables foreach(src ${SC_SDAI_ADDITIONAL_EXES_SRCS}) get_filename_component(name ${src} NAME_WE) get_filename_component(path ${src} ABSOLUTE) - SC_ADDEXEC(${name}_${PROJECT_NAME} SOURCES ${src} LINK_LIBRARIES ${PROJECT_NAME} stepdai stepcore stepeditor steputils base TESTABLE) + SC_ADDEXEC(${name}_${PROJECT_NAME} SOURCES ${src} LINK_LIBRARIES ${PROJECT_NAME} stepdai stepcore stepeditor steputils TESTABLE) #set_target_properties(${name}_${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${${PROJECT_NAME}_COMPILE_FLAGS} -I${path}") endforeach(src ${SC_SDAI_ADDITIONAL_EXES_SRCS}) ENDMACRO(SCHEMA_EXES) @@ -89,12 +89,12 @@ macro(SCHEMA_TARGETS expFile schemaName sourceFiles) ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${SC_SOURCE_DIR}/src/cldai ${SC_SOURCE_DIR}/src/cleditor - ${SC_SOURCE_DIR}/src/clutils ${SC_SOURCE_DIR}/src/clstepcore ${SC_SOURCE_DIR}/src/base - ${SC_SOURCE_DIR}/src/base/judy/src + ${SC_SOURCE_DIR}/src/clutils ${SC_SOURCE_DIR}/src/clstepcore ${SC_SOURCE_DIR}/src/cllazyfile + ${SC_SOURCE_DIR}/src/cllazyfile/judy/src ) - # if testing is enabled, "TESTABLE" sets property EXCLUDE_FROM_ALL and prevents installation + # Schema libraries should be installed by default if(BUILD_SHARED_LIBS) - SC_ADDLIB(${PROJECT_NAME} SHARED SOURCES ${sourceFiles} LINK_LIBRARIES stepdai stepcore stepeditor steputils base TESTABLE) + SC_ADDLIB(${PROJECT_NAME} SHARED SOURCES ${sourceFiles} LINK_LIBRARIES stepdai stepcore stepeditor steputils) add_dependencies(${PROJECT_NAME} generate_cpp_${PROJECT_NAME}) if(WIN32) target_compile_definitions("${PROJECT_NAME}" PRIVATE SC_SCHEMA_DLL_EXPORTS) @@ -110,10 +110,10 @@ macro(SCHEMA_TARGETS expFile schemaName sourceFiles) endif() endif() - if($CACHE{SC_BUILD_STATIC_LIBS}) - SC_ADDLIB(${PROJECT_NAME}-static STATIC SOURCES ${sourceFiles} LINK_LIBRARIES stepdai-static stepcore-static stepeditor-static steputils-static base-static TESTABLE) + if(BUILD_STATIC_LIBS) + SC_ADDLIB(${PROJECT_NAME}-static STATIC SOURCES ${sourceFiles} LINK_LIBRARIES stepdai-static stepcore-static stepeditor-static steputils-static) add_dependencies(${PROJECT_NAME}-static generate_cpp_${PROJECT_NAME}) - target_compile_defines("${PROJECT_NAME}-static" PRIVATE SC_STATIC) + target_compile_definitions("${PROJECT_NAME}-static" PRIVATE SC_STATIC) if(MSVC) target_compile_options("${PROJECT_NAME}-static" PRIVATE "/bigobj") endif() diff --git a/cmake/SC_Config_Headers.cmake b/cmake/SC_Config_Headers.cmake index f9a8cc86b..68f1c37ad 100644 --- a/cmake/SC_Config_Headers.cmake +++ b/cmake/SC_Config_Headers.cmake @@ -1,4 +1,4 @@ -# create sc_cf.h +# create config.h include(CheckLibraryExists) include(CheckIncludeFile) @@ -77,9 +77,9 @@ int main() {return !(f() == f());} cmake_pop_check_state() endif(SC_ENABLE_CXX11) -# Now that all the tests are done, configure the sc_cf.h file: -configure_file(${CMAKE_SOURCE_DIR}/include/sc_cf.h.in ${SC_BINARY_DIR}/${INCLUDE_DIR}/sc_cf.h.gen) -execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SC_BINARY_DIR}/${INCLUDE_DIR}/sc_cf.h.gen ${SC_BINARY_DIR}/${INCLUDE_DIR}/sc_cf.h) +# Now that all the tests are done, configure the config.h file: +configure_file(${CMAKE_SOURCE_DIR}/include/config.h.in ${SC_BINARY_DIR}/${INCLUDE_DIR}/config.h.gen) +execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SC_BINARY_DIR}/${INCLUDE_DIR}/config.h.gen ${SC_BINARY_DIR}/${INCLUDE_DIR}/config.h) # Local Variables: # tab-width: 8 diff --git a/cmake/schema_scanner/CMakeLists.txt b/cmake/schema_scanner/CMakeLists.txt index 16219eb9a..20968ddb0 100644 --- a/cmake/schema_scanner/CMakeLists.txt +++ b/cmake/schema_scanner/CMakeLists.txt @@ -16,7 +16,6 @@ set(SC_BINARY_DIR ${SC_BUILDDIR}) include(${CMAKE_CURRENT_SOURCE_DIR}/../SC_Outdirs.cmake) set(schema_scanner_src - ${SC_ROOT}/src/base/sc_mkdir.c ${SC_ROOT}/src/exp2cxx/genCxxFilenames.c ${SC_ROOT}/src/exp2cxx/class_strings.c ${SC_ROOT}/src/express/generated/expparse.c @@ -52,7 +51,6 @@ include_directories( ${SC_ROOT}/include/ ${SC_ROOT}/src/express/ ${SC_ROOT}/src/express/generated - ${SC_ROOT}/src/base ${SC_ROOT}/src/exp2cxx ${SC_BUILDDIR}/include ) diff --git a/cmake/schema_scanner/schemaScanner.cc b/cmake/schema_scanner/schemaScanner.cc index 88bd110ae..e37238415 100644 --- a/cmake/schema_scanner/schemaScanner.cc +++ b/cmake/schema_scanner/schemaScanner.cc @@ -14,20 +14,25 @@ */ extern "C" { -# include "expparse.h" -# include "expscan.h" -# include "express/scope.h" -# include "genCxxFilenames.h" -# include "sc_mkdir.h" - -# include - -# ifdef _WIN32 -# include -# define getcwd _getcwd -# else -# include -# endif +#define _XOPEN_SOURCE /* for S_IFDIR */ + +#include +#include +#include + +#include "expparse.h" +#include "expscan.h" +#include "express/scope.h" +#include "genCxxFilenames.h" + +#include + +#ifdef _WIN32 +# include +# define getcwd _getcwd +#else +# include +#endif } #include @@ -125,6 +130,30 @@ string makeShortName( const char * longName ) { return filename; } +/* cross-platform mkdir */ +int sc_mkdir( const char * path ) { + #ifdef _WIN32 + return mkdir( path ); + #else + return mkdir( path, 0777 ); + #endif /* _WIN32 */ +} + +/* return -1 if error, 0 if created, 1 if dir existed already */ +static int mkDirIfNone( const char * path ) { + struct stat s; + if( stat( path, &s ) != 0 ) { + if( errno == ENOENT ) { + return sc_mkdir( path ); + } + } else if( s.st_mode & S_IFDIR ) { + return 1; + } + /* either stat returned an error other than ENOENT, or 'path' exists but isn't a dir */ + return -1; +} + + /** write a CMakeLists.txt file for the schema; print its directory to stdout for CMake's add_subdirectory() command */ void writeLists( const char * schemaName, stringstream & eh, stringstream & ei, int ecount, stringstream & th, stringstream & ti, int tcount ) { @@ -220,7 +249,7 @@ void writeLists( const char * schemaName, stringstream & eh, stringstream & ei, cmLists.close(); - char pwd[BUFSIZ] = {0}; + char pwd[BUFSIZ+1] = {0}; if( getcwd( pwd, BUFSIZ ) ) { cout << pwd << "/" << shortName << endl; } else { diff --git a/ctest_matrix.cmake b/ctest_matrix.cmake index d2288acb5..d052e38aa 100644 --- a/ctest_matrix.cmake +++ b/ctest_matrix.cmake @@ -9,7 +9,7 @@ set(CTEST_INITIAL_CACHE " SITE:STRING=${CTEST_SITE} BUILDNAME:STRING=${CTEST_BUILD_NAME} SC_ENABLE_TESTING:BOOL=ON -SC_BUILD_TYPE:STRING=Debug +CMAKE_BUILD_TYPE:STRING=Debug ") diff --git a/example/ap203min/CMakeLists.txt b/example/ap203min/CMakeLists.txt index 52bbe7028..4f3682dd1 100644 --- a/example/ap203min/CMakeLists.txt +++ b/example/ap203min/CMakeLists.txt @@ -31,7 +31,6 @@ set(SC_IS_SUBBUILD TRUE) if(NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug) endif(NOT DEFINED CMAKE_BUILD_TYPE) -set(SC_BUILD_TYPE ${CMAKE_BUILD_TYPE}) # Path to STEPcode set(STEPCODE_BUILD_DIR ${CMAKE_BINARY_DIR}/sc CACHE PATH "STEPcode build subdir") @@ -51,18 +50,13 @@ endif(NOT EXISTS ${SCHEMA_FILE}) get_filename_component(SCHEMA_SN ${SCHEMA_FILE} NAME) string(REGEX REPLACE "\(.*\).[Ee][Xx][Pp]" "sdai_\\1" SCHEMA_LINK_NAME ${SCHEMA_SN}) -set(STEPCODE_LIBRARIES base stepcore stepeditor stepdai steputils ${SCHEMA_LINK_NAME}) +set(STEPCODE_LIBRARIES stepcore stepeditor stepdai steputils ${SCHEMA_LINK_NAME}) # Add STEPCode project to CMake build. add_subdirectory(${STEPCODE_ROOT_DIR} "${CMAKE_CURRENT_BINARY_DIR}/sc" EXCLUDE_FROM_ALL) # Set up STEPcode include directories. set(STEPCODE_INCLUDE_DIR - ${STEPCODE_ROOT_DIR}/src/base - ${STEPCODE_ROOT_DIR}/src/clstepcore - ${STEPCODE_ROOT_DIR}/src/cldai - ${STEPCODE_ROOT_DIR}/src/clutils - ${STEPCODE_ROOT_DIR}/src/cleditor ${STEPCODE_BUILD_DIR}/include ${STEPCODE_ROOT_DIR}/include ${CMAKE_BINARY_DIR} diff --git a/example/ap203min/ExternalProjectBuild/CMakeLists.txt b/example/ap203min/ExternalProjectBuild/CMakeLists.txt index 3a5409088..45cce97e9 100644 --- a/example/ap203min/ExternalProjectBuild/CMakeLists.txt +++ b/example/ap203min/ExternalProjectBuild/CMakeLists.txt @@ -19,7 +19,6 @@ INCLUDE( External_STEPCode ) IF(NOT WIN32) set( STEPCODE_LIBRARIES - ${STEPCODE_INSTALL_DIR}/lib/libbase.a ${STEPCODE_INSTALL_DIR}/lib/libstepcore.a ${STEPCODE_INSTALL_DIR}/lib/libstepeditor.a ${STEPCODE_INSTALL_DIR}/lib/libstepdai.a @@ -28,7 +27,6 @@ IF(NOT WIN32) ) ELSE() set( STEPCODE_LIBRARIES - ${STEPCODE_INSTALL_DIR}/lib/libbase.lib ${STEPCODE_INSTALL_DIR}/lib/libstepcore.lib ${STEPCODE_INSTALL_DIR}/lib/libstepeditor.lib ${STEPCODE_INSTALL_DIR}/lib/libstepdai.lib @@ -44,7 +42,6 @@ MESSAGE( STATUS "STEPCODE_INSTALL_DIR: " ${STEPCODE_INSTALL_DIR} ) set( STEPCODE_INCLUDE_DIR ${STEPCODE_INSTALL_DIR}/include/stepcode -${STEPCODE_INSTALL_DIR}/include/stepcode/base ${STEPCODE_INSTALL_DIR}/include/stepcode/clstepcore ${STEPCODE_INSTALL_DIR}/include/stepcode/cldai ${STEPCODE_INSTALL_DIR}/include/stepcode/clutils diff --git a/example/ap203min/ExternalProjectBuild/cmake/External_STEPCode.cmake b/example/ap203min/ExternalProjectBuild/cmake/External_STEPCode.cmake index 96fca295b..08a5e306f 100644 --- a/example/ap203min/ExternalProjectBuild/cmake/External_STEPCode.cmake +++ b/example/ap203min/ExternalProjectBuild/cmake/External_STEPCode.cmake @@ -4,9 +4,9 @@ ExternalProject_Add( STEPCODE -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} - -DSC_BUILD_TYPE=Debug + -DCMAKE_BUILD_TYPE=Debug -DSC_BUILD_SCHEMAS=ap203/ap203.exp - -DSC_BUILD_STATIC_LIBS=ON + -DBUILD_STATIC_LIBS=ON -DSC_PYTHON_GENERATOR=OFF -DSC_INSTALL_PREFIX:PATH= ) diff --git a/example/ap203min/ap203min.cpp b/example/ap203min/ap203min.cpp index 5e05b7b59..1a6039f83 100644 --- a/example/ap203min/ap203min.cpp +++ b/example/ap203min/ap203min.cpp @@ -49,15 +49,15 @@ // $./AP203Minimum // AP203Minimum outfile.stp -#include -#include -#include -#include -#include -#include - -#include -#include +#include +#include +#include +#include +#include +#include + +#include +#include #include "schema.h" diff --git a/include/sc_cf.h.in b/example/ap203min/include/config.h.in similarity index 94% rename from include/sc_cf.h.in rename to example/ap203min/include/config.h.in index 67d88c433..63ccc4ed1 100644 --- a/include/sc_cf.h.in +++ b/example/ap203min/include/config.h.in @@ -15,7 +15,6 @@ #cmakedefine HAVE_IO_H 1 #cmakedefine SC_TRACE_FPRINTF 1 -#cmakedefine SC_MEMMGR_ENABLE_CHECKS 1 #cmakedefine HAVE_ABS 1 #cmakedefine HAVE_MEMCPY 1 diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index da3ae5eb5..5f39f0ba9 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -32,12 +32,17 @@ install(FILES ${exppp_HDRS} install(FILES ordered_attrs.h sc_export.h - sc_stdbool.h DESTINATION ${INCLUDE_DIR}/stepcode) -install(FILES ${SC_BINARY_DIR}/${INCLUDE_DIR}/sc_cf.h +install(FILES ${SC_BINARY_DIR}/${INCLUDE_DIR}/config.h DESTINATION ${INCLUDE_DIR}/stepcode) +add_subdirectory(cldai) +add_subdirectory(cleditor) +add_subdirectory(cllazyfile) +add_subdirectory(clstepcore) +add_subdirectory(clutils) + # Local Variables: # tab-width: 8 # mode: cmake diff --git a/include/cldai/CMakeLists.txt b/include/cldai/CMakeLists.txt new file mode 100644 index 000000000..471671fbd --- /dev/null +++ b/include/cldai/CMakeLists.txt @@ -0,0 +1,24 @@ +set(DAI_HDRS + sdaiApplication_instance_set.h + sdaiBinary.h + sdaiDaObject.h + sdaiEntity_extent.h + sdaiEntity_extent_set.h + sdaiEnum.h + sdaiModel_contents.h + sdaiModel_contents_list.h + sdaiObject.h + sdaiSession_instance.h + sdaiString.h + ) + +install(FILES ${DAI_HDRS} + DESTINATION ${INCLUDE_DIR}/stepcode/cldai) + +# Local Variables: +# tab-width: 8 +# mode: cmake +# indent-tabs-mode: t +# End: +# ex: shiftwidth=2 tabstop=8 + diff --git a/src/cldai/sdaiApplication_instance_set.h b/include/cldai/sdaiApplication_instance_set.h similarity index 100% rename from src/cldai/sdaiApplication_instance_set.h rename to include/cldai/sdaiApplication_instance_set.h diff --git a/src/cldai/sdaiBinary.h b/include/cldai/sdaiBinary.h similarity index 100% rename from src/cldai/sdaiBinary.h rename to include/cldai/sdaiBinary.h diff --git a/src/cldai/sdaiDaObject.h b/include/cldai/sdaiDaObject.h similarity index 99% rename from src/cldai/sdaiDaObject.h rename to include/cldai/sdaiDaObject.h index 168c7bfbc..3bb0c20f4 100644 --- a/src/cldai/sdaiDaObject.h +++ b/include/cldai/sdaiDaObject.h @@ -1,9 +1,9 @@ #ifndef SDAIDAOBJECT_H #define SDAIDAOBJECT_H 1 -#include -#include -#include +#include "cldai/sdaiObject.h" +#include "cldai/sdaiString.h" +#include "cldai/sdaiEnum.h" #include diff --git a/src/cldai/sdaiEntity_extent.h b/include/cldai/sdaiEntity_extent.h similarity index 100% rename from src/cldai/sdaiEntity_extent.h rename to include/cldai/sdaiEntity_extent.h diff --git a/src/cldai/sdaiEntity_extent_set.h b/include/cldai/sdaiEntity_extent_set.h similarity index 100% rename from src/cldai/sdaiEntity_extent_set.h rename to include/cldai/sdaiEntity_extent_set.h diff --git a/src/cldai/sdaiEnum.h b/include/cldai/sdaiEnum.h similarity index 100% rename from src/cldai/sdaiEnum.h rename to include/cldai/sdaiEnum.h diff --git a/src/cldai/sdaiModel_contents.h b/include/cldai/sdaiModel_contents.h similarity index 100% rename from src/cldai/sdaiModel_contents.h rename to include/cldai/sdaiModel_contents.h diff --git a/src/cldai/sdaiModel_contents_list.h b/include/cldai/sdaiModel_contents_list.h similarity index 100% rename from src/cldai/sdaiModel_contents_list.h rename to include/cldai/sdaiModel_contents_list.h diff --git a/src/cldai/sdaiObject.h b/include/cldai/sdaiObject.h similarity index 100% rename from src/cldai/sdaiObject.h rename to include/cldai/sdaiObject.h diff --git a/src/cldai/sdaiSession_instance.h b/include/cldai/sdaiSession_instance.h similarity index 94% rename from src/cldai/sdaiSession_instance.h rename to include/cldai/sdaiSession_instance.h index fcc8fad15..7aa9a1502 100644 --- a/src/cldai/sdaiSession_instance.h +++ b/include/cldai/sdaiSession_instance.h @@ -3,7 +3,7 @@ #define SESSION_INSTANCE_H 1 #include -//#include +//#include "clstepcore/sdai.h" class SC_DAI_EXPORT SDAI_Session_instance : public SDAI_sdaiObject { diff --git a/src/cldai/sdaiString.h b/include/cldai/sdaiString.h similarity index 100% rename from src/cldai/sdaiString.h rename to include/cldai/sdaiString.h diff --git a/include/cleditor/CMakeLists.txt b/include/cleditor/CMakeLists.txt new file mode 100644 index 000000000..1d128c8fa --- /dev/null +++ b/include/cleditor/CMakeLists.txt @@ -0,0 +1,20 @@ +set(EDITOR_HDRS + STEPfile.h + cmdmgr.h + editordefines.h + SdaiHeaderSchema.h + SdaiHeaderSchemaClasses.h + SdaiSchemaInit.h + seeinfodefault.h + ) + +install(FILES ${EDITOR_HDRS} + DESTINATION ${INCLUDE_DIR}/stepcode/cleditor) + +# Local Variables: +# tab-width: 8 +# mode: cmake +# indent-tabs-mode: t +# End: +# ex: shiftwidth=2 tabstop=8 + diff --git a/src/cleditor/STEPfile.h b/include/cleditor/STEPfile.h similarity index 98% rename from src/cleditor/STEPfile.h rename to include/cleditor/STEPfile.h index 37c7d20bc..1ecfb67c2 100644 --- a/src/cleditor/STEPfile.h +++ b/include/cleditor/STEPfile.h @@ -15,14 +15,14 @@ #include #include -#include -#include +#include "clstepcore/instmgr.h" +#include "clstepcore/Registry.h" #include -#include -#include +#include "clutils/dirobj.h" +#include "clutils/errordesc.h" #include -#include +#include "clstepcore/read_func.h" //error reporting level #define READ_COMPLETE 10 diff --git a/src/cleditor/SdaiHeaderSchema.h b/include/cleditor/SdaiHeaderSchema.h similarity index 97% rename from src/cleditor/SdaiHeaderSchema.h rename to include/cleditor/SdaiHeaderSchema.h index 7cd45d848..5979202f0 100644 --- a/src/cleditor/SdaiHeaderSchema.h +++ b/include/cleditor/SdaiHeaderSchema.h @@ -5,11 +5,11 @@ // regenerate it. #include -#include -#include -#include -#include -#include +#include "clstepcore/sdai.h" +#include "clstepcore/Registry.h" +#include "clstepcore/STEPaggregate.h" +#include "cleditor/SdaiHeaderSchemaClasses.h" +#include "cleditor/SdaiSchemaInit.h" ///////// ENTITY section_language diff --git a/src/cleditor/SdaiHeaderSchemaClasses.h b/include/cleditor/SdaiHeaderSchemaClasses.h similarity index 100% rename from src/cleditor/SdaiHeaderSchemaClasses.h rename to include/cleditor/SdaiHeaderSchemaClasses.h diff --git a/src/cleditor/SdaiSchemaInit.h b/include/cleditor/SdaiSchemaInit.h similarity index 60% rename from src/cleditor/SdaiSchemaInit.h rename to include/cleditor/SdaiSchemaInit.h index a0868fbc6..862f297bd 100644 --- a/src/cleditor/SdaiSchemaInit.h +++ b/include/cleditor/SdaiSchemaInit.h @@ -9,16 +9,16 @@ #endif #include -#include -#include -#include -#include -#include -#include -#include +#include "clstepcore/sdai.h" +#include "clstepcore/Registry.h" +#include "clstepcore/STEPaggregate.h" +#include "clstepcore/STEPundefined.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/complexSupport.h" -#include -#include +#include "cleditor/SdaiHeaderSchemaClasses.h" +#include "cleditor/SdaiHeaderSchema.h" SC_EDITOR_EXPORT void HeaderSchemaInit( Registry & ); SC_EDITOR_EXPORT void HeaderInitSchemasAndEnts( Registry & ); diff --git a/src/cleditor/cmdmgr.h b/include/cleditor/cmdmgr.h similarity index 94% rename from src/cleditor/cmdmgr.h rename to include/cleditor/cmdmgr.h index 7ef2f00b5..4f420467b 100644 --- a/src/cleditor/cmdmgr.h +++ b/include/cleditor/cmdmgr.h @@ -13,16 +13,16 @@ */ #include -#include -#include -#include +#include "clutils/gennode.h" +#include "clutils/gennodelist.h" +#include "clutils/gennodearray.h" -#include -#include -#include -#include -#include -#include +#include "cleditor/editordefines.h" +#include "clstepcore/mgrnode.h" +#include "clstepcore/mgrnodelist.h" +#include "clstepcore/dispnode.h" +#include "clstepcore/dispnodelist.h" +#include "clstepcore/SingleLinkList.h" //#define NUM_CMDMGR_CMDS 9 // this is the number of columns that contain cmds (as opposed @@ -145,6 +145,7 @@ class SC_EDITOR_EXPORT CmdMgr { public: CmdMgr(); + ~CmdMgr(); // STATE LIST OPERATIONS MgrNode * GetHead( stateEnum listType ); diff --git a/src/cleditor/editordefines.h b/include/cleditor/editordefines.h similarity index 100% rename from src/cleditor/editordefines.h rename to include/cleditor/editordefines.h diff --git a/src/cleditor/seeinfodefault.h b/include/cleditor/seeinfodefault.h similarity index 94% rename from src/cleditor/seeinfodefault.h rename to include/cleditor/seeinfodefault.h index 51198eac8..202c5eb1a 100644 --- a/src/cleditor/seeinfodefault.h +++ b/include/cleditor/seeinfodefault.h @@ -20,10 +20,10 @@ class MgrNode; class DisplayNode; class DisplayNodelist; -#include +#include "clstepcore/sdai.h" //class SDAI_Application_instance; -#include +#include "cleditor/editordefines.h" class SC_EDITOR_EXPORT seeInfo : public DisplayNode { public: diff --git a/include/cllazyfile/CMakeLists.txt b/include/cllazyfile/CMakeLists.txt new file mode 100644 index 000000000..853aa98b9 --- /dev/null +++ b/include/cllazyfile/CMakeLists.txt @@ -0,0 +1,27 @@ +set(LAZY_HDRS + headerSectionReader.h + lazyFileReader.h + lazyP21DataSectionReader.h + p21HeaderSectionReader.h + lazyDataSectionReader.h + lazyInstMgr.h + lazyTypes.h + sectionReader.h + instMgrHelper.h + judy.h + judyL2Array.h + judyLArray.h + judyS2Array.h + judySArray.h + ) + +install(FILES ${LAZY_HDRS} + DESTINATION ${INCLUDE_DIR}/stepcode/cllazyfile) + +# Local Variables: +# tab-width: 8 +# mode: cmake +# indent-tabs-mode: t +# End: +# ex: shiftwidth=2 tabstop=8 + diff --git a/src/cllazyfile/headerSectionReader.h b/include/cllazyfile/headerSectionReader.h similarity index 88% rename from src/cllazyfile/headerSectionReader.h rename to include/cllazyfile/headerSectionReader.h index 8a51f5721..e3a9f5725 100644 --- a/src/cllazyfile/headerSectionReader.h +++ b/include/cllazyfile/headerSectionReader.h @@ -5,10 +5,9 @@ #include #include "judyL2Array.h" -#include "lazyFileReader.h" -#include "sectionReader.h" -#include "lazyTypes.h" -#include "sc_memmgr.h" +#include "cllazyfile/lazyFileReader.h" +#include "cllazyfile/sectionReader.h" +#include "cllazyfile/lazyTypes.h" #include "sc_export.h" @@ -31,6 +30,7 @@ class SC_LAZYFILE_EXPORT headerSectionReader: public sectionReader { //FIXME delete each instance?! maybe add to clear, since it iterates over everything already //enum clearHow { rawData, deletePointers } _headerInstances->clear(); + delete _headerInstances; } }; diff --git a/src/cllazyfile/instMgrHelper.h b/include/cllazyfile/instMgrHelper.h similarity index 94% rename from src/cllazyfile/instMgrHelper.h rename to include/cllazyfile/instMgrHelper.h index 659f1ec8e..1af698160 100644 --- a/src/cllazyfile/instMgrHelper.h +++ b/include/cllazyfile/instMgrHelper.h @@ -3,9 +3,9 @@ #include -#include -#include -#include +#include "clstepcore/mgrnode.h" +#include "cllazyfile/lazyInstMgr.h" +#include "clstepcore/instmgr.h" /** * \file instMgrHelper.h helper classes for the lazyInstMgr. Allows use of SDAI_Application_instance class diff --git a/src/base/judy/src/judy.h b/include/cllazyfile/judy.h similarity index 100% rename from src/base/judy/src/judy.h rename to include/cllazyfile/judy.h diff --git a/src/base/judy/src/judyL2Array.h b/include/cllazyfile/judyL2Array.h similarity index 100% rename from src/base/judy/src/judyL2Array.h rename to include/cllazyfile/judyL2Array.h diff --git a/src/base/judy/src/judyLArray.h b/include/cllazyfile/judyLArray.h similarity index 100% rename from src/base/judy/src/judyLArray.h rename to include/cllazyfile/judyLArray.h diff --git a/src/base/judy/src/judyS2Array.h b/include/cllazyfile/judyS2Array.h similarity index 97% rename from src/base/judy/src/judyS2Array.h rename to include/cllazyfile/judyS2Array.h index 726a6449a..c9b25db35 100644 --- a/src/base/judy/src/judyS2Array.h +++ b/include/cllazyfile/judyS2Array.h @@ -51,8 +51,8 @@ class judyS2Array { explicit judyS2Array( const judyS2Array< JudyValue > & other ): _maxKeyLen( other._maxKeyLen ), _success( other._success ) { _judyarray = judy_clone( other._judyarray ); _buff = new unsigned char[_maxKeyLen]; - strncpy( _buff, other._buff, _maxKeyLen ); - _buff[ _maxKeyLen ] = '\0'; //ensure that _buff is null-terminated, since strncpy won't necessarily do so + strncpy( reinterpret_cast< char * >( _buff ), reinterpret_cast< const char * >( other._buff ), _maxKeyLen - 1 ); + _buff[ _maxKeyLen - 1 ] = '\0'; //ensure that _buff is null-terminated find( _buff ); //set _lastSlot } diff --git a/src/base/judy/src/judySArray.h b/include/cllazyfile/judySArray.h similarity index 96% rename from src/base/judy/src/judySArray.h rename to include/cllazyfile/judySArray.h index db75ec91c..f95716ec8 100644 --- a/src/base/judy/src/judySArray.h +++ b/include/cllazyfile/judySArray.h @@ -39,8 +39,8 @@ class judySArray { explicit judySArray( const judySArray< JudyValue > & other ): _maxKeyLen( other._maxKeyLen ), _success( other._success ) { _judyarray = judy_clone( other._judyarray ); _buff = new unsigned char[_maxKeyLen]; - strncpy( _buff, other._buff, _maxKeyLen ); - _buff[ _maxKeyLen ] = '\0'; //ensure that _buff is null-terminated, since strncpy won't necessarily do so + strncpy( reinterpret_cast< char * >( _buff ), reinterpret_cast< const char * >( other._buff ), _maxKeyLen - 1 ); + _buff[ _maxKeyLen - 1 ] = '\0'; //ensure that _buff is null-terminated find( _buff ); //set _lastSlot } diff --git a/src/cllazyfile/lazyDataSectionReader.h b/include/cllazyfile/lazyDataSectionReader.h similarity index 92% rename from src/cllazyfile/lazyDataSectionReader.h rename to include/cllazyfile/lazyDataSectionReader.h index f2dc9dee4..6fad4e0b8 100644 --- a/src/cllazyfile/lazyDataSectionReader.h +++ b/include/cllazyfile/lazyDataSectionReader.h @@ -3,9 +3,8 @@ #include #include -#include "sectionReader.h" -#include "lazyTypes.h" -#include "sc_memmgr.h" +#include "cllazyfile/sectionReader.h" +#include "cllazyfile/lazyTypes.h" #include "sc_export.h" diff --git a/src/cllazyfile/lazyFileReader.h b/include/cllazyfile/lazyFileReader.h similarity index 90% rename from src/cllazyfile/lazyFileReader.h rename to include/cllazyfile/lazyFileReader.h index 49eea5b50..9a5fccb5e 100644 --- a/src/cllazyfile/lazyFileReader.h +++ b/include/cllazyfile/lazyFileReader.h @@ -8,16 +8,14 @@ #include "sc_export.h" // PART 21 -#include "lazyP21DataSectionReader.h" -#include "p21HeaderSectionReader.h" -#include "headerSectionReader.h" +#include "cllazyfile/lazyP21DataSectionReader.h" +#include "cllazyfile/p21HeaderSectionReader.h" +#include "cllazyfile/headerSectionReader.h" /* // PART 28 * #include "lazyP28DataSectionReader.h" * #include "p28HeaderSectionReader.h" */ -#include "sc_memmgr.h" - class lazyInstMgr; class Registry; class headerSectionReader; diff --git a/src/cllazyfile/lazyInstMgr.h b/include/cllazyfile/lazyInstMgr.h similarity index 98% rename from src/cllazyfile/lazyInstMgr.h rename to include/cllazyfile/lazyInstMgr.h index 78444a756..e3445660a 100644 --- a/src/cllazyfile/lazyInstMgr.h +++ b/include/cllazyfile/lazyInstMgr.h @@ -5,12 +5,11 @@ #include #include -#include "lazyDataSectionReader.h" -#include "lazyFileReader.h" -#include "lazyTypes.h" +#include "cllazyfile/lazyDataSectionReader.h" +#include "cllazyfile/lazyFileReader.h" +#include "cllazyfile/lazyTypes.h" -#include "Registry.h" -#include "sc_memmgr.h" +#include "clstepcore/Registry.h" #include "sc_export.h" #include "judyLArray.h" diff --git a/src/cllazyfile/lazyP21DataSectionReader.h b/include/cllazyfile/lazyP21DataSectionReader.h similarity index 89% rename from src/cllazyfile/lazyP21DataSectionReader.h rename to include/cllazyfile/lazyP21DataSectionReader.h index 423679142..c14376fc0 100644 --- a/src/cllazyfile/lazyP21DataSectionReader.h +++ b/include/cllazyfile/lazyP21DataSectionReader.h @@ -1,9 +1,8 @@ #ifndef LAZYP21DATASECTIONREADER_H #define LAZYP21DATASECTIONREADER_H -#include "lazyDataSectionReader.h" -#include "lazyFileReader.h" -#include "sc_memmgr.h" +#include "cllazyfile/lazyDataSectionReader.h" +#include "cllazyfile/lazyFileReader.h" #include "sc_export.h" class SC_LAZYFILE_EXPORT lazyP21DataSectionReader: public lazyDataSectionReader { diff --git a/src/cllazyfile/lazyTypes.h b/include/cllazyfile/lazyTypes.h similarity index 99% rename from src/cllazyfile/lazyTypes.h rename to include/cllazyfile/lazyTypes.h index 0ba2aa671..f1fdbd782 100644 --- a/src/cllazyfile/lazyTypes.h +++ b/include/cllazyfile/lazyTypes.h @@ -1,7 +1,7 @@ #ifndef LAZYTYPES_H #define LAZYTYPES_H -#include "sc_cf.h" +#include "config.h" #include #include diff --git a/src/cllazyfile/p21HeaderSectionReader.h b/include/cllazyfile/p21HeaderSectionReader.h similarity index 91% rename from src/cllazyfile/p21HeaderSectionReader.h rename to include/cllazyfile/p21HeaderSectionReader.h index b5ce04948..ab91fb2bd 100644 --- a/src/cllazyfile/p21HeaderSectionReader.h +++ b/include/cllazyfile/p21HeaderSectionReader.h @@ -1,8 +1,7 @@ #ifndef P21HEADERSECTIONREADER_H #define P21HEADERSECTIONREADER_H -#include "headerSectionReader.h" -#include "sc_memmgr.h" +#include "cllazyfile/headerSectionReader.h" #include "sc_export.h" class SC_LAZYFILE_EXPORT p21HeaderSectionReader: public headerSectionReader { diff --git a/src/cllazyfile/sectionReader.h b/include/cllazyfile/sectionReader.h similarity index 96% rename from src/cllazyfile/sectionReader.h rename to include/cllazyfile/sectionReader.h index c6a64b55a..74f1fa5bf 100644 --- a/src/cllazyfile/sectionReader.h +++ b/include/cllazyfile/sectionReader.h @@ -3,11 +3,10 @@ #include #include -#include "lazyTypes.h" -#include "sc_memmgr.h" +#include "cllazyfile/lazyTypes.h" #include "sc_export.h" -#include "errordesc.h" -#include "STEPcomplex.h" +#include "clutils/errordesc.h" +#include "clstepcore/STEPcomplex.h" class SDAI_Application_instance; class lazyFileReader; @@ -38,6 +37,7 @@ class SC_LAZYFILE_EXPORT sectionReader { // protected member functions sectionReader( lazyFileReader * parent, std::ifstream & file, std::streampos start, sectionID sid ); + ~sectionReader(); /** Find a string, ignoring occurrences in comments or Part 21 strings (i.e. 'string with \S\' control directive' ) * \param str string to find diff --git a/include/clstepcore/CMakeLists.txt b/include/clstepcore/CMakeLists.txt new file mode 100644 index 000000000..a8447cea3 --- /dev/null +++ b/include/clstepcore/CMakeLists.txt @@ -0,0 +1,71 @@ +set(CORE_HDRS + aggrTypeDescriptor.h + attrDescriptor.h + attrDescriptorList.h + baseType.h + complexSupport.h + create_Aggr.h + derivedAttribute.h + dictSchema.h + dictdefs.h + dictionaryInstance.h + dispnode.h + dispnodelist.h + entityDescriptor.h + entityDescriptorList.h + enumTypeDescriptor.h + ExpDict.h + explicitItemId.h + globalRule.h + implicitItemId.h + instmgr.h + interfaceSpec.h + interfacedItem.h + inverseAttribute.h + inverseAttributeList.h + mgrnode.h + mgrnodearray.h + mgrnodelist.h + needFunc.h + read_func.h + realTypeDescriptor.h + Registry.h + schRename.h + sdai.h + sdaiApplication_instance.h + sdaiSelect.h + selectTypeDescriptor.h + SingleLinkList.h + STEPaggregate.h + STEPaggrBinary.h + STEPaggrEntity.h + STEPaggrEnum.h + STEPaggrGeneric.h + STEPaggrInt.h + STEPaggrReal.h + STEPaggrSelect.h + STEPaggrString.h + STEPattribute.h + STEPattributeList.h + STEPcomplex.h + STEPinvAttrList.h + STEPundefined.h + stringTypeDescriptor.h + SubSuperIterators.h + typeDescriptor.h + typeDescriptorList.h + typeOrRuleVar.h + uniquenessRule.h + whereRule.h +) + +install(FILES ${CORE_HDRS} + DESTINATION ${INCLUDE_DIR}/stepcode/clstepcore) + +# Local Variables: +# tab-width: 8 +# mode: cmake +# indent-tabs-mode: t +# End: +# ex: shiftwidth=2 tabstop=8 + diff --git a/src/clstepcore/ExpDict.h b/include/clstepcore/ExpDict.h similarity index 70% rename from src/clstepcore/ExpDict.h rename to include/clstepcore/ExpDict.h index e73b8dd01..c8c71258b 100644 --- a/src/clstepcore/ExpDict.h +++ b/include/clstepcore/ExpDict.h @@ -15,20 +15,20 @@ */ #include -#include +#include "clstepcore/sdai.h" #include #include #include -#include +#include "clstepcore/SingleLinkList.h" -#include -#include -#include +#include "clstepcore/baseType.h" +#include "clstepcore/dictdefs.h" +#include "clutils/Str.h" // each of these contains linked list, list node, iterator -#include "attrDescriptorList.h" +#include "clstepcore/attrDescriptorList.h" #include "inverseAttributeList.h" #include "typeDescriptorList.h" #include "entityDescriptorList.h" @@ -37,12 +37,12 @@ #include "typeDescriptor.h" #include "entityDescriptor.h" #include "enumTypeDescriptor.h" -#include "attrDescriptor.h" -#include "derivedAttribute.h" +#include "clstepcore/attrDescriptor.h" +#include "clstepcore/derivedAttribute.h" #include "inverseAttribute.h" -#include "create_Aggr.h" -#include "dictionaryInstance.h" +#include "clstepcore/create_Aggr.h" +#include "clstepcore/dictionaryInstance.h" #include "uniquenessRule.h" #include "whereRule.h" @@ -53,10 +53,10 @@ #include "interfaceSpec.h" #include "typeOrRuleVar.h" #include "globalRule.h" -#include "dictSchema.h" +#include "clstepcore/dictSchema.h" #include "schRename.h" -#include "aggrTypeDescriptor.h" +#include "clstepcore/aggrTypeDescriptor.h" #include "selectTypeDescriptor.h" #include "stringTypeDescriptor.h" #include "realTypeDescriptor.h" diff --git a/src/clstepcore/Registry.h b/include/clstepcore/Registry.h similarity index 95% rename from src/clstepcore/Registry.h rename to include/clstepcore/Registry.h index d4d4d4db0..099015686 100644 --- a/src/clstepcore/Registry.h +++ b/include/clstepcore/Registry.h @@ -13,11 +13,11 @@ */ #include -#include -#include -#include -#include -#include +#include "clstepcore/sdai.h" +#include "clutils/errordesc.h" +#include "clutils/sc_hash.h" +#include "clutils/Str.h" +#include "clstepcore/complexSupport.h" // defined and created in Registry.cc diff --git a/src/clstepcore/STEPaggrBinary.h b/include/clstepcore/STEPaggrBinary.h similarity index 97% rename from src/clstepcore/STEPaggrBinary.h rename to include/clstepcore/STEPaggrBinary.h index cd4991bbb..59ea61ab5 100644 --- a/src/clstepcore/STEPaggrBinary.h +++ b/include/clstepcore/STEPaggrBinary.h @@ -1,7 +1,7 @@ #ifndef STEPAGGRBINARY_H #define STEPAGGRBINARY_H -#include "STEPaggregate.h" +#include "clstepcore/STEPaggregate.h" #include /** \file STEPaggrBinary.h diff --git a/src/clstepcore/STEPaggrEntity.h b/include/clstepcore/STEPaggrEntity.h similarity index 98% rename from src/clstepcore/STEPaggrEntity.h rename to include/clstepcore/STEPaggrEntity.h index f18bc3d0f..8338fc8f8 100644 --- a/src/clstepcore/STEPaggrEntity.h +++ b/include/clstepcore/STEPaggrEntity.h @@ -5,7 +5,7 @@ * classes EntityAggregate, EntityNode */ -#include "STEPaggregate.h" +#include "clstepcore/STEPaggregate.h" #include class SC_CORE_EXPORT EntityAggregate : public STEPaggregate { diff --git a/src/clstepcore/STEPaggrEnum.h b/include/clstepcore/STEPaggrEnum.h similarity index 92% rename from src/clstepcore/STEPaggrEnum.h rename to include/clstepcore/STEPaggrEnum.h index 161706a48..cf16fb0e6 100644 --- a/src/clstepcore/STEPaggrEnum.h +++ b/include/clstepcore/STEPaggrEnum.h @@ -1,7 +1,7 @@ #ifndef STEPAGGRENUM_H #define STEPAGGRENUM_H -#include "STEPaggregate.h" +#include "clstepcore/STEPaggregate.h" #include "sc_export.h" /** \file StepaggrEnum.h * classes EnumAggregate, LOGICALS, BOOLEANS, EnumNode @@ -9,7 +9,7 @@ /** * \class EnumAggregate - * This is a minimal representions for a collection of SDAI_Enum + * This is a minimal representation for a collection of SDAI_Enum */ class SC_CORE_EXPORT EnumAggregate : public STEPaggregate { public: @@ -55,7 +55,7 @@ SC_CORE_EXPORT BOOLEANS * create_BOOLEANS(); /** * * \class EnumNode - ** This is a minimal representions for node in lists of SDAI_Enum + ** This is a minimal representation for node in lists of SDAI_Enum */ class SC_CORE_EXPORT EnumNode : public STEPnode { public: diff --git a/src/clstepcore/STEPaggrGeneric.h b/include/clstepcore/STEPaggrGeneric.h similarity index 97% rename from src/clstepcore/STEPaggrGeneric.h rename to include/clstepcore/STEPaggrGeneric.h index 76190406e..ecb286d00 100644 --- a/src/clstepcore/STEPaggrGeneric.h +++ b/include/clstepcore/STEPaggrGeneric.h @@ -1,7 +1,7 @@ #ifndef STEPAGGRGENERIC_H #define STEPAGGRGENERIC_H -#include "STEPaggregate.h" +#include "clstepcore/STEPaggregate.h" #include /** \file STEPaggrGeneric.h diff --git a/src/clstepcore/STEPaggrInt.h b/include/clstepcore/STEPaggrInt.h similarity index 97% rename from src/clstepcore/STEPaggrInt.h rename to include/clstepcore/STEPaggrInt.h index 726d07c0e..11bf57464 100644 --- a/src/clstepcore/STEPaggrInt.h +++ b/include/clstepcore/STEPaggrInt.h @@ -1,7 +1,7 @@ #ifndef STEPAGGRINT_H #define STEPAGGRINT_H -#include "STEPaggregate.h" +#include "clstepcore/STEPaggregate.h" #include class SC_CORE_EXPORT IntAggregate : public STEPaggregate { diff --git a/src/clstepcore/STEPaggrReal.h b/include/clstepcore/STEPaggrReal.h similarity index 97% rename from src/clstepcore/STEPaggrReal.h rename to include/clstepcore/STEPaggrReal.h index 48cd90e51..920c98907 100644 --- a/src/clstepcore/STEPaggrReal.h +++ b/include/clstepcore/STEPaggrReal.h @@ -1,7 +1,7 @@ #ifndef STEPAGGRREAL_H #define STEPAGGRREAL_H -#include "STEPaggregate.h" +#include "clstepcore/STEPaggregate.h" #include class SC_CORE_EXPORT RealAggregate : public STEPaggregate { diff --git a/src/clstepcore/STEPaggrSelect.h b/include/clstepcore/STEPaggrSelect.h similarity index 95% rename from src/clstepcore/STEPaggrSelect.h rename to include/clstepcore/STEPaggrSelect.h index b62a9c3fe..dd6621caa 100644 --- a/src/clstepcore/STEPaggrSelect.h +++ b/include/clstepcore/STEPaggrSelect.h @@ -1,7 +1,7 @@ #ifndef STEPAGGRSELECT_H #define STEPAGGRSELECT_H -#include "STEPaggregate.h" +#include "clstepcore/STEPaggregate.h" #include /** \file STEPaggrSelect.h @@ -11,7 +11,7 @@ /** * * \class SelectAggregate - ** This is a minimal represention for a collection of SDAI_Select + ** This is a minimal representation for a collection of SDAI_Select */ class SC_CORE_EXPORT SelectAggregate : public STEPaggregate { public: @@ -35,7 +35,7 @@ typedef SelectAggregate_ptr SelectAggregate_var; /** * * \class SelectNode - ** This is a minimal representions for node in lists of SDAI_Select + ** This is a minimal representation for node in lists of SDAI_Select */ class SC_CORE_EXPORT SelectNode : public STEPnode { public: diff --git a/src/clstepcore/STEPaggrString.h b/include/clstepcore/STEPaggrString.h similarity index 97% rename from src/clstepcore/STEPaggrString.h rename to include/clstepcore/STEPaggrString.h index 6f5cc8331..93aa1636e 100644 --- a/src/clstepcore/STEPaggrString.h +++ b/include/clstepcore/STEPaggrString.h @@ -1,7 +1,7 @@ #ifndef STEPAGGRSTRING_H #define STEPAGGRSTRING_H -#include "STEPaggregate.h" +#include "clstepcore/STEPaggregate.h" #include /** \file STEPaggrString.h diff --git a/src/clstepcore/STEPaggregate.h b/include/clstepcore/STEPaggregate.h similarity index 89% rename from src/clstepcore/STEPaggregate.h rename to include/clstepcore/STEPaggregate.h index df2178ee9..0acb638d6 100644 --- a/src/clstepcore/STEPaggregate.h +++ b/include/clstepcore/STEPaggregate.h @@ -17,11 +17,11 @@ class STEPaggregate; class TypeDescriptor; #include -#include -#include -#include -#include -#include +#include "clutils/errordesc.h" +#include "clstepcore/SingleLinkList.h" +#include "clstepcore/baseType.h" +#include "clstepcore/sdai.h" +#include "clstepcore/STEPundefined.h" #include #define AGGR_NULL &NilSTEPaggregate @@ -110,14 +110,14 @@ class SC_CORE_EXPORT STEPnode : public SingleLinkNode { }; typedef STEPnode * STEPnodeH; -#include "STEPaggrGeneric.h" -#include "STEPaggrEntity.h" -#include "STEPaggrSelect.h" -#include "STEPaggrString.h" -#include "STEPaggrBinary.h" -#include "STEPaggrEnum.h" -#include "STEPaggrReal.h" -#include "STEPaggrInt.h" +#include "clstepcore/STEPaggrGeneric.h" +#include "clstepcore/STEPaggrEntity.h" +#include "clstepcore/STEPaggrSelect.h" +#include "clstepcore/STEPaggrString.h" +#include "clstepcore/STEPaggrBinary.h" +#include "clstepcore/STEPaggrEnum.h" +#include "clstepcore/STEPaggrReal.h" +#include "clstepcore/STEPaggrInt.h" /****************************************************************** ** FIXME The following classes are currently stubs diff --git a/src/clstepcore/STEPattribute.h b/include/clstepcore/STEPattribute.h similarity index 98% rename from src/clstepcore/STEPattribute.h rename to include/clstepcore/STEPattribute.h index 08d8a62e5..f496fa46c 100644 --- a/src/clstepcore/STEPattribute.h +++ b/include/clstepcore/STEPattribute.h @@ -15,10 +15,10 @@ #include #include -#include -#include +#include "clutils/errordesc.h" +#include "clstepcore/baseType.h" -#include +#include "clstepcore/sdai.h" /** \def REAL_NUM_PRECISION * this is used to set a const int Real_Num_Precision @@ -208,7 +208,7 @@ class SC_CORE_EXPORT STEPattribute { } const char * Name() const; - const char * TypeName() const; + std::string TypeName() const; BASE_TYPE Type() const; BASE_TYPE NonRefType() const; BASE_TYPE BaseType() const; diff --git a/src/clstepcore/STEPattributeList.h b/include/clstepcore/STEPattributeList.h similarity index 97% rename from src/clstepcore/STEPattributeList.h rename to include/clstepcore/STEPattributeList.h index 9159f4664..54aca69b4 100644 --- a/src/clstepcore/STEPattributeList.h +++ b/include/clstepcore/STEPattributeList.h @@ -16,7 +16,7 @@ class STEPattribute; #include -#include +#include "clstepcore/SingleLinkList.h" class STEPattributeList; diff --git a/src/clstepcore/STEPcomplex.h b/include/clstepcore/STEPcomplex.h similarity index 95% rename from src/clstepcore/STEPcomplex.h rename to include/clstepcore/STEPcomplex.h index caf7ea255..3c8a75fc3 100644 --- a/src/clstepcore/STEPcomplex.h +++ b/include/clstepcore/STEPcomplex.h @@ -2,11 +2,11 @@ #define STEPCOMPLEX_H #include -#include -#include -#include -#include -#include +#include "clutils/errordesc.h" +#include "clstepcore/sdai.h" +#include "clstepcore/baseType.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/Registry.h" #include diff --git a/src/clstepcore/STEPinvAttrList.h b/include/clstepcore/STEPinvAttrList.h similarity index 98% rename from src/clstepcore/STEPinvAttrList.h rename to include/clstepcore/STEPinvAttrList.h index 342720065..ccbb733b0 100644 --- a/src/clstepcore/STEPinvAttrList.h +++ b/include/clstepcore/STEPinvAttrList.h @@ -15,7 +15,7 @@ class Inverse_attribute; #include -#include +#include "clstepcore/SingleLinkList.h" class STEPinvAttrList; class EntityAggregate; diff --git a/src/clstepcore/STEPundefined.h b/include/clstepcore/STEPundefined.h similarity index 95% rename from src/clstepcore/STEPundefined.h rename to include/clstepcore/STEPundefined.h index 306eb0ef2..9cbb87ee7 100644 --- a/src/clstepcore/STEPundefined.h +++ b/include/clstepcore/STEPundefined.h @@ -13,9 +13,9 @@ */ #include -#include +#include "clutils/errordesc.h" #include -#include +#include "clstepcore/read_func.h" class SC_CORE_EXPORT SCLundefined { protected: diff --git a/src/clstepcore/SingleLinkList.h b/include/clstepcore/SingleLinkList.h similarity index 100% rename from src/clstepcore/SingleLinkList.h rename to include/clstepcore/SingleLinkList.h diff --git a/src/clstepcore/SubSuperIterators.h b/include/clstepcore/SubSuperIterators.h similarity index 99% rename from src/clstepcore/SubSuperIterators.h rename to include/clstepcore/SubSuperIterators.h index 9ca78765b..ccc059d28 100644 --- a/src/clstepcore/SubSuperIterators.h +++ b/include/clstepcore/SubSuperIterators.h @@ -1,8 +1,8 @@ #ifndef SUB_SUPER_ITERATORS #define SUB_SUPER_ITERATORS -#include "ExpDict.h" -#include "ExpDict.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/ExpDict.h" #include #include diff --git a/src/clstepcore/aggrTypeDescriptor.h b/include/clstepcore/aggrTypeDescriptor.h similarity index 97% rename from src/clstepcore/aggrTypeDescriptor.h rename to include/clstepcore/aggrTypeDescriptor.h index 850a6b2e7..0031adf2d 100644 --- a/src/clstepcore/aggrTypeDescriptor.h +++ b/include/clstepcore/aggrTypeDescriptor.h @@ -2,7 +2,7 @@ #define AGGRTYPEDESCRIPTOR_H #include "typeDescriptor.h" -#include "create_Aggr.h" +#include "clstepcore/create_Aggr.h" #include "assert.h" @@ -57,7 +57,7 @@ class SC_CORE_EXPORT AggrTypeDescriptor : public TypeDescriptor { AggrTypeDescriptor( const char * nm, PrimitiveType ft, Schema * origSchema, const char * d, AggregateCreator f = 0 ) - : TypeDescriptor( nm, ft, origSchema, d ), _bound1( 0 ), _bound2( 0 ), _uniqueElements( 0 ), _aggrDomainType( NULL ), CreateNewAggr( f ) { } + : TypeDescriptor( nm, ft, origSchema, d ), _bound1( 0 ), _bound2( 0 ), _uniqueElements( 0 ), _aggrDomainType( NULL ), CreateNewAggr( f ), _bound1_type( bound_unset ), _bound2_type( bound_unset ), _bound1_callback( NULL ), _bound2_callback( NULL ) { } virtual ~AggrTypeDescriptor(); diff --git a/src/clstepcore/attrDescriptor.h b/include/clstepcore/attrDescriptor.h similarity index 99% rename from src/clstepcore/attrDescriptor.h rename to include/clstepcore/attrDescriptor.h index cee4d13bc..c3d6493dd 100644 --- a/src/clstepcore/attrDescriptor.h +++ b/include/clstepcore/attrDescriptor.h @@ -3,7 +3,7 @@ #include "typeDescriptor.h" -#include "sdaiEnum.h" +#include "cldai/sdaiEnum.h" #include "sc_export.h" diff --git a/src/clstepcore/attrDescriptorList.h b/include/clstepcore/attrDescriptorList.h similarity index 100% rename from src/clstepcore/attrDescriptorList.h rename to include/clstepcore/attrDescriptorList.h diff --git a/src/clstepcore/baseType.h b/include/clstepcore/baseType.h similarity index 100% rename from src/clstepcore/baseType.h rename to include/clstepcore/baseType.h diff --git a/src/clstepcore/complexSupport.h b/include/clstepcore/complexSupport.h similarity index 99% rename from src/clstepcore/complexSupport.h rename to include/clstepcore/complexSupport.h index cd2d9611f..34e78814e 100644 --- a/src/clstepcore/complexSupport.h +++ b/include/clstepcore/complexSupport.h @@ -18,7 +18,7 @@ #include #include using namespace std; -#include "Str.h" +#include "clutils/Str.h" #define LISTEND 999 /** \def LISTEND @@ -132,7 +132,7 @@ class SC_CORE_EXPORT EntNode { private: MarkType mark; - char name[BUFSIZ]; + char name[BUFSIZ+1]; bool multSupers; ///< do I correspond to an entity with >1 supertype? EntNode * lastSmaller( EntNode * ); ///< used by ::sort() }; @@ -238,7 +238,7 @@ class SC_CORE_EXPORT SimpleList : public EntList { } private: - char name[BUFSIZ]; ///< Name of entity we correspond to. + char name[BUFSIZ+1]; ///< Name of entity we correspond to. MarkType I_marked; ///< Did I mark, and with what type of mark. }; diff --git a/src/clstepcore/create_Aggr.h b/include/clstepcore/create_Aggr.h similarity index 97% rename from src/clstepcore/create_Aggr.h rename to include/clstepcore/create_Aggr.h index a0483fa66..7e5fdb0b3 100644 --- a/src/clstepcore/create_Aggr.h +++ b/include/clstepcore/create_Aggr.h @@ -3,7 +3,7 @@ //typedef's for aggregate creators -#include "sdai.h" +#include "clstepcore/sdai.h" #include "sc_export.h" diff --git a/src/clstepcore/derivedAttribute.h b/include/clstepcore/derivedAttribute.h similarity index 95% rename from src/clstepcore/derivedAttribute.h rename to include/clstepcore/derivedAttribute.h index 234521a07..69e0a37cf 100644 --- a/src/clstepcore/derivedAttribute.h +++ b/include/clstepcore/derivedAttribute.h @@ -1,7 +1,7 @@ #ifndef DERIVEDATTRIBUTE_H #define DERIVEDATTRIBUTE_H -#include "attrDescriptor.h" +#include "clstepcore/attrDescriptor.h" #include "sc_export.h" diff --git a/src/clstepcore/dictSchema.h b/include/clstepcore/dictSchema.h similarity index 100% rename from src/clstepcore/dictSchema.h rename to include/clstepcore/dictSchema.h diff --git a/src/clstepcore/dictdefs.h b/include/clstepcore/dictdefs.h similarity index 100% rename from src/clstepcore/dictdefs.h rename to include/clstepcore/dictdefs.h diff --git a/src/clstepcore/dictionaryInstance.h b/include/clstepcore/dictionaryInstance.h similarity index 100% rename from src/clstepcore/dictionaryInstance.h rename to include/clstepcore/dictionaryInstance.h diff --git a/src/clstepcore/dispnode.h b/include/clstepcore/dispnode.h similarity index 92% rename from src/clstepcore/dispnode.h rename to include/clstepcore/dispnode.h index 1209b9c3e..fccde675c 100644 --- a/src/clstepcore/dispnode.h +++ b/include/clstepcore/dispnode.h @@ -17,14 +17,14 @@ #include -/*#include */ +/*#include "clstepcore/STEPattribute.h"*/ /*#include */ -#include +#include "clstepcore/sdai.h" -#include -#include +#include "clutils/gennode.h" +#include "clutils/gennodelist.h" //#include -#include +#include "cleditor/editordefines.h" //#include class MgrNode; diff --git a/src/clstepcore/dispnodelist.h b/include/clstepcore/dispnodelist.h similarity index 92% rename from src/clstepcore/dispnodelist.h rename to include/clstepcore/dispnodelist.h index c4fe4dde3..6dfc697bd 100644 --- a/src/clstepcore/dispnodelist.h +++ b/include/clstepcore/dispnodelist.h @@ -17,12 +17,12 @@ #include -#include +#include "clutils/gennode.h" //#include -#include -#include -#include -#include +#include "cleditor/editordefines.h" +#include "clstepcore/mgrnode.h" +#include "clstepcore/dispnode.h" +#include "clutils/gennodelist.h" /////////////////////////////////////////////////////////////////////////////// // class DisplayNodeList diff --git a/src/clstepcore/entityDescriptor.h b/include/clstepcore/entityDescriptor.h similarity index 98% rename from src/clstepcore/entityDescriptor.h rename to include/clstepcore/entityDescriptor.h index e0bd25ec8..a51810c3f 100644 --- a/src/clstepcore/entityDescriptor.h +++ b/include/clstepcore/entityDescriptor.h @@ -2,9 +2,9 @@ #define ENTITYDESCRIPTOR_H #include "typeDescriptor.h" -#include "attrDescriptor.h" +#include "clstepcore/attrDescriptor.h" #include "uniquenessRule.h" -#include "attrDescriptorList.h" +#include "clstepcore/attrDescriptorList.h" #include "inverseAttributeList.h" #include "sc_export.h" diff --git a/src/clstepcore/entityDescriptorList.h b/include/clstepcore/entityDescriptorList.h similarity index 100% rename from src/clstepcore/entityDescriptorList.h rename to include/clstepcore/entityDescriptorList.h diff --git a/src/clstepcore/enumTypeDescriptor.h b/include/clstepcore/enumTypeDescriptor.h similarity index 100% rename from src/clstepcore/enumTypeDescriptor.h rename to include/clstepcore/enumTypeDescriptor.h diff --git a/src/clstepcore/explicitItemId.h b/include/clstepcore/explicitItemId.h similarity index 100% rename from src/clstepcore/explicitItemId.h rename to include/clstepcore/explicitItemId.h diff --git a/src/clstepcore/globalRule.h b/include/clstepcore/globalRule.h similarity index 97% rename from src/clstepcore/globalRule.h rename to include/clstepcore/globalRule.h index ffd1200fd..0987fbfbd 100644 --- a/src/clstepcore/globalRule.h +++ b/include/clstepcore/globalRule.h @@ -1,7 +1,7 @@ #ifndef GLOBALRULE_H #define GLOBALRULE_H -#include "dictionaryInstance.h" +#include "clstepcore/dictionaryInstance.h" #include "whereRule.h" #include "entityDescriptorList.h" diff --git a/src/clstepcore/implicitItemId.h b/include/clstepcore/implicitItemId.h similarity index 100% rename from src/clstepcore/implicitItemId.h rename to include/clstepcore/implicitItemId.h diff --git a/src/clstepcore/instmgr.h b/include/clstepcore/instmgr.h similarity index 93% rename from src/clstepcore/instmgr.h rename to include/clstepcore/instmgr.h index 3f185b3fb..86ed28603 100644 --- a/src/clstepcore/instmgr.h +++ b/include/clstepcore/instmgr.h @@ -27,17 +27,17 @@ // IT IS VERY IMPORTANT THAT THE ORDER OF THE FOLLOWING INCLUDE FILES // BE PRESERVED -#include -#include -#include +#include "clutils/gennode.h" +#include "clutils/gennodelist.h" +#include "clutils/gennodearray.h" -#include -#include +#include "clstepcore/mgrnode.h" +#include "clstepcore/mgrnodelist.h" -#include -#include +#include "clstepcore/dispnode.h" +#include "clstepcore/dispnodelist.h" -#include +#include "clstepcore/mgrnodearray.h" class SC_CORE_EXPORT InstMgrBase { public: diff --git a/src/clstepcore/interfaceSpec.h b/include/clstepcore/interfaceSpec.h similarity index 97% rename from src/clstepcore/interfaceSpec.h rename to include/clstepcore/interfaceSpec.h index 0b61b4b04..9eeea3f85 100644 --- a/src/clstepcore/interfaceSpec.h +++ b/include/clstepcore/interfaceSpec.h @@ -1,8 +1,8 @@ #ifndef INTERFACESPEC_H #define INTERFACESPEC_H -#include "dictionaryInstance.h" -#include "explicitItemId.h" +#include "clstepcore/dictionaryInstance.h" +#include "clstepcore/explicitItemId.h" #include "implicitItemId.h" #include "sc_export.h" diff --git a/src/clstepcore/interfacedItem.h b/include/clstepcore/interfacedItem.h similarity index 89% rename from src/clstepcore/interfacedItem.h rename to include/clstepcore/interfacedItem.h index 00401b68b..238969836 100644 --- a/src/clstepcore/interfacedItem.h +++ b/include/clstepcore/interfacedItem.h @@ -1,9 +1,9 @@ #ifndef INTERFACEDITEM_H #define INTERFACEDITEM_H -#include "dictionaryInstance.h" +#include "clstepcore/dictionaryInstance.h" -#include "sdai.h" +#include "clstepcore/sdai.h" #include "sc_export.h" diff --git a/src/clstepcore/inverseAttribute.h b/include/clstepcore/inverseAttribute.h similarity index 98% rename from src/clstepcore/inverseAttribute.h rename to include/clstepcore/inverseAttribute.h index 0d02b793d..4008cdaf8 100644 --- a/src/clstepcore/inverseAttribute.h +++ b/include/clstepcore/inverseAttribute.h @@ -1,7 +1,7 @@ #ifndef INVERSEATTRIBUTE_H #define INVERSEATTRIBUTE_H -#include "attrDescriptor.h" +#include "clstepcore/attrDescriptor.h" class SC_CORE_EXPORT Inverse_attribute : public AttrDescriptor { diff --git a/src/clstepcore/inverseAttributeList.h b/include/clstepcore/inverseAttributeList.h similarity index 100% rename from src/clstepcore/inverseAttributeList.h rename to include/clstepcore/inverseAttributeList.h diff --git a/src/clstepcore/mgrnode.h b/include/clstepcore/mgrnode.h similarity index 97% rename from src/clstepcore/mgrnode.h rename to include/clstepcore/mgrnode.h index eca3e19e7..9bc96ef1d 100644 --- a/src/clstepcore/mgrnode.h +++ b/include/clstepcore/mgrnode.h @@ -18,12 +18,12 @@ class GenericNode; class DisplayNode; -#include +#include "clstepcore/sdai.h" -#include -#include +#include "clutils/gennode.h" +#include "clutils/gennodelist.h" -#include +#include "cleditor/editordefines.h" class InstMgr; diff --git a/src/clstepcore/mgrnodearray.h b/include/clstepcore/mgrnodearray.h similarity index 95% rename from src/clstepcore/mgrnodearray.h rename to include/clstepcore/mgrnodearray.h index 22019d071..c09f6995f 100644 --- a/src/clstepcore/mgrnodearray.h +++ b/include/clstepcore/mgrnodearray.h @@ -19,14 +19,14 @@ #include -#include -#include +#include "clutils/gennode.h" +#include "clutils/gennodelist.h" //#include -#include -#include +#include "clstepcore/mgrnode.h" +#include "clstepcore/mgrnodelist.h" -#include +#include "clutils/gennodearray.h" #define ARRAY_DEFAULT_SIZE (1024) diff --git a/src/clstepcore/mgrnodelist.h b/include/clstepcore/mgrnodelist.h similarity index 94% rename from src/clstepcore/mgrnodelist.h rename to include/clstepcore/mgrnodelist.h index be822c798..e085b66c5 100644 --- a/src/clstepcore/mgrnodelist.h +++ b/include/clstepcore/mgrnodelist.h @@ -17,10 +17,10 @@ #include -#include +#include "clutils/gennode.h" //#include -#include -#include +#include "clutils/gennodelist.h" +#include "cleditor/editordefines.h" ////////////////////////////////////////////////////////////////////////////// // class MgrNodeList diff --git a/src/clstepcore/needFunc.h b/include/clstepcore/needFunc.h similarity index 100% rename from src/clstepcore/needFunc.h rename to include/clstepcore/needFunc.h diff --git a/src/clstepcore/read_func.h b/include/clstepcore/read_func.h similarity index 99% rename from src/clstepcore/read_func.h rename to include/clstepcore/read_func.h index 92cff5705..448297164 100644 --- a/src/clstepcore/read_func.h +++ b/include/clstepcore/read_func.h @@ -2,7 +2,7 @@ #define READ_FUNC_H #include -#include +#include "clstepcore/sdai.h" /// This was 512. According to 10303-21:2002 section 5.6: comment length is unlimited. FIXME need to check the code for potential problems before eliminating this limit completely. #define MAX_COMMENT_LENGTH 8192 diff --git a/src/clstepcore/realTypeDescriptor.h b/include/clstepcore/realTypeDescriptor.h similarity index 100% rename from src/clstepcore/realTypeDescriptor.h rename to include/clstepcore/realTypeDescriptor.h diff --git a/src/clstepcore/schRename.h b/include/clstepcore/schRename.h similarity index 86% rename from src/clstepcore/schRename.h rename to include/clstepcore/schRename.h index a0403a5d8..b3f7fdefd 100644 --- a/src/clstepcore/schRename.h +++ b/include/clstepcore/schRename.h @@ -4,7 +4,7 @@ #include #include -#include "Str.h" +#include "clutils/Str.h" #include "sc_export.h" @@ -22,8 +22,10 @@ class SC_CORE_EXPORT SchRename { public: SchRename( const char * sch = "\0", const char * newnm = "\0" ) : next( 0 ) { - strcpy( schName, sch ); - strcpy( newName, newnm ); + strncpy( schName, sch, BUFSIZ ); + schName[BUFSIZ] = '\0'; + strncpy( newName, newnm, BUFSIZ ); + newName[BUFSIZ] = '\0'; } ~SchRename() { delete next; @@ -41,8 +43,8 @@ class SC_CORE_EXPORT SchRename { SchRename * next; private: - char schName[BUFSIZ]; - char newName[BUFSIZ]; + char schName[BUFSIZ+1]; + char newName[BUFSIZ+1]; }; diff --git a/src/clstepcore/sdai.h b/include/clstepcore/sdai.h similarity index 91% rename from src/clstepcore/sdai.h rename to include/clstepcore/sdai.h index 5751996a0..f063653ce 100644 --- a/src/clstepcore/sdai.h +++ b/include/clstepcore/sdai.h @@ -18,7 +18,7 @@ * values for the EXPRESS base types. */ -#include "sc_cf.h" +#include "config.h" #include extern const char * SCLversion; @@ -27,11 +27,11 @@ extern const char * SCLversion; #include -#include "dictdefs.h" +#include "clstepcore/dictdefs.h" -#include "baseType.h" -#include "Str.h" -#include "errordesc.h" +#include "clstepcore/baseType.h" +#include "clutils/Str.h" +#include "clutils/errordesc.h" typedef std::string Express_id; @@ -40,8 +40,8 @@ class EntityDescriptor; class SelectTypeDescriptor; class InstMgrBase; -#include "STEPattributeList.h" -#include "STEPinvAttrList.h" +#include "clstepcore/STEPattributeList.h" +#include "clstepcore/STEPinvAttrList.h" class STEPattributeList; class STEPattribute; @@ -155,12 +155,12 @@ typedef char * SDAI_Time_stamp; typedef char * SDAI_Entity_name; typedef char * SDAI_Schema_name; -#include +#include "cldai/sdaiString.h" -#include +#include "cldai/sdaiBinary.h" // define Object which I am calling sdaiObject for now - DAS -#include +#include "cldai/sdaiObject.h" /****************************************************************************** ENUMERATION @@ -172,7 +172,7 @@ ENUMERATION * the value ENUM_NULL is used to represent NULL for all enumerated types *****************************************************************************/ -#include +#include "cldai/sdaiEnum.h" /****************************************************************************** BOOLEAN and LOGICAL @@ -185,11 +185,11 @@ BOOLEAN and LOGICAL // ***note*** this file needs classes from sdaiEnum.h // define DAObjectID and classes PID, PID_DA, PID_SDAI, DAObject, DAObject_SDAI -#include +#include "cldai/sdaiDaObject.h" -#include -#include +#include "clstepcore/sdaiApplication_instance.h" +#include "cldai/sdaiApplication_instance_set.h" /****************************************************************************** SELECT @@ -198,18 +198,18 @@ SELECT sdaiSelect.h ******************************************************************************/ -#include +#include "clstepcore/sdaiSelect.h" class SDAI_Model_contents; typedef SDAI_Model_contents * SDAI_Model_contents_ptr; typedef SDAI_Model_contents_ptr SDAI_Model_contents_var; -#include +#include "cldai/sdaiModel_contents_list.h" -#include -#include -#include -#include +#include "cldai/sdaiSession_instance.h" +#include "cldai/sdaiEntity_extent.h" +#include "cldai/sdaiEntity_extent_set.h" +#include "cldai/sdaiModel_contents.h" // ENTITY extern SC_CORE_EXPORT SDAI_Application_instance NilSTEPentity; diff --git a/src/clstepcore/sdaiApplication_instance.h b/include/clstepcore/sdaiApplication_instance.h similarity index 99% rename from src/clstepcore/sdaiApplication_instance.h rename to include/clstepcore/sdaiApplication_instance.h index 405964c24..4e764f593 100644 --- a/src/clstepcore/sdaiApplication_instance.h +++ b/include/clstepcore/sdaiApplication_instance.h @@ -16,7 +16,7 @@ #include #include -#include +#include "cldai/sdaiDaObject.h" class EntityAggregate; class Inverse_attribute; diff --git a/src/clstepcore/sdaiSelect.h b/include/clstepcore/sdaiSelect.h similarity index 100% rename from src/clstepcore/sdaiSelect.h rename to include/clstepcore/sdaiSelect.h diff --git a/src/clstepcore/selectTypeDescriptor.h b/include/clstepcore/selectTypeDescriptor.h similarity index 100% rename from src/clstepcore/selectTypeDescriptor.h rename to include/clstepcore/selectTypeDescriptor.h diff --git a/src/clstepcore/stringTypeDescriptor.h b/include/clstepcore/stringTypeDescriptor.h similarity index 100% rename from src/clstepcore/stringTypeDescriptor.h rename to include/clstepcore/stringTypeDescriptor.h diff --git a/src/clstepcore/typeDescriptor.h b/include/clstepcore/typeDescriptor.h similarity index 99% rename from src/clstepcore/typeDescriptor.h rename to include/clstepcore/typeDescriptor.h index 915c1831d..51a815593 100644 --- a/src/clstepcore/typeDescriptor.h +++ b/include/clstepcore/typeDescriptor.h @@ -3,7 +3,7 @@ #include "schRename.h" #include "whereRule.h" -#include "dictSchema.h" +#include "clstepcore/dictSchema.h" #include "sc_export.h" @@ -111,7 +111,7 @@ class SC_CORE_EXPORT TypeDescriptor { /// schema which USEs/ REFERENCEs this. (A complete list of /// alternate names is stored in altNames below. _altname pro- /// vides storage space for the currently used one.) - char _altname[BUFSIZ]; + char _altname[BUFSIZ+1]; /// contains list of renamings of type - used by other schemas /// which USE/ REFERENCE this diff --git a/src/clstepcore/typeDescriptorList.h b/include/clstepcore/typeDescriptorList.h similarity index 100% rename from src/clstepcore/typeDescriptorList.h rename to include/clstepcore/typeDescriptorList.h diff --git a/src/clstepcore/typeOrRuleVar.h b/include/clstepcore/typeOrRuleVar.h similarity index 89% rename from src/clstepcore/typeOrRuleVar.h rename to include/clstepcore/typeOrRuleVar.h index 09f78da59..c698c5bd5 100644 --- a/src/clstepcore/typeOrRuleVar.h +++ b/include/clstepcore/typeOrRuleVar.h @@ -1,7 +1,7 @@ #ifndef TYPEORRULEVAR_H #define TYPEORRULEVAR_H -#include "dictionaryInstance.h" +#include "clstepcore/dictionaryInstance.h" #include "sc_export.h" diff --git a/src/clstepcore/uniquenessRule.h b/include/clstepcore/uniquenessRule.h similarity index 96% rename from src/clstepcore/uniquenessRule.h rename to include/clstepcore/uniquenessRule.h index 4751ce97b..b42a7414d 100644 --- a/src/clstepcore/uniquenessRule.h +++ b/include/clstepcore/uniquenessRule.h @@ -1,9 +1,9 @@ #ifndef UNIQUENESSRULE_H #define UNIQUENESSRULE_H -#include "dictionaryInstance.h" +#include "clstepcore/dictionaryInstance.h" -#include "sdai.h" +#include "clstepcore/sdai.h" #include "sc_export.h" diff --git a/src/clstepcore/whereRule.h b/include/clstepcore/whereRule.h similarity index 96% rename from src/clstepcore/whereRule.h rename to include/clstepcore/whereRule.h index ef9043a4b..98952d049 100644 --- a/src/clstepcore/whereRule.h +++ b/include/clstepcore/whereRule.h @@ -2,8 +2,8 @@ #define WHERERULE_H #include -#include "sdai.h" -#include "dictionaryInstance.h" +#include "clstepcore/sdai.h" +#include "clstepcore/dictionaryInstance.h" #include "typeOrRuleVar.h" #include "sc_export.h" diff --git a/include/clutils/CMakeLists.txt b/include/clutils/CMakeLists.txt new file mode 100644 index 000000000..9992890bc --- /dev/null +++ b/include/clutils/CMakeLists.txt @@ -0,0 +1,20 @@ +set(UTILS_HDRS + dirobj.h + errordesc.h + gennodearray.h + gennode.h + gennodelist.h + sc_hash.h + Str.h + ) + +install(FILES ${UTILS_HDRS} + DESTINATION ${INCLUDE_DIR}/stepcode/clutils) + +# Local Variables: +# tab-width: 8 +# mode: cmake +# indent-tabs-mode: t +# End: +# ex: shiftwidth=2 tabstop=8 + diff --git a/src/clutils/Str.h b/include/clutils/Str.h similarity index 98% rename from src/clutils/Str.h rename to include/clutils/Str.h index f605bfdda..487a2c9e2 100644 --- a/src/clutils/Str.h +++ b/include/clutils/Str.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include "clutils/errordesc.h" #ifndef STRING_DELIM #define STRING_DELIM '\'' diff --git a/src/clutils/dirobj.h b/include/clutils/dirobj.h similarity index 95% rename from src/clutils/dirobj.h rename to include/clutils/dirobj.h index a89e28dad..fe847a1e5 100644 --- a/src/clutils/dirobj.h +++ b/include/clutils/dirobj.h @@ -33,7 +33,7 @@ // /////////////////////////////////////////////////////////////////////////////// -#include +#include "config.h" #include #include @@ -61,10 +61,10 @@ class SC_UTILS_EXPORT DirObj { const char * File( int index ); // check for file in the currently loaded directory bool FileExists( const char * file ) { - return Index( file ) ? 1 : 0; + return Index( file ) != -1; } bool FileExists( const std::string & file ) { - return Index( file.c_str() ) ? true : false; + return Index( file.c_str() ) != -1; } int Count(); diff --git a/src/clutils/errordesc.h b/include/clutils/errordesc.h similarity index 100% rename from src/clutils/errordesc.h rename to include/clutils/errordesc.h diff --git a/src/clutils/gennode.h b/include/clutils/gennode.h similarity index 100% rename from src/clutils/gennode.h rename to include/clutils/gennode.h diff --git a/src/clutils/gennodearray.h b/include/clutils/gennodearray.h similarity index 98% rename from src/clutils/gennodearray.h rename to include/clutils/gennodearray.h index 4c0ee075a..1643f05e6 100644 --- a/src/clutils/gennodearray.h +++ b/include/clutils/gennodearray.h @@ -26,7 +26,7 @@ #include #include // to get bcopy for CenterLine -#include +#include "clutils/gennode.h" // the initial size of the array #define ARRAY_DEFAULT_SIZE (1024) diff --git a/src/clutils/gennodelist.h b/include/clutils/gennodelist.h similarity index 100% rename from src/clutils/gennodelist.h rename to include/clutils/gennodelist.h diff --git a/src/clutils/sc_hash.h b/include/clutils/sc_hash.h similarity index 100% rename from src/clutils/sc_hash.h rename to include/clutils/sc_hash.h diff --git a/include/sc_cf_cmake.h.in b/include/config.h.in similarity index 90% rename from include/sc_cf_cmake.h.in rename to include/config.h.in index 873be14bf..63ccc4ed1 100644 --- a/include/sc_cf_cmake.h.in +++ b/include/config.h.in @@ -2,6 +2,7 @@ #define SCL_CF_H /**** Define statements for CMake ****/ +#cmakedefine SC_VERSION "@SC_VERSION@" #cmakedefine HAVE_NDIR_H 1 #cmakedefine HAVE_STDINT_H 1 #cmakedefine HAVE_SYS_STAT_H 1 @@ -14,7 +15,6 @@ #cmakedefine HAVE_IO_H 1 #cmakedefine SC_TRACE_FPRINTF 1 -#cmakedefine SC_MEMMGR_ENABLE_CHECKS 1 #cmakedefine HAVE_ABS 1 #cmakedefine HAVE_MEMCPY 1 @@ -26,5 +26,6 @@ #cmakedefine HAVE_STD_THREAD 1 #cmakedefine HAVE_STD_CHRONO 1 +#cmakedefine HAVE_NULLPTR 1 #endif /* SCL_CF_H */ diff --git a/include/exppp/exppp.h b/include/exppp/exppp.h index f6159cbf5..e519aa70b 100644 --- a/include/exppp/exppp.h +++ b/include/exppp/exppp.h @@ -1,7 +1,7 @@ #ifndef EXPPP_H #define EXPPP_H -#include +#include #include diff --git a/include/express/alloc.h b/include/express/alloc.h index 79199773a..1c95792d4 100644 --- a/include/express/alloc.h +++ b/include/express/alloc.h @@ -58,7 +58,7 @@ struct freelist_head { #endif }; -char * nnew(); +char * nnew(void); #include "error.h" diff --git a/include/express/basic.h b/include/express/basic.h index 2dffecf3c..191924812 100644 --- a/include/express/basic.h +++ b/include/express/basic.h @@ -71,7 +71,7 @@ * */ -#include +#include "config.h" #include #include @@ -82,7 +82,7 @@ #ifdef HAVE_STDBOOL_H # include #else -# include +# include #endif #if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(__cplusplus) @@ -93,8 +93,11 @@ /* function pointer types */ /**************************/ -typedef void ( *voidFuncptr )(); -typedef int ( *intFuncptr )(); +typedef void ( *voidFuncptr )(void); +typedef int ( *intFuncptr )(void); + +/* Option index - can we get rid of this? */ +extern SC_EXPRESS_EXPORT int sc_optind; #endif /* BASIC_H */ diff --git a/include/express/factory.h b/include/express/factory.h index 4942256fe..f4400d9e7 100644 --- a/include/express/factory.h +++ b/include/express/factory.h @@ -3,6 +3,6 @@ #include "sc_export.h" -SC_EXPRESS_EXPORT void FACTORYinitialize(); +SC_EXPRESS_EXPORT void FACTORYinitialize(void); #endif /* __FACTORY_H_ */ diff --git a/include/express/memory.h b/include/express/memory.h index 3d1e58c74..02adac89e 100644 --- a/include/express/memory.h +++ b/include/express/memory.h @@ -3,6 +3,6 @@ #include "sc_export.h" -SC_EXPRESS_EXPORT void MEMORYinitialize(); +SC_EXPRESS_EXPORT void MEMORYinitialize(void); #endif // __MEMORY_H diff --git a/include/express/object.h b/include/express/object.h index e5736f45b..15e4a435f 100644 --- a/include/express/object.h +++ b/include/express/object.h @@ -68,7 +68,7 @@ /***************************/ struct Object { - struct Symbol_ * ( *get_symbol )(); + struct Symbol_ * ( *get_symbol )( void * ); char * type; /**< should complete the phrase "X is ..." - i.e., "an entity", "a type", "of unknown type" */ int bits; /**< a bitwise selector of a type, i.e. OBJ_XX_BITS */ }; diff --git a/include/sc_stdbool.h b/include/sc_stdbool.h deleted file mode 100644 index 0591fa536..000000000 --- a/include/sc_stdbool.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef STDBOOL_H_ -#define STDBOOL_H_ - -/** - * stdbool.h - ISO C99 Boolean type - * Author - Bill Chatfield - * E-mail - bill underscore chatfield at yahoo dot com - * Copyright - You are free to use for any purpose except illegal acts - * Warrenty - None: don't blame me if it breaks something - * - * In ISO C99, stdbool.h is a standard header and _Bool is a keyword, but - * some compilers don't offer these yet. This header file is an - * implementation of the standard ISO C99 stdbool.h header file. It checks - * for various compiler versions and defines things that are missing in - * those versions. - * - * See http://predef.sourceforge.net/precomp.html for compile macros. - */ - -#ifndef __cplusplus - -/** - * Microsoft C/C++ version 14.00.50727.762, which comes with Visual C++ 2005, - * and version 15.00.30729.01, which comes with Visual C++ 2008, do not - * define _Bool. - */ -#if defined(_MSC_VER) && _MSC_VER<1800 -typedef int _Bool; -#endif - -/** - * Define the Boolean macros only if they are not already defined. - */ -#ifndef __bool_true_false_are_defined -#define bool _Bool -#define false 0 -#define true 1 -#define __bool_true_false_are_defined 1 -#endif - -#endif /* __cplusplus */ - -#endif /*STDBOOL_H_*/ diff --git a/lcov.cmake b/lcov.cmake index 4ca1388db..74adc1576 100644 --- a/lcov.cmake +++ b/lcov.cmake @@ -15,7 +15,7 @@ BUILDNAME:STRING=${CTEST_BUILD_NAME} SC_ENABLE_TESTING:BOOL=ON SC_ENABLE_COVERAGE:BOOL=ON SC_BUILD_SCHEMAS:STRING=ALL -SC_BUILD_TYPE:STRING=Debug +CMAKE_BUILD_TYPE:STRING=Debug ") set(LCOV_OUT "${CTEST_BINARY_DIRECTORY}/lcov_html") diff --git a/misc/header_mv.sh b/misc/header_mv.sh new file mode 100755 index 000000000..0d2be0f0f --- /dev/null +++ b/misc/header_mv.sh @@ -0,0 +1,10 @@ +#!/bin/bash +find . -type f -path "*/cl*" -not -path "*.git/*" -not -path "*/exp*" -regex '.*\(c\|cc\|cpp\|cxx\|h\|hpp\)$' -exec perl -0777 -pi -e "s/include \"$1\"/include \"utils\/$1\"/g" {} \; +find . -type f -path "*/cl*" -not -path "*.git/*" -not -path "*/exp*" -regex '.*\(c\|cc\|cpp\|cxx\|h\|hpp\)$' -exec perl -0777 -pi -e "s/include <$1>/include \"utils\/$1\"/g" {} \; + +find . -type f -path "*/include*" -not -path "*.git/*" -regex '.*\(c\|cc\|cpp\|cxx\|h\|hpp\)$' -exec perl -0777 -pi -e "s/include \"$1\"/include \"utils\/$1\"/g" {} \; +find . -type f -path "*/include*" -not -path "*.git/*" -regex '.*\(c\|cc\|cpp\|cxx\|h\|hpp\)$' -exec perl -0777 -pi -e "s/include <$1>/include \"utils\/$1\"/g" {} \; + +find . -type f -path "*/test*" -not -path "*.git/*" -regex '.*\(c\|cc\|cpp\|cxx\|h\|hpp\)$' -exec perl -0777 -pi -e "s/include \"$1\"/include \"utils\/$1\"/g" {} \; +find . -type f -path "*/test*" -not -path "*.git/*" -regex '.*\(c\|cc\|cpp\|cxx\|h\|hpp\)$' -exec perl -0777 -pi -e "s/include <$1>/include \"utils\/$1\"/g" {} \; + diff --git a/run_ctest.cmake b/run_ctest.cmake index 7533d7c17..a8d833789 100644 --- a/run_ctest.cmake +++ b/run_ctest.cmake @@ -9,7 +9,7 @@ set(CTEST_INITIAL_CACHE " SITE:STRING=${CTEST_SITE} BUILDNAME:STRING=${CTEST_BUILD_NAME} SC_ENABLE_TESTING:BOOL=ON -SC_BUILD_TYPE:STRING=Debug +CMAKE_BUILD_TYPE:STRING=Debug ") diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt deleted file mode 100644 index 5aad0a929..000000000 --- a/src/base/CMakeLists.txt +++ /dev/null @@ -1,72 +0,0 @@ - -set(SC_BASE_SOURCES - sc_memmgr.cc - sc_trace_fprintf.c - sc_getopt.cc - sc_benchmark.cc - sc_mkdir.c - path2str.c - judy/src/judy.c - ) - -set(SC_BASE_HDRS - sc_benchmark.h - sc_memmgr.h - sc_getopt.h - sc_trace_fprintf.h - sc_mkdir.h - path2str.h - judy/src/judy.h - judy/src/judyLArray.h - judy/src/judyL2Array.h - judy/src/judySArray.h - judy/src/judyS2Array.h - ) - -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/judy/src - ) - -if($CACHE{SC_MEMMGR_ENABLE_CHECKS}) - add_definitions(-DSC_MEMMGR_ENABLE_CHECKS) -endif() - -if(BUILD_SHARED_LIBS) - SC_ADDLIB(base SHARED SOURCES ${SC_BASE_SOURCES}) - if(WIN32) - target_link_libraries(base psapi) - target_compile_definitions(base PRIVATE SC_BASE_DLL_EXPORTS) - endif() -endif() - -if(BUILD_STATIC_LIBS) - SC_ADDLIB(base-static STATIC SOURCES ${SC_BASE_SOURCES}) - if(WIN32) - target_link_libraries(base-static psapi) - endif() -endif() - -if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/judy/src") - message("Judy array source code not found. Downloading (don't sweat, it's public domain)...") - file(DOWNLOAD "http://github.com/mpictor/judy-template/archive/master.tar.gz" - "${CMAKE_CURRENT_SOURCE_DIR}/judy.tar.gz" SHOW_PROGRESS) - execute_process( - COMMAND ${CMAKE_COMMAND} -E tar xzf "${CMAKE_CURRENT_SOURCE_DIR}/judy.tar.gz" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/" - ) - file(RENAME judy-template-master judy) - file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/judy.tar.gz") - message("Judy array source code extracted.") -endif(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/judy/src") - -install(FILES ${SC_BASE_HDRS} - DESTINATION ${INCLUDE_DIR}/stepcode/base) - -# Local Variables: -# tab-width: 8 -# mode: cmake -# indent-tabs-mode: t -# End: -# ex: shiftwidth=2 tabstop=8 - diff --git a/src/base/judy/CMakeLists.txt b/src/base/judy/CMakeLists.txt deleted file mode 100644 index 3c26e4df2..000000000 --- a/src/base/judy/CMakeLists.txt +++ /dev/null @@ -1,78 +0,0 @@ - -cmake_minimum_required(VERSION 3.12) -project( JudyTemplates ) - -if( NOT DEFINED CMAKE_BUILD_TYPE ) - # set( CMAKE_BUILD_TYPE "RelWithDebInfo" ) #optimize, but include debug info - set( CMAKE_BUILD_TYPE "Release" ) -endif( NOT DEFINED CMAKE_BUILD_TYPE ) - -SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) -SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) -SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) - -if( NOT DEFINED JUDY_OPTIMIZE_FLAGS ) - if( CMAKE_COMPILER_IS_GNUCC ) - set( JUDY_OPTIMIZE_FLAGS "-march=native" ) - - #test for LTO; this uses an internal variable so it may break - if( DEFINED CMAKE_C_COMPILER_VERSION ) - if( ${CMAKE_C_COMPILER_VERSION} VERSION_GREATER 4.7.0 ) - set( JUDY_OPTIMIZE_FLAGS "${JUDY_OPTIMIZE_FLAGS} -flto" ) - message( " -- GCC version: ${CMAKE_C_COMPILER_VERSION}. Enabling link-time optimization." ) - endif( ${CMAKE_C_COMPILER_VERSION} VERSION_GREATER 4.7.0 ) - endif( DEFINED CMAKE_C_COMPILER_VERSION ) - #elseif( MSVC ) - # set( JUDY_OPTIMIZE_FLAGS "..." ) # <--- set MSVC flags here <--- - else() - message( "Unrecognized compiler - no optimization flags set. Edit CMakeLists.txt or set JUDY_OPTIMIZE_FLAGS." ) - set( JUDY_OPTIMIZE_FLAGS "" ) - endif( CMAKE_COMPILER_IS_GNUCC ) -endif( NOT DEFINED JUDY_OPTIMIZE_FLAGS ) -add_definitions( ${JUDY_OPTIMIZE_FLAGS} ) - -set( JUDYS_SOURCES src/judy.c src/judy.h ) - -if( CMAKE_COMPILER_IS_GNUCC ) - add_definitions( -pedantic -W -Wall -Wundef -Wfloat-equal -Wshadow -Winline -Wno-long-long ) -endif( CMAKE_COMPILER_IS_GNUCC ) - -add_library( judy_lib STATIC ${JUDYS_SOURCES} ) - -include_directories( src ) - -if( ENABLE_TESTING ) - include( CTest ) - include_directories( test ) - enable_testing() - - add_executable( pennysort test/pennySort.c test/sort.c ${JUDYS_SOURCES} ) - add_executable( hexsort test/hexSort.c test/sort.c ${JUDYS_SOURCES} ) - set_target_properties( pennysort hexsort PROPERTIES COMPILE_FLAGS "-DSTANDALONE" ) - - - add_executable( judyLtest test/judyLtest.cc ) - target_link_libraries( judyLtest judy_lib ) - add_test( judyLtest judyLtest ) - - add_executable( judyL2test test/judyL2test.cc ) - target_link_libraries( judyL2test judy_lib ) - add_test( judyL2test judyL2test ) - - add_executable( judyStest test/judyStest.cc ) - target_link_libraries( judyStest judy_lib ) - add_test( judyStest judyStest ) - - add_executable( judyS2test test/judyS2test.cc ) - target_link_libraries( judyS2test judy_lib ) - add_test( judyS2test judyS2test ) - -endif( ENABLE_TESTING ) - -# Local Variables: -# tab-width: 8 -# mode: cmake -# indent-tabs-mode: t -# End: -# ex: shiftwidth=2 tabstop=8 - diff --git a/src/base/judy/README.md b/src/base/judy/README.md deleted file mode 100644 index 5fc134587..000000000 --- a/src/base/judy/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Judy Array Templates -The Judy Array is a sparse dynamic array. It is a particular kind of trie that is highly efficient in space and time, and does not require tuning. - -This uses [Karl Malbrain's implementation](http://code.google.com/p/judyarray/) of the Judy Array. Additional information can be found with Doug Baskins' [original implementation](http://judy.sourceforge.net/) on sourceforge, or on [Wikipedia](http://en.wikipedia.org/wiki/Judy_array). -## The templates -* `judyLArray` - a C++ template wrapper for an int-int Judy Array. JudyKey and JudyValue must be integer types and the same size as a pointer (i.e. 32- or 64-bit) -* `judySArray` - Same as judyLArray, but with string-int mapping. The above restrictions on JudyValue apply here as well. -* **TODO** - single-key, multi-value versions of the above -* **TODO** - single-key, n-value versions of the above *(?)* - -## Comparison between this and the versions Karl and Doug wrote -* Doug Baskins' code is licenced under the LGPL. While more permissive than the GPL, it's still not always acceptable. His code is very fast but weighs in at ~20k lines. -* Karl Malbrain's code is ~1250 lines, in a single file containing the judy array and the test code; use requires creating a header. -* Both of the above are written in C, so they don't fit neatly into object-oriented C++. -* Unlike Doug's code, this is ~1250 lines. Unlike Karl's, this is split into several files. - -## Files -* `CMakeLists.txt` - CMake build logic. If you don't have CMake, it should be quite easy to write a file for the build system of your choice. -* **src/** - * `judy.c`, `judy.h` - implementation of the Judy Array - * `judyLArray.h` - the judyLArray template - * `judySArray.h` - the judySArray template -* **test/** - * `hexSort.c` - Sorts a file where each line contains 32 hex chars. Compiles to `hexsort`, which is the same executable as compiling Karl's code with `-DHEXSORT -DSTANDALONE` - * `pennySort.c` - Sorts strings; compiles to `pennysort`. Same as compiling Karl's code with `-DSTANDALONE`. - * `sort.c`, `sort.h` - Karl's sorting functions. Only used by `hexsort` and `pennysort`. - * `judyLtest.cc` - an incomplete test of the judyLArray template. - * `judyStest.cc` - an incomplete test of the judySArray template. - - -## Compiling -* requires C and C++ compilers, CMake. -* from the command line: - * `mkdir build; cd build` - * `cmake .. -DENABLE_TESTING=TRUE` - * `make` - -## License - -Karl Malbrain's judy array code is public domain; what I've added is public domain as well. - -## Contact -mpictor -a-t- gmail diff --git a/src/base/judy/misc/astyle.cfg b/src/base/judy/misc/astyle.cfg deleted file mode 100644 index eec1dd399..000000000 --- a/src/base/judy/misc/astyle.cfg +++ /dev/null @@ -1,29 +0,0 @@ -#astyle config file - -#run astyle on one or a few files: use -# astyle --options=misc/astyle.cfg path/to/file - -#run astyle on all files: from the root dir, use -# astyle --options=misc/astyle.cfg --recursive "src/*.c" "src/*.h" "test/*.c" "test/*.h" -# in the above line, the double quotes *are* necessary - - -suffix=none #don't create backup files - -style=java #compact bracket style - -indent=spaces=4 - -indent-preprocessor -indent-classes -indent-switches -indent-namespaces -pad-oper #pad (space) around operators -pad-paren-in #pad inside parenthesis -unpad-paren #remove parenthesis padding other than requested above - -add-brackets #add brackets on one-line conditionals -convert-tabs #convert all tabs to spaces -align-pointer=middle #char * foo - -lineend=linux #lines end with LF (linux), not CRLF (windows) diff --git a/src/base/judy/misc/hextest.sh b/src/base/judy/misc/hextest.sh deleted file mode 100755 index ee8606d48..000000000 --- a/src/base/judy/misc/hextest.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -#generates a file of hex keys and runs hexsort on it. No verification is done. -#hex data comes from /dev/urandom, so it isn't all that random. - -hexdump -v -e '2/8 "%08x"' -e '"\n"' /dev/urandom |head -n 1000000 >ukeys -#a.out [in-file] [out-file] [keysize] [recordlen] [keyoffset] [mergerecs] -time bin/hexsort ukeys skeys \ No newline at end of file diff --git a/src/base/judy/misc/judy64n.c b/src/base/judy/misc/judy64n.c deleted file mode 100644 index 8dc8f909a..000000000 --- a/src/base/judy/misc/judy64n.c +++ /dev/null @@ -1,2084 +0,0 @@ -// Judy arrays 23 NOV 2012 - -// Author Karl Malbrain, malbrain@yahoo.com -// with assistance from Jan Weiss. - -// Simplified judy arrays for strings and integers -// Adapted from the ideas of Douglas Baskins of HP. - -// The -D ASKITIS benchmarking option was implemented with -// assistance from Dr. Nikolas Askitis (www.naskitis.com). - -// Map a set of keys to corresponding memory cells (unsigned ints). -// Each cell must be set to a non-zero value by the caller. - -// STANDALONE is defined to compile into a string sorter. - -// String mappings are denoted by calling judy_open with zero as -// the second argument. Integer mappings are denoted by calling -// judy_open with the Integer depth of the Judy Trie as the second -// argument. - -//#define STANDALONE - -// functions: -// judy_open: open a new judy array returning a judy object. -// judy_close: close an open judy array, freeing all memory. -// judy_clone: clone an open judy array, duplicating the stack. -// judy_data: allocate data memory within judy array for external use. -// judy_cell: insert a string into the judy array, return cell pointer. -// judy_strt: retrieve the cell pointer greater than or equal to given key -// judy_slot: retrieve the cell pointer, or return NULL for a given key. -// judy_key: retrieve the string value for the most recent judy query. -// judy_end: retrieve the cell pointer for the last string in the array. -// judy_nxt: retrieve the cell pointer for the next string in the array. -// judy_prv: retrieve the cell pointer for the prev string in the array. -// judy_del: delete the key and cell for the current stack entry. - -#include -#include -#include - -#ifdef linux - #define _FILE_OFFSET_BITS 64 - #define _LARGEFILE_SOURCE - #define __USE_FILE_OFFSET64 - - #include -#else - #ifdef __BIG_ENDIAN__ - #ifndef BYTE_ORDER - #define BYTE_ORDER 4321 - #endif - #else - #ifndef BYTE_ORDER - #define BYTE_ORDER 1234 - #endif - #endif - #ifndef BIG_ENDIAN - #define BIG_ENDIAN 4321 - #endif -#endif - - - -#define PRIuint "u" - -#if defined(__LP64__) || \ - defined(__x86_64__) || \ - defined(__amd64__) || \ - defined(_WIN64) || \ - defined(__sparc64__) || \ - defined(__arch64__) || \ - defined(__powerpc64__) || \ - defined (__s390x__) - // defines for 64 bit - - typedef unsigned long long judyvalue; - typedef unsigned long long JudySlot; - #define JUDY_key_mask (0x07) - #define JUDY_key_size 8 - #define JUDY_slot_size 8 - #define JUDY_span_bytes (3 * JUDY_key_size) - #define JUDY_span_equiv JUDY_2 - #define JUDY_radix_equiv JUDY_8 - - #define PRIjudyvalue "llu" - -#else - // defines for 32 bit - - typedef unsigned int judyvalue; - typedef unsigned int JudySlot; - #define JUDY_key_mask (0x03) - #define JUDY_key_size 4 - #define JUDY_slot_size 4 - #define JUDY_span_bytes (7 * JUDY_key_size) - #define JUDY_span_equiv JUDY_4 - #define JUDY_radix_equiv JUDY_8 - - #define PRIjudyvalue "u" - -#endif - -#define JUDY_mask (~(JudySlot)0x07) - -// define the alignment factor for judy nodes and allocations -// to enable this feature, set to 64 - -#define JUDY_cache_line 8 // minimum size is 8 bytes - -#if defined(STANDALONE) || defined(ASKITIS) -#include -#include - -unsigned int MaxMem = 0; - -// void judy_abort (char *msg) __attribute__ ((noreturn)); // Tell static analyser that this function will not return -void judy_abort (char *msg) -{ - fprintf(stderr, "%s\n", msg); - exit(1); -} -#endif - -#define JUDY_seg 65536 - -enum JUDY_types { - JUDY_radix = 0, // inner and outer radix fan-out - JUDY_1 = 1, // linear list nodes of designated count - JUDY_2 = 2, - JUDY_4 = 3, - JUDY_8 = 4, - JUDY_16 = 5, - JUDY_32 = 6, -#ifdef ASKITIS - JUDY_64 = 7 -#else - JUDY_span = 7 // up to 28 tail bytes of key contiguously stored -#endif -}; - -int JudySize[] = { - (JUDY_slot_size * 16), // JUDY_radix node size - (JUDY_slot_size + JUDY_key_size), // JUDY_1 node size - (2 * JUDY_slot_size + 2 * JUDY_key_size), - (4 * JUDY_slot_size + 4 * JUDY_key_size), - (8 * JUDY_slot_size + 8 * JUDY_key_size), - (16 * JUDY_slot_size + 16 * JUDY_key_size), - (32 * JUDY_slot_size + 32 * JUDY_key_size), -#ifndef ASKITIS - (JUDY_span_bytes + JUDY_slot_size) -#else - (64 * JUDY_slot_size + 64 * JUDY_key_size) -#endif -}; - -judyvalue JudyMask[9] = { -0, 0xff, 0xffff, 0xffffff, 0xffffffff, -#if JUDY_key_size > 4 -0xffffffffffULL, 0xffffffffffffULL, 0xffffffffffffffULL, 0xffffffffffffffffULL -#endif -}; - -typedef struct { - void *seg; // next used allocator - unsigned int next; // next available offset -} JudySeg; - -typedef struct { - JudySlot next; // judy object - unsigned int off; // offset within key - int slot; // slot within object -} JudyStack; - -typedef struct { - JudySlot root[1]; // root of judy array - void **reuse[8]; // reuse judy blocks - JudySeg *seg; // current judy allocator - unsigned int level; // current height of stack - unsigned int max; // max height of stack - unsigned int depth; // number of Integers in a key, or zero for string keys - JudyStack stack[1]; // current cursor -} Judy; - -#ifdef ASKITIS -int Words = 0; -int Inserts = 0; -int Found = 0; - -#if JUDY_key_size < 8 -#define JUDY_max JUDY_16 -#else -#define JUDY_max JUDY_64 -#endif -#else -#define JUDY_max JUDY_32 -#endif - -// open judy object -// call with max key size -// and Integer tree depth. - -void *judy_open (unsigned int max, unsigned int depth) -{ -JudySeg *seg; -Judy *judy; -unsigned int amt; - - max++; // allow for zero terminator on keys - - if( (seg = malloc(JUDY_seg)) ) { - seg->seg = NULL; - seg->next = JUDY_seg; - } else { -#if defined(STANDALONE) || defined(ASKITIS) - judy_abort ("No virtual memory"); -#else - return NULL; -#endif - } - - amt = sizeof(Judy) + max * sizeof(JudyStack); - - if( amt & (JUDY_cache_line - 1) ) - amt |= JUDY_cache_line - 1, amt++; - -#if defined(STANDALONE) || defined(ASKITIS) - MaxMem += JUDY_seg; -#endif - - seg->next -= (JudySlot)seg & (JUDY_cache_line - 1); - seg->next -= amt; - - judy = (Judy *)((unsigned char *)seg + seg->next); - memset(judy, 0, amt); - judy->depth = depth; - judy->seg = seg; - judy->max = max; - return judy; -} - -void judy_close (Judy *judy) -{ -JudySeg *seg, *nxt = judy->seg; - - while( (seg = nxt) ) - nxt = seg->seg, free (seg); -} - -// allocate judy node - -void *judy_alloc (Judy *judy, unsigned int type) -{ -unsigned int amt, idx, min; -JudySeg *seg; -void **block; -void **rtn; - - if( !judy->seg ) -#if defined(STANDALONE) || defined(ASKITIS) - judy_abort("illegal allocation from judy clone"); -#else - return NULL; -#endif - - if( type == JUDY_radix ) - type = JUDY_radix_equiv; - -#ifndef ASKITIS - if( type == JUDY_span ) - type = JUDY_span_equiv; -#endif - - amt = JudySize[type]; - - if( amt & 0x07 ) - amt |= 0x07, amt += 1; - - // see if free block is already available - - if( (block = judy->reuse[type]) ) { - judy->reuse[type] = *block; - memset (block, 0, amt); - return (void *)block; - } - - // break down available larger block - // for reuse into smaller blocks - - if( type >= JUDY_1 ) - for( idx = type; idx++ < JUDY_max; ) - if( block = judy->reuse[idx] ) { - judy->reuse[idx] = *block; - while( idx-- > type) { - judy->reuse[idx] = block + JudySize[idx] / sizeof(void *); - block[JudySize[idx] / sizeof(void *)] = 0; - } - memset (block, 0, amt); - return (void *)block; - } - - min = amt < JUDY_cache_line ? JUDY_cache_line : amt; - - if( judy->seg->next < min + sizeof(*seg) ) { - if( (seg = malloc (JUDY_seg)) ) { - seg->next = JUDY_seg; - seg->seg = judy->seg; - judy->seg = seg; - seg->next -= (JudySlot)seg & (JUDY_cache_line - 1); - } else { -#if defined(STANDALONE) || defined(ASKITIS) - judy_abort("Out of virtual memory"); -#else - return NULL; -#endif - } - -#if defined(STANDALONE) || defined(ASKITIS) - MaxMem += JUDY_seg; -#endif - } - - // generate additional free blocks - // to fill up to cache line size - - rtn = (void **)((unsigned char *)judy->seg + judy->seg->next - amt); - - for( idx = type; amt & (JUDY_cache_line - 1); amt <<= 1 ) { - block = (void **)((unsigned char *)judy->seg + judy->seg->next - 2 * amt); - judy->reuse[idx++] = block; - *block = 0; - } - - judy->seg->next -= amt; - memset (rtn, 0, JudySize[type]); - return (void *)rtn; -} - -void *judy_data (Judy *judy, unsigned int amt) - -{ -JudySeg *seg; -void *block; - - if( !judy->seg ) -#if defined(STANDALONE) || defined(ASKITIS) - judy_abort("illegal allocation from judy clone"); -#else - return NULL; -#endif - - if( amt & (JUDY_cache_line - 1)) - amt |= (JUDY_cache_line - 1), amt += 1; - - if( judy->seg->next < amt + sizeof(*seg) ) { - if( (seg = malloc (JUDY_seg)) ) { - seg->next = JUDY_seg; - seg->seg = judy->seg; - judy->seg = seg; - seg->next -= (JudySlot)seg & (JUDY_cache_line - 1); - } else { -#if defined(STANDALONE) || defined(ASKITIS) - judy_abort("Out of virtual memory"); -#else - return NULL; -#endif - } - -#if defined(STANDALONE) || defined(ASKITIS) - MaxMem += JUDY_seg; -#endif - } - - judy->seg->next -= amt; - - block = (void *)((unsigned char *)judy->seg + judy->seg->next); - memset (block, 0, amt); - return block; -} - -void *judy_clone (Judy *judy) -{ -Judy *clone; -unsigned int amt; - - amt = sizeof(Judy) + judy->max * sizeof(JudyStack); - clone = judy_data (judy, amt); - memcpy (clone, judy, amt); - clone->seg = NULL; // stop allocations from cloned array - return clone; -} - -void judy_free (Judy *judy, void *block, int type) -{ - if( type == JUDY_radix ) - type = JUDY_radix_equiv; - -#ifndef ASKITIS - if( type == JUDY_span ) - type = JUDY_span_equiv; -#endif - - *((void **)(block)) = judy->reuse[type]; - judy->reuse[type] = (void **)block; - return; -} - -// assemble key from current path - -unsigned int judy_key (Judy *judy, unsigned char *buff, unsigned int max) -{ -judyvalue *dest = (judyvalue *)buff; -unsigned int len = 0, idx = 0, depth; -int slot, off, type; -judyvalue value; -unsigned char *base; -int keysize; - - if( judy->depth ) - max = judy->depth * JUDY_key_size; - else - max--; // leave room for zero terminator - - while( len < max && ++idx <= judy->level ) { - type = judy->stack[idx].next & 0x07; - slot = judy->stack[idx].slot; - depth = len / JUDY_key_size; - - if( judy->depth ) - if( !(len & JUDY_key_mask) ) - dest[depth] = 0; - - switch( type ) { - case JUDY_1: - case JUDY_2: - case JUDY_4: - case JUDY_8: - case JUDY_16: - case JUDY_32: -#ifdef ASKITIS - case JUDY_64: -#endif - keysize = JUDY_key_size - (judy->stack[idx].off & JUDY_key_mask); - base = (unsigned char *)(judy->stack[idx].next & JUDY_mask); - - if( judy->depth ) { - value = *(judyvalue *)(base + slot * keysize); - value &= JudyMask[keysize]; - dest[depth++] |= value; - len += keysize; - - if( depth < judy->depth ) - continue; - - return len; - } - -#if BYTE_ORDER != BIG_ENDIAN - off = keysize; - - while( off-- && len < max ) - if( buff[len] = base[slot * keysize + off] ) - len++; - else - break; -#else - for( off = 0; off < keysize && len < max; off++ ) - if( buff[len] = base[slot * keysize + off] ) - len++; - else - break; -#endif - continue; - - case JUDY_radix: - if( judy->depth ) { - dest[depth] |= (judyvalue)slot << (JUDY_key_size - (++len & JUDY_key_mask)) * 8; - if( !(len & JUDY_key_mask) ) - depth++; - if( depth < judy->depth ) - continue; - - return len; - } - - if( !slot ) - break; - buff[len++] = (unsigned char)slot; - continue; - -#ifndef ASKITIS - case JUDY_span: - base = (unsigned char *)(judy->stack[idx].next & JUDY_mask); - - for( slot = 0; slot < JUDY_span_bytes && base[slot]; slot++ ) - if( len < max ) - buff[len++] = base[slot]; - continue; -#endif - } - } - buff[len] = 0; - return len; -} - -// find slot & setup cursor - -JudySlot *judy_slot (Judy *judy, unsigned char *buff, unsigned int max) -{ -judyvalue *src = (judyvalue *)buff; -int slot, size, keysize, tst, cnt; -JudySlot next = *judy->root; -judyvalue value, test = 0; -JudySlot *table; -JudySlot *node; -unsigned int depth = 0; -unsigned int off = 0; -unsigned char *base; - -#ifndef ASKITIS - judy->level = 0; -#endif - - while( next ) { -#ifndef ASKITIS - if( judy->level < judy->max ) - judy->level++; - - judy->stack[judy->level].next = next; - judy->stack[judy->level].off = off; -#endif - size = JudySize[next & 0x07]; - - switch( next & 0x07 ) { - - case JUDY_1: - case JUDY_2: - case JUDY_4: - case JUDY_8: - case JUDY_16: - case JUDY_32: -#ifdef ASKITIS - case JUDY_64: -#endif - base = (unsigned char *)(next & JUDY_mask); - node = (JudySlot *)((next & JUDY_mask) + size); - keysize = JUDY_key_size - (off & JUDY_key_mask); - cnt = size / (sizeof(JudySlot) + keysize); - slot = cnt; - value = 0; - - if( judy->depth ) { - value = src[depth++]; - off |= JUDY_key_mask; - off++; - value &= JudyMask[keysize]; - } else - do { - value <<= 8; - if( off < max ) - value |= buff[off]; - } while( ++off & JUDY_key_mask ); - - // find slot > key - - while( slot-- ) { - test = *(judyvalue *)(base + slot * keysize); -#if BYTE_ORDER == BIG_ENDIAN - test >>= 8 * (JUDY_key_size - keysize); -#else - test &= JudyMask[keysize]; -#endif - if( test <= value ) - break; - } -#ifndef ASKITIS - judy->stack[judy->level].slot = slot; -#endif - if( test == value ) { - - // is this a leaf? - - if( !judy->depth && !(value & 0xFF) || judy->depth && depth == judy->depth ) - return &node[-slot-1]; - - next = node[-slot-1]; - continue; - } - - return NULL; - - case JUDY_radix: - table = (JudySlot *)(next & JUDY_mask); // outer radix - - if( judy->depth ) - slot = (src[depth] >> ((JUDY_key_size - off++ & JUDY_key_mask) * 8)) & 0xff; - else if( off < max ) - slot = buff[off++]; - else - slot = 0; -#ifndef ASKITIS - // put radix slot on judy stack - - judy->stack[judy->level].slot = slot; -#endif - if( (next = table[slot >> 4]) ) - table = (JudySlot *)(next & JUDY_mask); // inner radix - else - return NULL; - - if( judy->depth ) - if( !(off & JUDY_key_mask) ) - depth++; - - if( !judy->depth && !slot || judy->depth && depth == judy->depth ) // leaf? - if( table[slot & 0x0F] ) // occupied? - return &table[slot & 0x0F]; - else - return NULL; - - next = table[slot & 0x0F]; - continue; - -#ifndef ASKITIS - case JUDY_span: - node = (JudySlot *)((next & JUDY_mask) + JudySize[JUDY_span]); - base = (unsigned char *)(next & JUDY_mask); - cnt = tst = JUDY_span_bytes; - if( tst > (int)(max - off) ) - tst = max - off; - value = strncmp((const char *)base, (const char *)(buff + off), tst); - if( !value && tst < cnt && !base[tst] ) // leaf? - return &node[-1]; - - if( !value && tst == cnt ) { - next = node[-1]; - off += cnt; - continue; - } - return NULL; -#endif - } - } - - return NULL; -} - -// promote full nodes to next larger size - -JudySlot *judy_promote (Judy *judy, JudySlot *next, int idx, judyvalue value, int keysize) -{ -unsigned char *base = (unsigned char *)(*next & JUDY_mask); -int oldcnt, newcnt, slot; -#if BYTE_ORDER == BIG_ENDIAN - int i; -#endif -JudySlot *newnode, *node; -JudySlot *result; -unsigned char *newbase; -unsigned int type; - - type = (*next & 0x07) + 1; - node = (JudySlot *)((*next & JUDY_mask) + JudySize[type-1]); - oldcnt = JudySize[type-1] / (sizeof(JudySlot) + keysize); - newcnt = JudySize[type] / (sizeof(JudySlot) + keysize); - - // promote node to next larger size - - newbase = judy_alloc (judy, type); - newnode = (JudySlot *)(newbase + JudySize[type]); - *next = (JudySlot)newbase | type; - - // open up slot at idx - - memcpy(newbase + (newcnt - oldcnt - 1) * keysize, base, idx * keysize); // copy keys - - for( slot = 0; slot < idx; slot++ ) - newnode[-(slot + newcnt - oldcnt)] = node[-(slot + 1)]; // copy ptr - - // fill in new node - -#if BYTE_ORDER != BIG_ENDIAN - memcpy(newbase + (idx + newcnt - oldcnt - 1) * keysize, &value, keysize); // copy key -#else - i = keysize; - - while( i-- ) - newbase[(idx + newcnt - oldcnt - 1) * keysize + i] = value, value >>= 8; -#endif - result = &newnode[-(idx + newcnt - oldcnt)]; - - // copy rest of old node - - memcpy(newbase + (idx + newcnt - oldcnt) * keysize, base + (idx * keysize), (oldcnt - slot) * keysize); // copy keys - - for( ; slot < oldcnt; slot++ ) - newnode[-(slot + newcnt - oldcnt + 1)] = node[-(slot + 1)]; // copy ptr - -#ifndef ASKITIS - judy->stack[judy->level].next = *next; - judy->stack[judy->level].slot = idx + newcnt - oldcnt - 1; -#endif - judy_free (judy, (void **)base, type - 1); - return result; -} - -// construct new node for JUDY_radix entry -// make node with slot - start entries -// moving key over one offset - -void judy_radix (Judy *judy, JudySlot *radix, unsigned char *old, int start, int slot, int keysize, unsigned char key, unsigned int depth) -{ -int size, idx, cnt = slot - start, newcnt; -JudySlot *node, *oldnode; -unsigned int type = JUDY_1 - 1; -JudySlot *table; -unsigned char *base; - - // if necessary, setup inner radix node - - if( !(table = (JudySlot *)(radix[key >> 4] & JUDY_mask)) ) { - table = judy_alloc (judy, JUDY_radix); - radix[key >> 4] = (JudySlot)table | JUDY_radix; - } - - oldnode = (JudySlot *)(old + JudySize[JUDY_max]); - - // is this slot a leaf? - - if( !judy->depth && (!key || !keysize) || judy->depth && !keysize && depth == judy->depth) { - table[key & 0x0F] = oldnode[-start-1]; - return; - } - - // calculate new node big enough to contain slots - - do { - type++; - size = JudySize[type]; - newcnt = size / (sizeof(JudySlot) + keysize); - } while( cnt > newcnt && type < JUDY_max ); - - // store new node pointer in inner table - - base = judy_alloc (judy, type); - node = (JudySlot *)(base + size); - table[key & 0x0F] = (JudySlot)base | type; - - // allocate node and copy old contents - // shorten keys by 1 byte during copy - - for( idx = 0; idx < cnt; idx++ ) { -#if BYTE_ORDER != BIG_ENDIAN - memcpy (base + (newcnt - idx - 1) * keysize, old + (start + cnt - idx - 1) * (keysize + 1), keysize); -#else - memcpy (base + (newcnt - idx - 1) * keysize, old + (start + cnt - idx - 1) * (keysize + 1) + 1, keysize); -#endif - node[-(newcnt - idx)] = oldnode[-(start + cnt - idx)]; - } -} - -// decompose full node to radix nodes - -void judy_splitnode (Judy *judy, JudySlot *next, unsigned int size, unsigned int keysize, unsigned int depth) -{ -int cnt, slot, start = 0; -unsigned int key = 0x0100, nxt; -JudySlot *newradix; -unsigned char *base; - - base = (unsigned char *)(*next & JUDY_mask); - cnt = size / (sizeof(JudySlot) + keysize); - - // allocate outer judy_radix node - - newradix = judy_alloc (judy, JUDY_radix); - *next = (JudySlot)newradix | JUDY_radix; - - for( slot = 0; slot < cnt; slot++ ) { -#if BYTE_ORDER != BIG_ENDIAN - nxt = base[slot * keysize + keysize - 1]; -#else - nxt = base[slot * keysize]; -#endif - - if( key > 0xFF ) - key = nxt; - if( nxt == key ) - continue; - - // decompose portion of old node into radix nodes - - judy_radix (judy, newradix, base, start, slot, keysize - 1, (unsigned char)key, depth); - start = slot; - key = nxt; - } - - judy_radix (judy, newradix, base, start, slot, keysize - 1, (unsigned char)key, depth); - judy_free (judy, (void **)base, JUDY_max); -} - -// return first leaf - -JudySlot *judy_first (Judy *judy, JudySlot next, unsigned int off, unsigned int depth) -{ -JudySlot *table, *inner; -unsigned int keysize, size; -JudySlot *node; -int slot, cnt; -unsigned char *base; - - while( next ) { - if( judy->level < judy->max ) - judy->level++; - - judy->stack[judy->level].off = off; - judy->stack[judy->level].next = next; - size = JudySize[next & 0x07]; - - switch( next & 0x07 ) { - case JUDY_1: - case JUDY_2: - case JUDY_4: - case JUDY_8: - case JUDY_16: - case JUDY_32: -#ifdef ASKITIS - case JUDY_64: -#endif - keysize = JUDY_key_size - (off & JUDY_key_mask); - node = (JudySlot *)((next & JUDY_mask) + size); - base = (unsigned char *)(next & JUDY_mask); - cnt = size / (sizeof(JudySlot) + keysize); - - for( slot = 0; slot < cnt; slot++ ) - if( node[-slot-1] ) - break; - - judy->stack[judy->level].slot = slot; -#if BYTE_ORDER != BIG_ENDIAN - if( !judy->depth && !base[slot * keysize] || judy->depth && ++depth == judy->depth ) - return &node[-slot-1]; -#else - if( !judy->depth && !base[slot * keysize + keysize - 1] || judy->depth && ++depth == judy->depth ) - return &node[-slot-1]; -#endif - next = node[-slot - 1]; - off = (off | JUDY_key_mask) + 1; - continue; - case JUDY_radix: - off++; - - if( judy->depth ) - if( !(off & JUDY_key_mask) ) - depth++; - - table = (JudySlot *)(next & JUDY_mask); - for( slot = 0; slot < 256; slot++ ) - if( (inner = (JudySlot *)(table[slot >> 4] & JUDY_mask)) ) { - if( (next = inner[slot & 0x0F]) ) { - judy->stack[judy->level].slot = slot; - if( !judy->depth && !slot || judy->depth && depth == judy->depth ) - return &inner[slot & 0x0F]; - else - break; - } - } else - slot |= 0x0F; - continue; -#ifndef ASKITIS - case JUDY_span: - node = (JudySlot *)((next & JUDY_mask) + JudySize[JUDY_span]); - base = (unsigned char *)(next & JUDY_mask); - cnt = JUDY_span_bytes; - if( !base[cnt - 1] ) // leaf node? - return &node[-1]; - next = node[-1]; - off += cnt; - continue; -#endif - } - } - return NULL; -} - -// return last leaf cell pointer - -JudySlot *judy_last (Judy *judy, JudySlot next, unsigned int off, unsigned int depth) -{ -JudySlot *table, *inner; -unsigned int keysize, size; -JudySlot *node; -int slot, cnt; -unsigned char *base; - - while( next ) { - if( judy->level < judy->max ) - judy->level++; - - judy->stack[judy->level].next = next; - judy->stack[judy->level].off = off; - size = JudySize[next & 0x07]; - switch( next & 0x07 ) { - case JUDY_1: - case JUDY_2: - case JUDY_4: - case JUDY_8: - case JUDY_16: - case JUDY_32: -#ifdef ASKITIS - case JUDY_64: -#endif - keysize = JUDY_key_size - (off & JUDY_key_mask); - slot = size / (sizeof(JudySlot) + keysize); - base = (unsigned char *)(next & JUDY_mask); - node = (JudySlot *)((next & JUDY_mask) + size); - judy->stack[judy->level].slot = --slot; - -#if BYTE_ORDER != BIG_ENDIAN - if( !judy->depth && !base[slot * keysize] || judy->depth && ++depth == judy->depth ) -#else - if( !judy->depth && !base[slot * keysize + keysize - 1] || judy->depth && ++depth == judy->depth ) -#endif - return &node[-slot-1]; - - next = node[-slot-1]; - off += keysize; - continue; - - case JUDY_radix: - table = (JudySlot *)(next & JUDY_mask); - off++; - - if( judy->depth ) - if( !(off & JUDY_key_mask) ) - depth++; - - for( slot = 256; slot--; ) { - judy->stack[judy->level].slot = slot; - if( (inner = (JudySlot *)(table[slot >> 4] & JUDY_mask)) ) { - if( (next = inner[slot & 0x0F]) ) - if( !judy->depth && !slot || judy->depth && depth == judy->depth ) - return &inner[0]; - else - break; - } else - slot &= 0xF0; - } - continue; - -#ifndef ASKITIS - case JUDY_span: - node = (JudySlot *)((next & JUDY_mask) + JudySize[JUDY_span]); - base = (unsigned char *)(next & JUDY_mask); - cnt = JUDY_span_bytes; - if( !base[cnt - 1] ) // leaf node? - return &node[-1]; - next = node[-1]; - off += cnt; - continue; -#endif - } - } - return NULL; -} - -// judy_end: return last entry - -JudySlot *judy_end (Judy *judy) -{ - judy->level = 0; - return judy_last (judy, *judy->root, 0, 0); -} // judy_nxt: return next entry - -JudySlot *judy_nxt (Judy *judy) -{ -JudySlot *table, *inner; -int slot, size, cnt; -JudySlot *node; -JudySlot next; -unsigned int keysize; -unsigned char *base; -unsigned int depth; -unsigned int off; - - if( !judy->level ) - return judy_first (judy, *judy->root, 0, 0); - - while( judy->level ) { - next = judy->stack[judy->level].next; - slot = judy->stack[judy->level].slot; - off = judy->stack[judy->level].off; - keysize = JUDY_key_size - (off & JUDY_key_mask); - size = JudySize[next & 0x07]; - depth = off / JUDY_key_size; - - switch( next & 0x07 ) { - case JUDY_1: - case JUDY_2: - case JUDY_4: - case JUDY_8: - case JUDY_16: - case JUDY_32: -#ifdef ASKITIS - case JUDY_64: -#endif - cnt = size / (sizeof(JudySlot) + keysize); - node = (JudySlot *)((next & JUDY_mask) + size); - base = (unsigned char *)(next & JUDY_mask); - if( ++slot < cnt ) -#if BYTE_ORDER != BIG_ENDIAN - if( !judy->depth && !base[slot * keysize] || judy->depth && ++depth == judy->depth ) -#else - if( !judy->depth && !base[slot * keysize + keysize - 1] || judy->depth && ++depth == judy->depth ) -#endif - { - judy->stack[judy->level].slot = slot; - return &node[-slot - 1]; - } else { - judy->stack[judy->level].slot = slot; - return judy_first (judy, node[-slot-1], (off | JUDY_key_mask) + 1, depth); - } - judy->level--; - continue; - - case JUDY_radix: - table = (JudySlot *)(next & JUDY_mask); - - if( judy->depth ) - if( !((off+1) & JUDY_key_mask) ) - depth++; - - while( ++slot < 256 ) - if( (inner = (JudySlot *)(table[slot >> 4] & JUDY_mask)) ) { - if( inner[slot & 0x0F] ) { - judy->stack[judy->level].slot = slot; - if( !judy->depth || depth < judy->depth ) - return judy_first(judy, inner[slot & 0x0F], off + 1, depth); - return &inner[slot & 0x0F]; - } - } else - slot |= 0x0F; - - judy->level--; - continue; -#ifndef ASKITIS - case JUDY_span: - judy->level--; - continue; -#endif - } - } - return NULL; -} - -// judy_prv: return ptr to previous entry - -JudySlot *judy_prv (Judy *judy) -{ -int slot, size, keysize; -JudySlot *table, *inner; -JudySlot *node, next; -unsigned char *base; -unsigned int depth; -unsigned int off; - - if( !judy->level ) - return judy_last (judy, *judy->root, 0, 0); - - while( judy->level ) { - next = judy->stack[judy->level].next; - slot = judy->stack[judy->level].slot; - off = judy->stack[judy->level].off; - size = JudySize[next & 0x07]; - depth = off / JUDY_key_size; - - switch( next & 0x07 ) { - case JUDY_1: - case JUDY_2: - case JUDY_4: - case JUDY_8: - case JUDY_16: - case JUDY_32: -#ifdef ASKITIS - case JUDY_64: -#endif - node = (JudySlot *)((next & JUDY_mask) + size); - if( !slot || !node[-slot] ) { - judy->level--; - continue; - } - - base = (unsigned char *)(next & JUDY_mask); - judy->stack[judy->level].slot--; - keysize = JUDY_key_size - (off & JUDY_key_mask); - -#if BYTE_ORDER != BIG_ENDIAN - if( !judy->depth && !base[(slot - 1) * keysize] || judy->depth && ++depth == judy->depth ) -#else - if( !judy->depth && !base[(slot - 1) * keysize + keysize - 1] || judy->depth && ++depth == judy->depth ) -#endif - return &node[-slot]; - return judy_last (judy, node[-slot], (off | JUDY_key_mask) + 1, depth); - - case JUDY_radix: - table = (JudySlot *)(next & JUDY_mask); - - if( judy->depth ) - if( !((off + 1) & JUDY_key_mask) ) - depth++; - - while( slot-- ) { - judy->stack[judy->level].slot--; - if( (inner = (JudySlot *)(table[slot >> 4] & JUDY_mask)) ) - if( inner[slot & 0x0F] ) - if( !judy->depth && !slot || judy->depth && depth == judy->depth ) - return &inner[0]; - else - return judy_last(judy, inner[slot & 0x0F], off + 1, depth); - } - - judy->level--; - continue; - -#ifndef ASKITIS - case JUDY_span: - judy->level--; - continue; -#endif - } - } - return NULL; -} - -// judy_del: delete string from judy array -// returning previous entry. - -JudySlot *judy_del (Judy *judy) -{ -int slot, off, size, type, high; -JudySlot *table, *inner; -JudySlot next, *node; -int keysize, cnt; -unsigned char *base; - - while( judy->level ) { - next = judy->stack[judy->level].next; - slot = judy->stack[judy->level].slot; - off = judy->stack[judy->level].off; - size = JudySize[next & 0x07]; - - switch( type = next & 0x07 ) { - case JUDY_1: - case JUDY_2: - case JUDY_4: - case JUDY_8: - case JUDY_16: - case JUDY_32: -#ifdef ASKITIS - case JUDY_64: -#endif - keysize = JUDY_key_size - (off & JUDY_key_mask); - cnt = size / (sizeof(JudySlot) + keysize); - node = (JudySlot *)((next & JUDY_mask) + size); - base = (unsigned char *)(next & JUDY_mask); - - // move deleted slot to first slot - - while( slot ) { - node[-slot-1] = node[-slot]; - memcpy (base + slot * keysize, base + (slot - 1) * keysize, keysize); - slot--; - } - - // zero out first slot - - node[-1] = 0; - memset (base, 0, keysize); - - if( node[-cnt] ) { // does node have any slots left? - judy->stack[judy->level].slot++; - return judy_prv (judy); - } - - judy_free (judy, base, type); - judy->level--; - continue; - - case JUDY_radix: - table = (JudySlot *)(next & JUDY_mask); - inner = (JudySlot *)(table[slot >> 4] & JUDY_mask); - inner[slot & 0x0F] = 0; - high = slot & 0xF0; - - for( cnt = 16; cnt--; ) - if( inner[cnt] ) - return judy_prv (judy); - - judy_free (judy, inner, JUDY_radix); - table[slot >> 4] = 0; - - for( cnt = 16; cnt--; ) - if( table[cnt] ) - return judy_prv (judy); - - judy_free (judy, table, JUDY_radix); - judy->level--; - continue; - -#ifndef ASKITIS - case JUDY_span: - base = (unsigned char *)(next & JUDY_mask); - judy_free (judy, base, type); - judy->level--; - continue; -#endif - } - } - - // tree is now empty - - *judy->root = 0; - return NULL; -} - -// return cell for first key greater than or equal to given key - -JudySlot *judy_strt (Judy *judy, unsigned char *buff, unsigned int max) -{ -JudySlot *cell; - - judy->level = 0; - - if( !max ) - return judy_first (judy, *judy->root, 0, 0); - - if( (cell = judy_slot (judy, buff, max)) ) - return cell; - - return judy_nxt (judy); -} - -// split open span node - -#ifndef ASKITIS -void judy_splitspan (Judy *judy, JudySlot *next, unsigned char *base) -{ -JudySlot *node = (JudySlot *)(base + JudySize[JUDY_span]); -unsigned int cnt = JUDY_span_bytes; -unsigned char *newbase; -unsigned int off = 0; -#if BYTE_ORDER != BIG_ENDIAN -int i; -#endif - - do { - newbase = judy_alloc (judy, JUDY_1); - *next = (JudySlot)newbase | JUDY_1; - -#if BYTE_ORDER != BIG_ENDIAN - i = JUDY_key_size; - while( i-- ) - *newbase++ = base[off + i]; -#else - memcpy (newbase, base + off, JUDY_key_size); - newbase += JUDY_key_size; -#endif - next = (JudySlot *)newbase; - - off += JUDY_key_size; - cnt -= JUDY_key_size; - } while( cnt && base[off - 1] ); - - *next = node[-1]; - judy_free (judy, base, JUDY_span); -} -#endif - -// judy_cell: add string to judy array - -JudySlot *judy_cell (Judy *judy, unsigned char *buff, unsigned int max) -{ -judyvalue *src = (judyvalue *)buff; -int size, idx, slot, cnt, tst; -JudySlot *next = judy->root; -judyvalue test, value; -unsigned int off = 0, start; -JudySlot *table; -JudySlot *node; -unsigned int depth = 0; -unsigned int keysize; -unsigned char *base; - - judy->level = 0; -#ifdef ASKITIS - Words++; -#endif - - while( *next ) { -#ifndef ASKITIS - if( judy->level < judy->max ) - judy->level++; - - judy->stack[judy->level].next = *next; - judy->stack[judy->level].off = off; -#endif - switch( *next & 0x07 ) { - default: - size = JudySize[*next & 0x07]; - keysize = JUDY_key_size - (off & JUDY_key_mask); - cnt = size / (sizeof(JudySlot) + keysize); - base = (unsigned char *)(*next & JUDY_mask); - node = (JudySlot *)((*next & JUDY_mask) + size); - start = off; - slot = cnt; - value = 0; - - if( judy->depth ) { - value = src[depth++]; - off |= JUDY_key_mask; - off++; - value &= JudyMask[keysize]; - } else - do { - value <<= 8; - if( off < max ) - value |= buff[off]; - } while( ++off & JUDY_key_mask ); - - // find slot > key - - while( slot-- ) { - test = *(judyvalue *)(base + slot * keysize); -#if BYTE_ORDER == BIG_ENDIAN - test >>= 8 * (JUDY_key_size - keysize); -#else - test &= JudyMask[keysize]; -#endif - if( test <= value ) - break; - } -#ifndef ASKITIS - judy->stack[judy->level].slot = slot; -#endif - if( test == value ) { // new key is equal to slot key - next = &node[-slot-1]; - - // is this a leaf? - - if( !judy->depth && !(value & 0xFF) || judy->depth && depth == judy->depth ) { -#ifdef ASKITIS - if( *next ) - Found++; - else - Inserts++; -#endif - return next; - } - - continue; - } - - // if this node is not full - // open up cell after slot - - if( !node[-1] ) { - memmove(base, base + keysize, slot * keysize); // move keys less than new key down one slot -#if BYTE_ORDER != BIG_ENDIAN - memcpy(base + slot * keysize, &value, keysize); // copy new key into slot -#else - test = value; - idx = keysize; - - while( idx-- ) - base[slot * keysize + idx] = test, test >>= 8; -#endif - for( idx = 0; idx < slot; idx++ ) - node[-idx-1] = node[-idx-2];// copy tree ptrs/cells down one slot - - node[-slot-1] = 0; // set new tree ptr/cell - next = &node[-slot-1]; - - if( !judy->depth && !(value & 0xFF) || judy->depth && depth == judy->depth ) { -#ifdef ASKITIS - if( *next ) - Found++; - else - Inserts++; -#endif - return next; - } - - continue; - } - - if( size < JudySize[JUDY_max] ) { - next = judy_promote (judy, next, slot+1, value, keysize); - - if( !judy->depth && !(value & 0xFF) || judy->depth && depth == judy->depth ) { -#ifdef ASKITIS - if( *next ) - Found++; - else - Inserts++; -#endif - return next; - } - - continue; - } - - // split full maximal node into JUDY_radix nodes - // loop to reprocess new insert - - judy_splitnode (judy, next, size, keysize, depth); -#ifndef ASKITIS - judy->level--; -#endif - off = start; - if( judy->depth ) - depth--; - continue; - - case JUDY_radix: - table = (JudySlot *)(*next & JUDY_mask); // outer radix - - if( judy->depth ) - slot = (src[depth] >> ((JUDY_key_size - ++off & JUDY_key_mask) * 8)) & 0xff; - else if( off < max ) - slot = buff[off++]; - else - slot = 0, off++; - - if( judy->depth ) - if( !(off & JUDY_key_mask) ) - depth++; - - // allocate inner radix if empty - - if( !table[slot >> 4] ) - table[slot >> 4] = (JudySlot)judy_alloc (judy, JUDY_radix) | JUDY_radix; - - table = (JudySlot *)(table[slot >> 4] & JUDY_mask); -#ifndef ASKITIS - judy->stack[judy->level].slot = slot; -#endif - next = &table[slot & 0x0F]; - - if( !judy->depth && !slot || judy->depth && depth == judy->depth ) { // leaf? -#ifdef ASKITIS - if( *next ) - Found++; - else - Inserts++; -#endif - return next; - } - - continue; - -#ifndef ASKITIS - case JUDY_span: - base = (unsigned char *)(*next & JUDY_mask); - node = (JudySlot *)((*next & JUDY_mask) + JudySize[JUDY_span]); - cnt = JUDY_span_bytes; - tst = cnt; - - if( tst > (int)(max - off) ) - tst = max - off; - - value = strncmp((const char *)base, (const char *)(buff + off), tst); - - if( !value && tst < cnt && !base[tst] ) // leaf? - return &node[-1]; - - if( !value && tst == cnt ) { - next = &node[-1]; - off += cnt; - continue; - } - - // bust up JUDY_span node and produce JUDY_1 nodes - // then loop to reprocess insert - - judy_splitspan (judy, next, base); - judy->level--; - continue; -#endif - } - } - - // place JUDY_1 node under JUDY_radix node(s) - -#ifndef ASKITIS - if( off & JUDY_key_mask ) - if( judy->depth || off <= max ) { -#else - while( off <= max ) { -#endif - base = judy_alloc (judy, JUDY_1); - keysize = JUDY_key_size - (off & JUDY_key_mask); - node = (JudySlot *)(base + JudySize[JUDY_1]); - *next = (JudySlot)base | JUDY_1; - - // fill in slot 0 with bytes of key - - if( judy->depth ) { - value = src[depth]; -#if BYTE_ORDER != BIG_ENDIAN - memcpy(base, &value, keysize); // copy new key into slot -#else - while( keysize-- ) - base[keysize] = value, value >>= 8; -#endif - } else { -#if BYTE_ORDER != BIG_ENDIAN - while( keysize ) - if( off + keysize <= max ) - *base++ = buff[off + --keysize]; - else - base++, --keysize; -#else - tst = keysize; - - if( tst > (int)(max - off) ) - tst = max - off; - - memcpy (base, buff + off, tst); -#endif - } -#ifndef ASKITIS - if( judy->level < judy->max ) - judy->level++; - judy->stack[judy->level].next = *next; - judy->stack[judy->level].slot = 0; - judy->stack[judy->level].off = off; -#endif - next = &node[-1]; - - off |= JUDY_key_mask; - depth++; - off++; - } - - // produce span nodes to consume rest of key - // or judy_1 nodes if not string tree - -#ifndef ASKITIS - if( !judy->depth ) - while( off <= max ) { - base = judy_alloc (judy, JUDY_span); - *next = (JudySlot)base | JUDY_span; - node = (JudySlot *)(base + JudySize[JUDY_span]); - cnt = tst = JUDY_span_bytes; - if( tst > (int)(max - off) ) - tst = max - off; - memcpy (base, buff + off, tst); - - if( judy->level < judy->max ) - judy->level++; - judy->stack[judy->level].next = *next; - judy->stack[judy->level].slot = 0; - judy->stack[judy->level].off = off; - next = &node[-1]; - off += tst; - depth++; - - if( !base[cnt-1] ) // done on leaf - break; - } - else - while( depth < judy->depth ) { - base = judy_alloc (judy, JUDY_1); - node = (JudySlot *)(base + JudySize[JUDY_1]); - *next = (JudySlot)base | JUDY_1; - - // fill in slot 0 with bytes of key - - *(judyvalue *)base = src[depth]; - - if( judy->level < judy->max ) - judy->level++; - judy->stack[judy->level].next = *next; - judy->stack[judy->level].slot = 0; - judy->stack[judy->level].off = off; - next = &node[-1]; - off |= JUDY_key_mask; - depth++; - off++; - } -#endif - -#ifdef ASKITIS - Inserts++; -#endif - return next; -} - -#if defined(STANDALONE) || defined(ASKITIS) - -#if defined(__APPLE__) || defined(linux) -#include -#include -#include -#include -#include -#else -#include -#include -#endif - -#include - -// memory map input file and sort - -// define pennysort parameters - -unsigned int PennyRecs = (4096 * 400); // records to sort to temp files -unsigned int PennyLine = 100; // length of input record -unsigned int PennyKey = 10; // length of input key -unsigned int PennyOff = 0; // key offset in input record - -unsigned long long PennyMerge; // PennyRecs * PennyLine = file map length -unsigned int PennyPasses; // number of intermediate files created -unsigned int PennySortTime; // cpu time to run sort -unsigned int PennyMergeTime; // cpu time to run merge - -typedef struct { - void *buff; // record pointer in input file map - void *next; // duplicate chain -} PennySort; - -void sort (FILE *infile, char *outname) -{ -unsigned long long size, off, offset, part; -int ifd = fileno (infile); -char filename[512]; -PennySort *line; -JudySlot *cell; -unsigned char *inbuff; -void *judy; -FILE *out; -#if defined(_WIN32) -HANDLE hndl, fm; -DWORD hiword; -FILETIME dummy[1]; -FILETIME user[1]; -#else -struct tms buff[1]; -#endif -time_t start = time(NULL); - - if( PennyOff + PennyKey > PennyLine ) - fprintf (stderr, "Key Offset + Key Length > Record Length\n"), exit(1); - - offset = 0; - PennyPasses = 0; - -#if defined(_WIN32) - hndl = (HANDLE)_get_osfhandle(ifd); - size = GetFileSize (hndl, &hiword); - fm = CreateFileMapping(hndl, NULL, PAGE_READONLY, hiword, (DWORD)size, NULL); - if( !fm ) - fprintf (stderr, "CreateFileMapping error %d\n", GetLastError()), exit(1); - size |= (unsigned long long)hiword << 32; -#else - size = lseek (ifd, 0L, 2); -#endif - - while( offset < size ) { -#if defined(_WIN32) - part = offset + PennyMerge > size ? size - offset : PennyMerge; - inbuff = MapViewOfFile( fm, FILE_MAP_READ, offset >> 32, offset, part); - if( !inbuff ) - fprintf (stderr, "MapViewOfFile error %d\n", GetLastError()), exit(1); -#else - inbuff = mmap (NULL, PennyMerge, PROT_READ, MAP_SHARED, ifd, offset); - - if( inbuff == MAP_FAILED ) - fprintf (stderr, "mmap error %d\n", errno), exit(1); - - if( madvise (inbuff, PennyMerge, MADV_WILLNEED | MADV_SEQUENTIAL) < 0 ) - fprintf (stderr, "madvise error %d\n", errno); -#endif - judy = judy_open (PennyKey, 0); - - off = 0; - - // build judy array from mapped input chunk - - while( offset + off < size && off < PennyMerge ) { - line = judy_data (judy, sizeof(PennySort)); - cell = judy_cell (judy, inbuff + off + PennyOff, PennyKey); - line->next = *(void **)cell; - line->buff = inbuff + off; - - *(PennySort **)cell = line; - off += PennyLine; - } - - sprintf (filename, "%s.%d", outname, PennyPasses); - out = fopen (filename, "wb"); - setvbuf (out, NULL, _IOFBF, 4096 * 1024); - -#ifndef _WIN32 - if( madvise (inbuff, PennyMerge, MADV_WILLNEED | MADV_RANDOM) < 0 ) - fprintf (stderr, "madvise error %d\n", errno); -#endif - - // write judy array in sorted order to temporary file - - cell = judy_strt (judy, NULL, 0); - - if( cell ) do { - line = *(PennySort **)cell; - do fwrite (line->buff, PennyLine, 1, out); - while( line = line->next ); - } while( cell = judy_nxt (judy) ); - -#if defined(_WIN32) - UnmapViewOfFile (inbuff); -#else - munmap (inbuff, PennyMerge); -#endif - judy_close (judy); - offset += off; - fflush (out); - fclose (out); - PennyPasses++; - } - fprintf (stderr, "End Sort %d secs", time(NULL) - start); -#if defined(_WIN32) - CloseHandle (fm); - GetProcessTimes (GetCurrentProcess(), dummy, dummy, dummy, user); - PennySortTime = *(unsigned long long*)user / 10000000; -#else - times (buff); - PennySortTime = buff->tms_utime/100; -#endif - fprintf (stderr, " Cpu %d\n", PennySortTime); -} - -int merge (FILE *out, char *outname) -{ -time_t start = time(NULL); -char filename[512]; -JudySlot *cell; -unsigned int nxt, idx; -unsigned char **line; -unsigned int *next; -void *judy; -FILE **in; - - next = calloc (PennyPasses + 1, sizeof(unsigned int)); - line = calloc (PennyPasses, sizeof(void *)); - in = calloc (PennyPasses, sizeof(void *)); - - judy = judy_open (PennyKey, 0); - - // initialize merge with one record from each temp file - - for( idx = 0; idx < PennyPasses; idx++ ) { - sprintf (filename, "%s.%d", outname, idx); - in[idx] = fopen (filename, "rb"); - line[idx] = malloc (PennyLine); - setvbuf (in[idx], NULL, _IOFBF, 4096 * 1024); - fread (line[idx], PennyLine, 1, in[idx]); - cell = judy_cell (judy, line[idx] + PennyOff, PennyKey); - next[idx + 1] = *(unsigned int *)cell; - *cell = idx + 1; - } - - // output records, replacing smallest each time - - while( cell = judy_strt (judy, NULL, 0) ) { - nxt = *(unsigned int *)cell; - judy_del (judy); - - // process duplicates - - while( idx = nxt ) { - nxt = next[idx--]; - fwrite (line[idx], PennyLine, 1, out); - - if( fread (line[idx], PennyLine, 1, in[idx]) ) { - cell = judy_cell (judy, line[idx] + PennyOff, PennyKey); - next[idx + 1] = *(unsigned int *)cell; - *cell = idx + 1; - } else - next[idx + 1] = 0; - } - } - - for( idx = 0; idx < PennyPasses; idx++ ) { - fclose (in[idx]); - free (line[idx]); - } - - free (line); - free (next); - free (in); - - fprintf (stderr, "End Merge %d secs", time(NULL) - start); -#ifdef _WIN32 - { - FILETIME dummy[1]; - FILETIME user[1]; - GetProcessTimes (GetCurrentProcess(), dummy, dummy, dummy, user); - PennyMergeTime = *(unsigned long long*)user / 10000000; - } -#else - { - struct tms buff[1]; - times (buff); - PennyMergeTime = buff->tms_utime/100; - } -#endif - fprintf (stderr, " Cpu %d\n", PennyMergeTime - PennySortTime); - judy_close (judy); - fflush (out); - fclose (out); - return 0; -} - -// compilation: -// cc -O3 judy64j.c - -// usage: -// a.out [in-file] [out-file] [keysize] [recordlen] [keyoffset] [mergerecs] -// where keysize is 10 to indicate pennysort files - -#if !defined(_WIN32) -typedef struct timeval timer; -#endif - -// ASKITIS compilation: -// cc -O3 judy64n.c - -// usage: -// a.out [in-file] [out-file] [keysize] [recordlen] [keyoffset] [mergerecs] -// where keysize is 10 to indicate pennysort files - -// naskitis.com. -// g++ -O3 -fpermissive -fomit-frame-pointer -w -D STANDALONE -D ASKITIS -o judy64n judy64n.c -// ./judy64n [input-file-to-build-judy] e.g. distinct_1 or skew1_1 - -// note: the judy array is an in-memory data structure. As such, make sure you -// have enough memory to hold the entire input file + data structure, otherwise -// you'll have to break the input file into smaller pieces and load them in -// on-by-one. - -// Also, the file to search judy is hardcoded to skew1_1. - -int main (int argc, char **argv) -{ -unsigned char buff[1024]; -JudySlot max = 0; -JudySlot *cell; -FILE *in, *out; -void *judy; -unsigned int len; -unsigned int idx; -#ifdef ASKITIS -char *askitis; -int prev, off; -float insert_real_time=0.0; -float search_real_time=0.0; -int size; -#if !defined(_WIN32) -timer start, stop; -#else -time_t start[1], stop[1]; -#endif -#endif - - if( argc > 1 ) - in = fopen (argv[1], "rb"); - else - in = stdin; - - if( argc > 2 ) - out = fopen (argv[2], "wb"); - else - out = stdout; - - setvbuf (out, NULL, _IOFBF, 4096 * 1024); - - if( !in ) - fprintf (stderr, "unable to open input file\n"); - - if( !out ) - fprintf (stderr, "unable to open output file\n"); - - if( argc > 6 ) - PennyRecs = atoi(argv[6]); - - if( argc > 5 ) - PennyOff = atoi(argv[5]); - - if( argc > 4 ) - PennyLine = atoi(argv[4]); - - PennyMerge = (unsigned long long)PennyLine * PennyRecs; - - if( argc > 3 ) { - PennyKey = atoi(argv[3]); - sort (in, argv[2]); - return merge (out, argv[2]); - } - -#ifdef ASKITIS - judy = judy_open (1024, 0); - -// build judy array - size = lseek (fileno(in), 0L, 2); - askitis = malloc(size); - lseek (fileno(in), 0L, 0); - read (fileno(in), askitis,size); - prev = 0; -// naskitis.com: -// Start the timer. - -#if !defined(_WIN32) - gettimeofday(&start, NULL); -#else - time(start); -#endif - - for( off = 0; off < size; off++ ) - if( askitis[off] == '\n' ) { - *(judy_cell (judy, askitis+prev, off - prev)) += 1; // count instances of string - prev = off + 1; - } -// naskitis.com: -// Stop the timer and do some math to compute the time required to insert the strings into the judy array. - -#if !defined(_WIN32) - gettimeofday(&stop, NULL); - - insert_real_time = 1000.0 * ( stop.tv_sec - start.tv_sec ) + 0.001 * (stop.tv_usec - start.tv_usec ); - insert_real_time = insert_real_time/1000.0; -#else - time (stop); - insert_real_time = *stop - *start; -#endif - -// naskitis.com: -// Free the input buffer used to store the first file. We must do this before we get the process size below. - free (askitis); - fprintf(stderr, "JudyArray@Karl_Malbrain\nDASKITIS option enabled\n-------------------------------\n%-20s %.2f MB\n%-20s %.2f sec\n", - "Judy Array size:", MaxMem/1000000., "Time to insert:", insert_real_time); - fprintf(stderr, "%-20s %d\n", "Words:", Words); - fprintf(stderr, "%-20s %d\n", "Inserts:", Inserts); - fprintf(stderr, "%-20s %d\n", "Found:", Found); - - Words = 0; - Inserts = 0; - Found = 0; - -// search judy array - if( in = freopen ("skew1_1", "rb", in) ) - size = lseek (fileno(in), 0L, 2); - else - exit(0); - askitis = malloc(size); - lseek (fileno(in), 0L, 0); - read (fileno(in), askitis,size); - prev = 0; - -#if !defined(_WIN32) - gettimeofday(&start, NULL); -#else - time(start); -#endif - - for( off = 0; off < size; off++ ) - if( askitis[off] == '\n' ) { - *judy_cell (judy, askitis+prev, off - prev) += 1; - prev = off + 1; - } -// naskitis.com: -// Stop the timer and do some math to compute the time required to search the judy array. - -#if !defined(_WIN32) - gettimeofday(&stop, NULL); - search_real_time = 1000.0 * ( stop.tv_sec - start.tv_sec ) + 0.001 - * (stop.tv_usec - start.tv_usec ); - search_real_time = search_real_time/1000.0; -#else - time(stop); - search_real_time = *stop - *start; -#endif - -// naskitis.com: -// To do: report a count on the number of strings found. - - fprintf(stderr,"\n%-20s %.2f MB\n%-20s %.2f sec\n", - "Judy Array size:", MaxMem/1000000., "Time to search:", search_real_time); - fprintf(stderr, "%-20s %d\n", "Words:", Words); - fprintf(stderr, "%-20s %d\n", "Inserts:", Inserts); - fprintf(stderr, "%-20s %d\n", "Found:", Found); - exit(0); -#endif -#ifdef HEXKEYS - judy = judy_open (1024, 16/JUDY_key_size); - - while( fgets((char *)buff, sizeof(buff), in) ) { - judyvalue key[16/JUDY_key_size]; - if( len = strlen((const char *)buff) ) - buff[--len] = 0; // remove LF -#if JUDY_key_size == 4 - key[3] = strtoul (buff + 24, NULL, 16); - buff[24] = 0; - key[2] = strtoul (buff + 16, NULL, 16); - buff[16] = 0; - key[1] = strtoul (buff + 8, NULL, 16); - buff[8] = 0; - key[0] = strtoul (buff, NULL, 16); -#else - key[1] = strtoull (buff + 16, NULL, 16); - buff[16] = 0; - key[0] = strtoull (buff, NULL, 16); -#endif - *(judy_cell (judy, (void *)key, 0)) += 1; // count instances of string - max++; - } - - fprintf(stderr, "%" PRIuint " memory used\n", MaxMem); - - cell = judy_strt (judy, NULL, 0); - - if( cell ) do { - judyvalue key[16/JUDY_key_size]; - len = judy_key(judy, (void *)key, 0); - for( idx = 0; idx < *cell; idx++ ){ // spit out duplicates -#if JUDY_key_size == 4 - fprintf (out, "%.8X", key[0]); - fprintf (out, "%.8X", key[1]); - fprintf (out, "%.8X", key[2]); - fprintf (out, "%.8X", key[3]); -#else - fprintf (out, "%.16llX", key[0]); - fprintf (out, "%.16llX", key[1]); -#endif - fputc('\n', out); - } - } while( cell = judy_nxt (judy) ); - -#else - judy = judy_open (1024, 0); - - while( fgets((char *)buff, sizeof(buff), in) ) { - if( len = strlen((const char *)buff) ) - buff[--len] = 0; // remove LF - *(judy_cell (judy, buff, len)) += 1; // count instances of string - max++; - } - - fprintf(stderr, "%" PRIuint " memory used\n", MaxMem); - - cell = judy_strt (judy, NULL, 0); - - if( cell ) do { - len = judy_key(judy, buff, sizeof(buff)); - for( idx = 0; idx < *cell; idx++ ){ // spit out duplicates - fwrite(buff, len, 1, out); - fputc('\n', out); - } - } while( cell = judy_nxt (judy) ); -#endif -#if 0 - // test deletion all the way to an empty tree - - if( cell = judy_prv (judy) ) - do max -= *cell; - while( cell = judy_del (judy) ); - - assert (max == 0); -#endif - judy_close(judy); - return 0; -} -#endif - diff --git a/src/base/judy/test/hexSort.c b/src/base/judy/test/hexSort.c deleted file mode 100644 index 0d770d752..000000000 --- a/src/base/judy/test/hexSort.c +++ /dev/null @@ -1,124 +0,0 @@ -// Judy arrays 13 DEC 2012 (judy64n.c from http://code.google.com/p/judyarray/ ) -// This code is public domain. - -// Author Karl Malbrain, malbrain AT yahoo.com -// with assistance from Jan Weiss. -// modifications (and any bugs) by Mark Pictor, mpictor at gmail - -// Simplified judy arrays for strings and integers -// Adapted from the ideas of Douglas Baskins of HP. - -// Map a set of keys to corresponding memory cells (uints). -// Each cell must be set to a non-zero value by the caller. - - -// Integer mappings are denoted by calling judy_open with the -// Integer depth of the Judy Trie as the second argument. - -#ifndef STANDALONE -# error must define STANDALONE while compiling this file and judy64.c -#endif - -#include "judy.h" -#include "sort.h" - -unsigned int MaxMem = 0; -/** - usage: - a.out [in-file] [out-file] - where all lines of in-file are 32 chars, hexadecimal - On linux, a 1M-line file can be created with the following: - hexdump -v -e '2/8 "%08x"' -e '"\n"' /dev/urandom |head -n 1000000 >in-file -*/ -int main( int argc, char ** argv ) { - unsigned char buff[1024]; - JudySlot max = 0; - JudySlot * cell; - FILE * in, *out; - void * judy; - unsigned int len; - unsigned int idx; - - if( argc > 1 ) { - in = fopen( argv[1], "rb" ); - } else { - in = stdin; - } - - if( argc > 2 ) { - out = fopen( argv[2], "wb" ); - } else { - out = stdout; - } - - setvbuf( out, NULL, _IOFBF, 4096 * 1024 ); - - if( !in ) { - fprintf( stderr, "unable to open input file\n" ); - } - - if( !out ) { - fprintf( stderr, "unable to open output file\n" ); - } - - PennyMerge = ( unsigned long long )PennyLine * PennyRecs; - - judy = judy_open( 1024, 16 / JUDY_key_size ); - - while( fgets( ( char * )buff, sizeof( buff ), in ) ) { - judyvalue key[16 / JUDY_key_size]; - if( len = strlen( ( const char * )buff ) ) { - buff[--len] = 0; // remove LF - } -#if JUDY_key_size == 4 - key[3] = strtoul( buff + 24, NULL, 16 ); - buff[24] = 0; - key[2] = strtoul( buff + 16, NULL, 16 ); - buff[16] = 0; - key[1] = strtoul( buff + 8, NULL, 16 ); - buff[8] = 0; - key[0] = strtoul( buff, NULL, 16 ); -#else - key[1] = strtoull( buff + 16, NULL, 16 ); - buff[16] = 0; - key[0] = strtoull( buff, NULL, 16 ); -#endif - *( judy_cell( judy, ( void * )key, 0 ) ) += 1; // count instances of string - max++; - } - - fprintf( stderr, "%" PRIuint " memory used\n", MaxMem ); - - cell = judy_strt( judy, NULL, 0 ); - - if( cell ) do { - judyvalue key[16 / JUDY_key_size]; - len = judy_key( judy, ( void * )key, 0 ); - for( idx = 0; idx < *cell; idx++ ) { // spit out duplicates -#if JUDY_key_size == 4 - fprintf( out, "%.8X", key[0] ); - fprintf( out, "%.8X", key[1] ); - fprintf( out, "%.8X", key[2] ); - fprintf( out, "%.8X", key[3] ); -#else - fprintf( out, "%.16llX", key[0] ); - fprintf( out, "%.16llX", key[1] ); -#endif - fputc( '\n', out ); - } - } while( cell = judy_nxt( judy ) ); - -#if 0 - // test deletion all the way to an empty tree - - if( cell = judy_prv( judy ) ) - do { - max -= *cell; - } while( cell = judy_del( judy ) ); - - assert( max == 0 ); -#endif - judy_close( judy ); - return 0; -} - diff --git a/src/base/judy/test/judyL2test.cc b/src/base/judy/test/judyL2test.cc deleted file mode 100644 index 20ef559a9..000000000 --- a/src/base/judy/test/judyL2test.cc +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include - -#include "judyL2Array.h" -typedef judyL2Array< uint64_t, uint64_t > jl2a; - -bool testFind( jl2a & j, uint64_t key, unsigned int count ) { - jl2a::cvector * v = j.find( key ); - std::cout << "find: key " << key << " ..." << std::endl; - if( count > 0 ) { - if( !v || !j.success() || ( v->size() != count ) ) { - std::cout << " false negative - v: " << v << " success: " << j.success(); - if( v ) { - std::cout << " expected count: " << count << " actual: " << v->size(); - } - std::cout << std::endl; - return false; - } else { - // note - this doesn't verify that the right keys are returned, just the right number! - jl2a::vector::const_iterator it = v->begin(); - std::cout << " correct number of values -"; - for( ; it != v->end(); it++ ) { - std::cout << " " << *it; - } - std::cout << std::endl; - } - } else { - if( v || j.success() ) { - std::cout << " false positive - v: " << v << " success: " << j.success() << std::endl; - return false; - } else { - std::cout << " not found, as expected." << std::endl; - } - } - return true; -} - -int main() { - bool pass = true; - jl2a jl; - std::cout.setf( std::ios::boolalpha ); -// std::cout << "size of judyL2Array: " << sizeof( jl ) << std::endl; - jl.insert( 5, 12 ); - jl.insert( 6, 2 ); - jl.insert( 7, 312 ); - jl.insert( 11, 412 ); - jl.insert( 7, 313 ); - jl2a::cpair kv = jl.atOrAfter( 4 ); - std::cout << "atOrAfter test ..." << std::endl; - if( kv.value != 0 && jl.success() ) { - std::cout << " key " << kv.key << " value " << kv.value->at( 0 ) << std::endl; - } else { - std::cout << " failed" << std::endl; - pass = false; - } - - pass &= testFind( jl, 8, 0 ); - pass &= testFind( jl, 11, 1 ); - pass &= testFind( jl, 7, 2 ); - - jl.clear(); - - //TODO test all of judyL2Array - if( pass ) { - std::cout << "All tests passed." << std::endl; - exit( EXIT_SUCCESS ); - } else { - std::cout << "At least one test failed." << std::endl; - exit( EXIT_FAILURE ); - } -} \ No newline at end of file diff --git a/src/base/judy/test/judyLtest.cc b/src/base/judy/test/judyLtest.cc deleted file mode 100644 index 01ae3d5d7..000000000 --- a/src/base/judy/test/judyLtest.cc +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include - -#include "judyLArray.h" - -int main() { - std::cout.setf( std::ios::boolalpha ); - judyLArray< uint64_t, uint64_t > jl; - std::cout << "size of judyLArray: " << sizeof( jl ) << std::endl; - jl.insert( 5, 12 ); - jl.insert( 6, 2 ); - jl.insert( 7, 312 ); - jl.insert( 8, 412 ); - judyLArray< uint64_t, uint64_t >::pair kv = jl.atOrAfter( 4 ); - std::cout << "k " << kv.key << " v " << kv.value << std::endl; - - long v = jl.find( 11 ); - if( v != 0 || jl.success() ) { - std::cout << "find: false positive - v: " << v << " success: " << jl.success() << std::endl; - exit( EXIT_FAILURE ); - } - v = jl.find( 7 ); - if( v != 312 || !jl.success() ) { - std::cout << "find: false negative - v: " << v << " success: " << jl.success() << std::endl; - exit( EXIT_FAILURE ); - } - - jl.clear(); - - //TODO test all of judyLArray - exit( EXIT_SUCCESS ); -} \ No newline at end of file diff --git a/src/base/judy/test/judyS2test.cc b/src/base/judy/test/judyS2test.cc deleted file mode 100644 index ec25f960b..000000000 --- a/src/base/judy/test/judyS2test.cc +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include - -#include "judyS2Array.h" - -typedef judyS2Array< uint64_t > js2a; - -bool testFind( js2a & j, const char * key, unsigned int count ) { - js2a::cvector * v = j.find( key ); - std::cout << "find: key " << key << " ..." << std::endl; - if( count > 0 ) { - if( !v || !j.success() || ( v->size() != count ) ) { - std::cout << " false negative - v: " << v << " success: " << j.success(); - if( v ) { - std::cout << " expected count: " << count << " actual: " << v->size(); - } - std::cout << std::endl; - return false; - } else { - // note - this doesn't verify that the right keys are returned, just the right number! - js2a::vector::const_iterator it = v->begin(); - std::cout << " correct number of values -"; - for( ; it != v->end(); it++ ) { - std::cout << " " << *it; - } - std::cout << std::endl; - } - } else { - if( v || j.success() ) { - std::cout << " false positive - v: " << v << " success: " << j.success() << std::endl; - return false; - } else { - std::cout << " not found, as expected." << std::endl; - } - } - return true; -} - -int main() { - bool pass = true; - std::cout.setf( std::ios::boolalpha ); - - js2a js( 255 ); - js.insert( "blah", 1234 ); - js.insert( "bah", 124 ); - js.insert( "blh", 123 ); - js.insert( "blh", 4123 ); - js.insert( "bla", 134 ); - js.insert( "bh", 234 ); - - js2a::cpair kv = js.atOrAfter( "ab" ); - std::cout << "atOrAfter test ..." << std::endl; - if( kv.value != 0 && js.success() ) { - std::cout << " key " << kv.key << " value " << kv.value->at( 0 ) << std::endl; - } else { - std::cout << " failed" << std::endl; - pass = false; - } - - pass &= testFind( js, "sdafsd", 0 ); - pass &= testFind( js, "bah", 1 ); - pass &= testFind( js, "blh", 2 ); - - js.clear(); - - //TODO test all of judyS2Array - if( pass ) { - std::cout << "All tests passed." << std::endl; - exit( EXIT_SUCCESS ); - } else { - std::cout << "At least one test failed." << std::endl; - exit( EXIT_FAILURE ); - } -} \ No newline at end of file diff --git a/src/base/judy/test/judyStest.cc b/src/base/judy/test/judyStest.cc deleted file mode 100644 index 3d620b015..000000000 --- a/src/base/judy/test/judyStest.cc +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -#include "judySArray.h" - -int main() { - bool pass = true; - std::cout.setf( std::ios::boolalpha ); - - judySArray< uint64_t > js( 255 ); - js.insert( "blah", 1234 ); - js.insert( "bah", 124 ); - js.insert( "blh", 123 ); - js.insert( "bla", 134 ); - js.insert( "bh", 234 ); - - - judySArray< uint64_t >::pair kv = js.atOrAfter( "ab" ); - //TODO if()... - std::cout << "k " << kv.key << " v " << kv.value << std::endl; - - long v = js.find( "sdafsd" ); - if( v != 0 || js.success() ) { - std::cout << "find: false positive - v: " << v << " success: " << js.success() << std::endl; - pass = false; - } - v = js.find( "bah" ); - if( v != 124 || !js.success() ) { - std::cout << "find: false negative - v: " << v << " success: " << js.success() << std::endl; - pass = false; - } - - - //TODO test all of judySArray - if( pass ) { - std::cout << "All tests passed." << std::endl; - exit( EXIT_SUCCESS ); - } else { - std::cout << "At least one test failed." << std::endl; - exit( EXIT_FAILURE ); - } -} \ No newline at end of file diff --git a/src/base/judy/test/pennySort.c b/src/base/judy/test/pennySort.c deleted file mode 100644 index a279b1a70..000000000 --- a/src/base/judy/test/pennySort.c +++ /dev/null @@ -1,236 +0,0 @@ -// Judy arrays 13 DEC 2012 (judy64n.c from http://code.google.com/p/judyarray/ ) -// This code is public domain. - -// Author Karl Malbrain, malbrain AT yahoo.com -// with assistance from Jan Weiss. -// modifications (and any bugs) by Mark Pictor, mpictor at gmail - -// Simplified judy arrays for strings and integers -// Adapted from the ideas of Douglas Baskins of HP. - -// Map a set of keys to corresponding memory cells (uints). -// Each cell must be set to a non-zero value by the caller. - -// STANDALONE is defined to compile into a string sorter. - -// String mappings are denoted by calling judy_open with zero as -// the second argument. - -#ifndef STANDALONE -# error must define STANDALONE while compiling this file and judy64.c -#endif - -#include "judy.h" -#include "sort.h" - -unsigned int MaxMem = 0; - -// usage: -// a.out [in-file] [out-file] [keysize] [recordlen] [keyoffset] [mergerecs] -// where keysize is 10 to indicate pennysort files - -// ASKITIS compilation: -// g++ -O3 -fpermissive -fomit-frame-pointer -w -D STANDALONE -D ASKITIS -o judy64n judy64n.c -// ./judy64n [input-file-to-build-judy] e.g. distinct_1 or skew1_1 - -// note: the judy array is an in-memory data structure. As such, make sure you -// have enough memory to hold the entire input file + data structure, otherwise -// you'll have to break the input file into smaller pieces and load them in -// on-by-one. - -// Also, the file to search judy is hardcoded to skew1_1. - -int main( int argc, char ** argv ) { - unsigned char buff[1024]; - JudySlot max = 0; - JudySlot * cell; - FILE * in, *out; - void * judy; - unsigned int len; - unsigned int idx; -#ifdef ASKITIS - char * askitis; - int prev, off; - float insert_real_time = 0.0; - float search_real_time = 0.0; - int size; -#if !defined(_WIN32) - timer start, stop; -#else - time_t start[1], stop[1]; -#endif -#endif - - if( argc > 1 ) { - in = fopen( argv[1], "rb" ); - } else { - in = stdin; - } - - if( argc > 2 ) { - out = fopen( argv[2], "wb" ); - } else { - out = stdout; - } - - setvbuf( out, NULL, _IOFBF, 4096 * 1024 ); - - if( !in ) { - fprintf( stderr, "unable to open input file\n" ); - } - - if( !out ) { - fprintf( stderr, "unable to open output file\n" ); - } - - if( argc > 6 ) { - PennyRecs = atoi( argv[6] ); - } - - if( argc > 5 ) { - PennyOff = atoi( argv[5] ); - } - - if( argc > 4 ) { - PennyLine = atoi( argv[4] ); - } - - PennyMerge = ( unsigned long long )PennyLine * PennyRecs; - - if( argc > 3 ) { - PennyKey = atoi( argv[3] ); - sort( in, argv[2] ); - return merge( out, argv[2] ); - } - -#ifdef ASKITIS - judy = judy_open( 1024, 0 ); - -// build judy array - size = lseek( fileno( in ), 0L, 2 ); - askitis = malloc( size ); - lseek( fileno( in ), 0L, 0 ); - read( fileno( in ), askitis, size ); - prev = 0; -// naskitis.com: -// Start the timer. - -#if !defined(_WIN32) - gettimeofday( &start, NULL ); -#else - time( start ); -#endif - - for( off = 0; off < size; off++ ) - if( askitis[off] == '\n' ) { - *( judy_cell( judy, askitis + prev, off - prev ) ) += 1; // count instances of string - prev = off + 1; - } -// naskitis.com: -// Stop the timer and do some math to compute the time required to insert the strings into the judy array. - -#if !defined(_WIN32) - gettimeofday( &stop, NULL ); - - insert_real_time = 1000.0 * ( stop.tv_sec - start.tv_sec ) + 0.001 * ( stop.tv_usec - start.tv_usec ); - insert_real_time = insert_real_time / 1000.0; -#else - time( stop ); - insert_real_time = *stop - *start; -#endif - -// naskitis.com: -// Free the input buffer used to store the first file. We must do this before we get the process size below. - free( askitis ); - fprintf( stderr, "JudyArray@Karl_Malbrain\nDASKITIS option enabled\n-------------------------------\n%-20s %.2f MB\n%-20s %.2f sec\n", - "Judy Array size:", MaxMem / 1000000., "Time to insert:", insert_real_time ); - fprintf( stderr, "%-20s %d\n", "Words:", Words ); - fprintf( stderr, "%-20s %d\n", "Inserts:", Inserts ); - fprintf( stderr, "%-20s %d\n", "Found:", Found ); - - Words = 0; - Inserts = 0; - Found = 0; - -// search judy array - if( in = freopen( "skew1_1", "rb", in ) ) { - size = lseek( fileno( in ), 0L, 2 ); - } else { - exit( 0 ); - } - askitis = malloc( size ); - lseek( fileno( in ), 0L, 0 ); - read( fileno( in ), askitis, size ); - prev = 0; - -#if !defined(_WIN32) - gettimeofday( &start, NULL ); -#else - time( start ); -#endif - - for( off = 0; off < size; off++ ) - if( askitis[off] == '\n' ) { - *judy_cell( judy, askitis + prev, off - prev ) += 1; - prev = off + 1; - } -// naskitis.com: -// Stop the timer and do some math to compute the time required to search the judy array. - -#if !defined(_WIN32) - gettimeofday( &stop, NULL ); - search_real_time = 1000.0 * ( stop.tv_sec - start.tv_sec ) + 0.001 - * ( stop.tv_usec - start.tv_usec ); - search_real_time = search_real_time / 1000.0; -#else - time( stop ); - search_real_time = *stop - *start; -#endif - -// naskitis.com: -// To do: report a count on the number of strings found. - - fprintf( stderr, "\n%-20s %.2f MB\n%-20s %.2f sec\n", - "Judy Array size:", MaxMem / 1000000., "Time to search:", search_real_time ); - fprintf( stderr, "%-20s %d\n", "Words:", Words ); - fprintf( stderr, "%-20s %d\n", "Inserts:", Inserts ); - fprintf( stderr, "%-20s %d\n", "Found:", Found ); - exit( 0 ); -#endif - - judy = judy_open( 1024, 0 ); - - while( fgets( ( char * )buff, sizeof( buff ), in ) ) { - if( len = strlen( ( const char * )buff ) ) { - buff[--len] = 0; // remove LF - } - *( judy_cell( judy, buff, len ) ) += 1; // count instances of string - max++; - } - - fprintf( stderr, "%" PRIuint " memory used\n", MaxMem ); - - cell = judy_strt( judy, NULL, 0 ); - - if( cell ) do { - len = judy_key( judy, buff, sizeof( buff ) ); - for( idx = 0; idx < *cell; idx++ ) { // spit out duplicates - fwrite( buff, len, 1, out ); - fputc( '\n', out ); - } - } while( cell = judy_nxt( judy ) ); - -#if 0 - // test deletion all the way to an empty tree - - if( cell = judy_prv( judy ) ) - do { - max -= *cell; - } while( cell = judy_del( judy ) ); - - assert( max == 0 ); -#endif - judy_close( judy ); - return 0; -} - diff --git a/src/base/judy/test/sort.c b/src/base/judy/test/sort.c deleted file mode 100644 index e483b92e0..000000000 --- a/src/base/judy/test/sort.c +++ /dev/null @@ -1,233 +0,0 @@ -// Judy arrays 13 DEC 2012 (judy64n.c from http://code.google.com/p/judyarray/ ) -// This code is public domain. - -// Author Karl Malbrain, malbrain AT yahoo.com -// with assistance from Jan Weiss. -// modifications (and any bugs) by Mark Pictor, mpictor at gmail - -// Simplified judy arrays for strings and integers -// Adapted from the ideas of Douglas Baskins of HP. - -// Map a set of keys to corresponding memory cells (uints). -// Each cell must be set to a non-zero value by the caller. - -// STANDALONE is defined to compile into a string sorter. - -// String mappings are denoted by calling judy_open with zero as -// the second argument. Integer mappings are denoted by calling -// judy_open with the Integer depth of the Judy Trie as the second -// argument. - -#include "judy.h" -#include "sort.h" - -// memory map input file and sort - -// define pennysort parameters -unsigned int PennyRecs = ( 4096 * 400 ); // records to sort to temp files -unsigned int PennyLine = 100; // length of input record -unsigned int PennyKey = 10; // length of input key -unsigned int PennyOff = 0; // key offset in input record - -unsigned long long PennyMerge; // PennyRecs * PennyLine = file map length -unsigned int PennyPasses; // number of intermediate files created -unsigned int PennySortTime; // cpu time to run sort -unsigned int PennyMergeTime; // cpu time to run merge - -void sort( FILE * infile, char * outname ) { - unsigned long long size, off, offset, part; - int ifd = fileno( infile ); - char filename[512]; - PennySort * line; - JudySlot * cell; - unsigned char * inbuff; - void * judy; - FILE * out; -#if defined(_WIN32) - HANDLE hndl, fm; - DWORD hiword; - FILETIME dummy[1]; - FILETIME user[1]; -#else - struct tms buff[1]; -#endif - time_t start = time( NULL ); - - if( PennyOff + PennyKey > PennyLine ) { - fprintf( stderr, "Key Offset + Key Length > Record Length\n" ), exit( 1 ); - } - - offset = 0; - PennyPasses = 0; - -#if defined(_WIN32) - hndl = ( HANDLE )_get_osfhandle( ifd ); - size = GetFileSize( hndl, &hiword ); - fm = CreateFileMapping( hndl, NULL, PAGE_READONLY, hiword, ( DWORD )size, NULL ); - if( !fm ) { - fprintf( stderr, "CreateFileMapping error %d\n", GetLastError() ), exit( 1 ); - } - size |= ( unsigned long long )hiword << 32; -#else - size = lseek( ifd, 0L, 2 ); -#endif - - while( offset < size ) { -#if defined(_WIN32) - part = offset + PennyMerge > size ? size - offset : PennyMerge; - inbuff = MapViewOfFile( fm, FILE_MAP_READ, offset >> 32, offset, part ); - if( !inbuff ) { - fprintf( stderr, "MapViewOfFile error %d\n", GetLastError() ), exit( 1 ); - } -#else - inbuff = mmap( NULL, PennyMerge, PROT_READ, MAP_SHARED, ifd, offset ); - - if( inbuff == MAP_FAILED ) { - fprintf( stderr, "mmap error %d\n", errno ), exit( 1 ); - } - - if( madvise( inbuff, PennyMerge, MADV_WILLNEED | MADV_SEQUENTIAL ) < 0 ) { - fprintf( stderr, "madvise error %d\n", errno ); - } -#endif - judy = judy_open( PennyKey, 0 ); - - off = 0; - - // build judy array from mapped input chunk - - while( offset + off < size && off < PennyMerge ) { - line = judy_data( judy, sizeof( PennySort ) ); - cell = judy_cell( judy, inbuff + off + PennyOff, PennyKey ); - line->next = *( void ** )cell; - line->buff = inbuff + off; - - *( PennySort ** )cell = line; - off += PennyLine; - } - - sprintf( filename, "%s.%d", outname, PennyPasses ); - out = fopen( filename, "wb" ); - setvbuf( out, NULL, _IOFBF, 4096 * 1024 ); - -#ifndef _WIN32 - if( madvise( inbuff, PennyMerge, MADV_WILLNEED | MADV_RANDOM ) < 0 ) { - fprintf( stderr, "madvise error %d\n", errno ); - } -#endif - - // write judy array in sorted order to temporary file - - cell = judy_strt( judy, NULL, 0 ); - - if( cell ) do { - line = *( PennySort ** )cell; - do { - fwrite( line->buff, PennyLine, 1, out ); - } while( line = line->next ); - } while( cell = judy_nxt( judy ) ); - -#if defined(_WIN32) - UnmapViewOfFile( inbuff ); -#else - munmap( inbuff, PennyMerge ); -#endif - judy_close( judy ); - offset += off; - fflush( out ); - fclose( out ); - PennyPasses++; - } - fprintf( stderr, "End Sort %llu secs", ( unsigned long long ) time( NULL ) - start ); -#if defined(_WIN32) - CloseHandle( fm ); - GetProcessTimes( GetCurrentProcess(), dummy, dummy, dummy, user ); - PennySortTime = *( unsigned long long * )user / 10000000; -#else - times( buff ); - PennySortTime = buff->tms_utime / 100; -#endif - fprintf( stderr, " Cpu %d\n", PennySortTime ); -} - -int merge( FILE * out, char * outname ) { - time_t start = time( NULL ); - char filename[512]; - JudySlot * cell; - unsigned int nxt, idx; - unsigned char ** line; - unsigned int * next; - void * judy; - FILE ** in; - - next = calloc( PennyPasses + 1, sizeof( unsigned int ) ); - line = calloc( PennyPasses, sizeof( void * ) ); - in = calloc( PennyPasses, sizeof( void * ) ); - - judy = judy_open( PennyKey, 0 ); - - // initialize merge with one record from each temp file - - for( idx = 0; idx < PennyPasses; idx++ ) { - sprintf( filename, "%s.%d", outname, idx ); - in[idx] = fopen( filename, "rb" ); - line[idx] = malloc( PennyLine ); - setvbuf( in[idx], NULL, _IOFBF, 4096 * 1024 ); - fread( line[idx], PennyLine, 1, in[idx] ); - cell = judy_cell( judy, line[idx] + PennyOff, PennyKey ); - next[idx + 1] = *( unsigned int * )cell; - *cell = idx + 1; - } - - // output records, replacing smallest each time - - while( cell = judy_strt( judy, NULL, 0 ) ) { - nxt = *( unsigned int * )cell; - judy_del( judy ); - - // process duplicates - - while( idx = nxt ) { - nxt = next[idx--]; - fwrite( line[idx], PennyLine, 1, out ); - - if( fread( line[idx], PennyLine, 1, in[idx] ) ) { - cell = judy_cell( judy, line[idx] + PennyOff, PennyKey ); - next[idx + 1] = *( unsigned int * )cell; - *cell = idx + 1; - } else { - next[idx + 1] = 0; - } - } - } - - for( idx = 0; idx < PennyPasses; idx++ ) { - fclose( in[idx] ); - free( line[idx] ); - } - - free( line ); - free( next ); - free( in ); - - fprintf( stderr, "End Merge %llu secs", ( unsigned long long ) time( NULL ) - start ); -#ifdef _WIN32 - { - FILETIME dummy[1]; - FILETIME user[1]; - GetProcessTimes( GetCurrentProcess(), dummy, dummy, dummy, user ); - PennyMergeTime = *( unsigned long long * )user / 10000000; - } -#else - { - struct tms buff[1]; - times( buff ); - PennyMergeTime = buff->tms_utime / 100; - } -#endif - fprintf( stderr, " Cpu %d\n", PennyMergeTime - PennySortTime ); - judy_close( judy ); - fflush( out ); - fclose( out ); - return 0; -} diff --git a/src/base/judy/test/sort.h b/src/base/judy/test/sort.h deleted file mode 100644 index 785e58d69..000000000 --- a/src/base/judy/test/sort.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SORT_H -#define SORT_H - -// Judy arrays 13 DEC 2012 (judy64n.c from http://code.google.com/p/judyarray/ ) -// This code is public domain. - -// Author Karl Malbrain, malbrain AT yahoo.com -// with assistance from Jan Weiss. -// modifications (and any bugs) by Mark Pictor, mpictor at gmail - -// Simplified judy arrays for strings and integers -// Adapted from the ideas of Douglas Baskins of HP. - -// Map a set of keys to corresponding memory cells (uints). -// Each cell must be set to a non-zero value by the caller. - -// STANDALONE is defined to compile into a string sorter. - -// String mappings are denoted by calling judy_open with zero as -// the second argument. Integer mappings are denoted by calling -// judy_open with the Integer depth of the Judy Trie as the second -// argument. - -#include -#include -#include -#include -#include "judy.h" - -#ifdef linux -# include -# include -# include -# include -# include -#else -# include -# include -#endif - -#include - -#define PRIuint "u" - - -//these are initialized in penny.c -extern unsigned int PennyRecs; -extern unsigned int PennyLine; -extern unsigned int PennyKey; -extern unsigned int PennyOff; -extern unsigned long long PennyMerge; - -typedef struct { - void * buff; // record pointer in input file map - void * next; // duplicate chain -} PennySort; - -#endif //SORT_H \ No newline at end of file diff --git a/src/base/path2str.c b/src/base/path2str.c deleted file mode 100644 index 6f5aedd7c..000000000 --- a/src/base/path2str.c +++ /dev/null @@ -1,29 +0,0 @@ - -#include "path2str.h" -#include "sc_memmgr.h" -#include - -/* for windows, rewrite backslashes in paths - * that will be written to generated code - */ -const char * path2str_fn( const char * fileMacro ) { - static char * result = 0; - static size_t rlen = 0; - char * p; - if( rlen < strlen( fileMacro ) ) { - if( result ) { - sc_free( result ); - } - rlen = strlen( fileMacro ); - result = ( char * )sc_malloc( rlen * sizeof( char ) + 1 ); - } - strcpy( result, fileMacro ); - p = result; - while( *p ) { - if( *p == '\\' ) { - *p = '/'; - } - p++; - } - return result; -} diff --git a/src/base/path2str.h b/src/base/path2str.h deleted file mode 100644 index 84155cd9f..000000000 --- a/src/base/path2str.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef PATH2STR_H -#define PATH2STR_H - -#include - -/** windows only: rewrite backslashes in paths as forward slashes - * call as path2str(__FILE__) to take advantage of macro - * - * silence "unknown escape sequence" warning when contents of __FILE__ - * are fprintf'd into string in generated code - */ -SC_BASE_EXPORT const char * path2str_fn( const char * fileMacro ); - -#ifdef _WIN32 -# define path2str(path) path2str_fn(path) -#else -# define path2str(path) path -#endif - -#endif /* PATH2STR_H */ diff --git a/src/base/sc_getopt.cc b/src/base/sc_getopt.cc deleted file mode 100644 index 01e925b56..000000000 --- a/src/base/sc_getopt.cc +++ /dev/null @@ -1,214 +0,0 @@ -/****** RENAMED from xgetopt.cc to sc_getopt.cc ***********/ - -// XGetopt.cpp Version 1.2 -// -// Author: Hans Dietrich -// hdietrich2@hotmail.com -// -// Description: -// XGetopt.cpp implements sc_getopt(), a function to parse command lines. -// -// History -// Version 1.2 - 2003 May 17 -// - Added Unicode support -// -// Version 1.1 - 2002 March 10 -// - Added example to XGetopt.cpp module header -// -// This software is released into the public domain. -// You are free to use it in any way you like. -// -// This software is provided "as is" with no expressed -// or implied warranty. I accept no liability for any -// damage or loss of business that this software may cause. -// -/////////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// -// if you are using precompiled headers then include this line: -//#include "stdafx.h" -/////////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// -// if you are not using precompiled headers then include these lines: -//#include -#include -#include -/////////////////////////////////////////////////////////////////////////////// - -#include "sc_getopt.h" - -/////////////////////////////////////////////////////////////////////////////// -// -// X G e t o p t . c p p -// -// -// NAME -// sc_getopt -- parse command line options -// -// SYNOPSIS -// int sc_getopt(int argc, char *argv[], char *optstring) -// -// extern char *sc_optarg; -// extern int sc_optind; -// -// DESCRIPTION -// The sc_getopt() function parses the command line arguments. Its -// arguments argc and argv are the argument count and array as -// passed into the application on program invocation. In the case -// of Visual C++ programs, argc and argv are available via the -// variables __argc and __argv (double underscores), respectively. -// sc_getopt returns the next option letter in argv that matches a -// letter in optstring. (Note: Unicode programs should use -// __targv instead of __argv. Also, all character and string -// literals should be enclosed in _T( ) ). -// -// optstring is a string of recognized option letters; if a letter -// is followed by a colon, the option is expected to have an argument -// that may or may not be separated from it by white space. sc_optarg -// is set to point to the start of the option argument on return from -// sc_getopt. -// -// Option letters may be combined, e.g., "-ab" is equivalent to -// "-a -b". Option letters are case sensitive. -// -// sc_getopt places in the external variable sc_optind the argv index -// of the next argument to be processed. sc_optind is initialized -// to 0 before the first call to sc_getopt. -// -// When all options have been processed (i.e., up to the first -// non-option argument), sc_getopt returns EOF, sc_optarg will point -// to the argument, and sc_optind will be set to the argv index of -// the argument. If there are no non-option arguments, sc_optarg -// will be set to NULL. -// -// The special option "--" may be used to delimit the end of the -// options; EOF will be returned, and "--" (and everything after it) -// will be skipped. -// -// RETURN VALUE -// For option letters contained in the string optstring, sc_getopt -// will return the option letter. sc_getopt returns a question mark (?) -// when it encounters an option letter not included in optstring. -// EOF is returned when processing is finished. -// -// BUGS -// 1) Long options are not supported. -// 2) The GNU double-colon extension is not supported. -// 3) The environment variable POSIXLY_CORRECT is not supported. -// 4) The + syntax is not supported. -// 5) The automatic permutation of arguments is not supported. -// 6) This implementation of sc_getopt() returns EOF if an error is -// encountered, instead of -1 as the latest standard requires. -// -// EXAMPLE -// BOOL CMyApp::ProcessCommandLine(int argc, char *argv[]) -// { -// int c; -// -// while ((c = sc_getopt(argc, argv, _T("aBn:"))) != EOF) -// { -// switch (c) -// { -// case _T('a'): -// TRACE(_T("option a\n")); -// // -// // set some flag here -// // -// break; -// -// case _T('B'): -// TRACE( _T("option B\n")); -// // -// // set some other flag here -// // -// break; -// -// case _T('n'): -// TRACE(_T("option n: value=%d\n"), atoi(sc_optarg)); -// // -// // do something with value here -// // -// break; -// -// case _T('?'): -// TRACE(_T("ERROR: illegal option %s\n"), argv[sc_optind-1]); -// return FALSE; -// break; -// -// default: -// TRACE(_T("WARNING: no handler for option %c\n"), c); -// return FALSE; -// break; -// } -// } -// // -// // check for non-option args here -// // -// return TRUE; -// } -// -/////////////////////////////////////////////////////////////////////////////// - -char * sc_optarg; // global argument pointer -int sc_optind = 0; // global argv index - -int sc_getopt( int argc, char * argv[], char * optstring ) { - static char * next = NULL; - if( sc_optind == 0 ) { - next = NULL; - } - - sc_optarg = NULL; - - if( next == NULL || *next == '\0' ) { - if( sc_optind == 0 ) { - sc_optind++; - } - - if( sc_optind >= argc || argv[sc_optind][0] != '-' || argv[sc_optind][1] == '\0' ) { - sc_optarg = NULL; - if( sc_optind < argc ) { - sc_optarg = argv[sc_optind]; - } - return EOF; - } - - if( strcmp( argv[sc_optind], "--" ) == 0 ) { - sc_optind++; - sc_optarg = NULL; - if( sc_optind < argc ) { - sc_optarg = argv[sc_optind]; - } - return EOF; - } - - next = argv[sc_optind]; - next++; // skip past - - sc_optind++; - } - - char c = *next++; - char * cp = strchr( optstring, c ); - - if( cp == NULL || c == ':' ) { - return '?'; - } - - cp++; - if( *cp == ':' ) { - if( *next != '\0' ) { - sc_optarg = next; - next = NULL; - } else if( sc_optind < argc ) { - sc_optarg = argv[sc_optind]; - sc_optind++; - } else { - return '?'; - } - } - - return c; -} diff --git a/src/base/sc_getopt.h b/src/base/sc_getopt.h deleted file mode 100644 index e1421a7bf..000000000 --- a/src/base/sc_getopt.h +++ /dev/null @@ -1,32 +0,0 @@ -/** \file sc_getopt.h - * this was xgetopt.h - * XGetopt.h Version 1.2 - * - * Author: Hans Dietrich - * hdietrich2@hotmail.com - * - * This software is released into the public domain. - * You are free to use it in any way you like. - * - * This software is provided "as is" with no expressed - * or implied warranty. I accept no liability for any - * damage or loss of business that this software may cause. - */ -#ifndef XGETOPT_H -#define XGETOPT_H -#include "sc_export.h" - -#ifdef __cplusplus -extern "C" { -#endif - - extern SC_BASE_EXPORT int sc_optind, sc_opterr; - extern SC_BASE_EXPORT char * sc_optarg; - - int SC_BASE_EXPORT sc_getopt( int argc, char * argv[], char * optstring ); - -#ifdef __cplusplus -} -#endif - -#endif /* XGETOPT_H */ diff --git a/src/base/sc_memmgr.cc b/src/base/sc_memmgr.cc deleted file mode 100644 index 262d26e28..000000000 --- a/src/base/sc_memmgr.cc +++ /dev/null @@ -1,405 +0,0 @@ - -#define SC_MEMMGR_CC - -#include -#include "sc_memmgr.h" - -#include -#include - -#include -#include - -#ifdef SC_MEMMGR_ENABLE_CHECKS - -/** - sc_memmgr_error definition -*/ -class sc_memmgr_error { - private: - std::string _srcfile; - unsigned int _srcline; - unsigned int _occurences; - public: - sc_memmgr_error( const std::string & file, const unsigned int line ); - sc_memmgr_error( const sc_memmgr_error & rhs ); - ~sc_memmgr_error( void ); - - bool operator<( const sc_memmgr_error & rhs ) const; - - std::string getsrcfile( void ) const; - unsigned int getsrcline( void ) const; - unsigned int getoccurences( void ) const; -}; - -typedef std::set sc_memmgr_errors; -typedef std::set::iterator sc_memmgr_error_iterator; - -/** - sc_memmgr_record definition -*/ -class sc_memmgr_record { - private: - void * _addr; - size_t _size; - std::string _srcfile; - unsigned int _srcline; - public: - sc_memmgr_record( void * addr, size_t size, const char * file, const unsigned int line ); - sc_memmgr_record( void * addr ); - sc_memmgr_record( const sc_memmgr_record & rhs ); - ~sc_memmgr_record( void ); - - bool operator<( const sc_memmgr_record & rhs ) const; - - void * getaddr( void ) const; - size_t getsize( void ) const; - std::string getsrcfile( void ) const; - unsigned int getsrcline( void ) const; -}; - -typedef std::set sc_memmgr_records; -typedef std::set::iterator sc_memmgr_record_iterator; - -#endif /* SC_MEMMGR_ENABLE_CHECKS */ - -/** - sc_memmgr definition -*/ -class sc_memmgr { - private: -#ifdef SC_MEMMGR_ENABLE_CHECKS - bool _record_insert_busy, _record_erase_busy; - // memory allocation/reallocation records, inserted at allocation, erased at deallocation. - sc_memmgr_records _records; - // memory stats - unsigned int _allocated; // amount of memory allocated simultaniously - unsigned int _maximum_allocated; // maximum amount of memory allocated simultaniously - unsigned int _allocated_total; // total amount of memory allocated in bytes - unsigned int _reallocated_total; // total amount of memory reallocated in bytes - unsigned int _deallocated_total; // total amount of memory deallocated in bytes -#endif /* SC_MEMMGR_ENABLE_CHECKS */ - protected: - public: - sc_memmgr( void ); - ~sc_memmgr( void ); - - void * allocate( size_t size, const char * file, const int line ); - void * reallocate( void * addr, size_t size, const char * file, const int line ); - void deallocate( void * addr, const char * file, const int line ); -}; - -/** - sc_memmgr instance. - There should be one static instance of memmgr. - This instance is automatically destroyed when application exits, so this allows us to add - memory leak detection in it's destructor. -*/ -sc_memmgr memmgr; - -/** - c memory functions implementation -*/ -extern "C" { - - void * sc_malloc_fn( unsigned int size, const char * file, const int line ) { - return memmgr.allocate( size, file, line ); - } - - void * sc_calloc_fn( unsigned int count, unsigned int size, const char * file, const int line ) { - return memmgr.allocate( count * size, file, line ); - } - - void * sc_realloc_fn( void * addr, unsigned int size, const char * file, const int line ) { - return memmgr.reallocate( addr, size, file, line ); - } - - void sc_free_fn( void * addr ) { - memmgr.deallocate( addr, "", 0 ); - } - -} - -/** - c++ memory operators implementation -*/ -void * sc_operator_new( size_t size, const char * file, const int line ) { - return memmgr.allocate( size, file, line ); -} - -void sc_operator_delete( void * addr, const char * file, const int line ) { - memmgr.deallocate( addr, file, line ); -} - -void sc_operator_delete( void * addr ) { - memmgr.deallocate( addr, "", 0 ); -} - -/** - sc_memmgr implementation -*/ -sc_memmgr::sc_memmgr( void ) { -#ifdef SC_MEMMGR_ENABLE_CHECKS - _record_insert_busy = false; - _record_erase_busy = false; - - _allocated = 0; - _maximum_allocated = 0; - _allocated_total = 0; - _reallocated_total = 0; - _deallocated_total = 0; -#endif /* SC_MEMMGR_ENABLE_CHECKS */ -} - -/** - Destructor: - sc_memmgr::~sc_memmgr(void) - Description: - The sc_memmgr destructor is used to check for memory leaks when enabled. - All records still present when sc_memmgr instance is destroyed can be considered as - memory leaks. -*/ -sc_memmgr::~sc_memmgr( void ) { -#ifdef SC_MEMMGR_ENABLE_CHECKS - sc_memmgr_record_iterator irecord; - sc_memmgr_errors errors; - sc_memmgr_error_iterator ierror; - - // Check if total allocated equals total deallocated - if( _allocated_total != _deallocated_total ) { - // todo: generate warning for possible memory leaks, enable full memory leak checking - fprintf( stderr, "sc_memmgr warning: Possible memory leaks detected (%d of %d bytes)\n", _allocated_total - _deallocated_total, _allocated_total ); - } - - // Compact leaks into an error list to prevent same leak being reported multiple times. - _record_insert_busy = true; - _record_erase_busy = true; - for( irecord = _records.begin(); - irecord != _records.end(); - irecord ++ ) { - sc_memmgr_error error( irecord->getsrcfile(), irecord->getsrcline() ); - ierror = errors.find( error ); - if( ierror == errors.end() ) { - errors.insert( error ); - } - //else - // ierror->occurences ++; - } - _record_insert_busy = false; - _record_erase_busy = false; - - // Loop through memory leaks to generate/buffer errors - for( ierror = errors.begin(); - ierror != errors.end(); - ierror ++ ) { - // todo: generate error for memory leak - fprintf( stderr, "sc_memmgr warning: Possible memory leak in %s line %d\n", ierror->getsrcfile().c_str(), ierror->getsrcline() ); - } - - // Clear remaining records - _record_erase_busy = true; - _records.clear(); - errors.clear(); - _record_erase_busy = false; -#endif /* SC_MEMMGR_ENABLE_CHECKS */ -} - -void * sc_memmgr::allocate( size_t size, const char * file, const int line ) { - void * addr; - - // Allocate - addr = malloc( size ); - if( addr == NULL ) { - // todo: error allocation failed - fprintf( stderr, "sc_memmgr error: Memory allocation failed in %s line %d\n", file, line ); - } - - // Some stl implementations (for example debian gcc) use the new operator to construct - // new elements when inserting sc_memmgr_record. When this our new operator gets used - // for this operation, this would result in an infinite loop. This is fixed by the - // _record_insert_busy flag. -#ifdef SC_MEMMGR_ENABLE_CHECKS - if( !_record_insert_busy ) { - // Store record for this allocation - _record_insert_busy = true; - _records.insert( sc_memmgr_record( addr, size, file, line ) ); - _record_insert_busy = false; - - // Update stats - _allocated += size; - if( _allocated > _maximum_allocated ) { - _maximum_allocated = _allocated; - } - _allocated_total += size; - } -#endif /* SC_MEMMGR_ENABLE_CHECKS */ - - return addr; -} - -void * sc_memmgr::reallocate( void * addr, size_t size, const char * file, const int line ) { -#ifdef SC_MEMMGR_ENABLE_CHECKS - sc_memmgr_record_iterator record; - - if( !_record_insert_busy ) { - // Find record of previous allocation/reallocation - record = _records.find( sc_memmgr_record( addr ) ); - if( record == _records.end() ) { - // todo: error reallocating memory not allocated? - fprintf( stderr, "sc_memmgr warning: Reallocation of not allocated memory at %s line %d\n", file, line ); - } else { - // Update stats - _allocated -= record->getsize(); - _deallocated_total += record->getsize(); - - // Erase previous allocation/reallocation - _record_erase_busy = true; - _records.erase( record ); - _record_erase_busy = false; - } - } -#endif /* SC_MEMMGR_ENABLE_CHECKS */ - - // Reallocate - addr = realloc( addr, size ); - if( addr == NULL ) { - // todo: error reallocation failed - fprintf( stderr, "sc_memmgr error: Reallocation failed at %s line %d\n", file, line ); - } - -#ifdef SC_MEMMGR_ENABLE_CHECKS - if( !_record_insert_busy ) { - // Store record for this reallocation - _record_insert_busy = true; - _records.insert( sc_memmgr_record( addr, size, file, line ) ); - _record_insert_busy = false; - - // Update stats - _allocated += size; - if( _allocated > _maximum_allocated ) { - _maximum_allocated = _allocated; - } - _allocated_total += size; - _reallocated_total += size; - } -#endif /* SC_MEMMGR_ENABLE_CHECKS */ - - return addr; -} - -void sc_memmgr::deallocate( void * addr, const char * file, const int line ) { -#ifdef SC_MEMMGR_ENABLE_CHECKS - sc_memmgr_record_iterator record; - - if( !_record_erase_busy ) { - // Find record of previous allocation/reallocation - record = _records.find( sc_memmgr_record( addr ) ); - if( record == _records.end() ) { - // todo: error free called for not allocated memory? - fprintf( stderr, "sc_memmgr warning: Deallocate of not allocated memory at %s line %d\n", file, line ); - } else { - // Update stats - _allocated -= record->getsize(); - _deallocated_total += record->getsize(); - - // Erase record - _record_erase_busy = true; - _records.erase( record ); - _record_erase_busy = false; - } - } -#else - (void) file; // quell unused param warnings - (void) line; -#endif /* SC_MEMMGR_ENABLE_CHECKS */ - - // Deallocate - free( addr ); -} - -#ifdef SC_MEMMGR_ENABLE_CHECKS -/** - sc_memmgr_error implementation -*/ -sc_memmgr_error::sc_memmgr_error( const std::string & file, const unsigned int line ) { - _srcfile = file; - _srcline = line; - _occurences = 1; -} - -sc_memmgr_error::sc_memmgr_error( const sc_memmgr_error & rhs ) { - _srcfile = rhs._srcfile; - _srcline = rhs._srcline; - _occurences = rhs._occurences; -} - -sc_memmgr_error::~sc_memmgr_error( void ) { -} - -bool sc_memmgr_error::operator<( const sc_memmgr_error & rhs ) const { - if( _srcfile == rhs._srcfile ) { - return _srcline < rhs._srcline; - } - return _srcfile < rhs._srcfile; -} - -std::string sc_memmgr_error::getsrcfile( void ) const { - return _srcfile; -} - -unsigned int sc_memmgr_error::getsrcline( void ) const { - return _srcline; -} - -unsigned int sc_memmgr_error::getoccurences( void ) const { - return _occurences; -} - -/** - sc_memmgr_record implementation -*/ -sc_memmgr_record::sc_memmgr_record( void * addr, size_t size, const char * file, const unsigned int line ) { - _addr = addr; - _size = size; - _srcfile = file; - _srcline = line; -} - -sc_memmgr_record::sc_memmgr_record( void * addr ) { - _addr = addr; - _size = 0; - _srcfile = ""; - _srcline = -1; -} - -sc_memmgr_record::sc_memmgr_record( const sc_memmgr_record & rhs ) { - _addr = rhs._addr; - _size = rhs._size; - _srcfile = rhs._srcfile; - _srcline = rhs._srcline; -} - -sc_memmgr_record::~sc_memmgr_record( void ) { -} - -bool sc_memmgr_record::operator<( const sc_memmgr_record & rhs ) const { - return _addr < rhs._addr; -} - -void * sc_memmgr_record::getaddr( void ) const { - return _addr; -} - -size_t sc_memmgr_record::getsize( void ) const { - return _size; -} - -std::string sc_memmgr_record::getsrcfile( void ) const { - return _srcfile; -} - -unsigned int sc_memmgr_record::getsrcline( void ) const { - return _srcline; -} - -#endif /* SC_MEMMGR_ENABLE_CHECKS */ diff --git a/src/base/sc_memmgr.h b/src/base/sc_memmgr.h deleted file mode 100644 index 9517a20bc..000000000 --- a/src/base/sc_memmgr.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef SC_MEMMGR_H -#define SC_MEMMGR_H - -#include -#include - -#if defined(SC_MEMMGR_ENABLE_CHECKS) - -#ifdef __cplusplus -#include -extern "C" { -#endif /* __cplusplus */ - - SC_BASE_EXPORT void * sc_malloc_fn( unsigned int size, const char * file, const int line ); - SC_BASE_EXPORT void * sc_calloc_fn( unsigned int count, unsigned int size, const char * file, const int line ); - SC_BASE_EXPORT void * sc_realloc_fn( void * addr, unsigned int size, const char * file, const int line ); - SC_BASE_EXPORT void sc_free_fn( void * addr ); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#ifdef __cplusplus - -SC_BASE_EXPORT void * sc_operator_new( size_t size, const char * file, const int line ); -SC_BASE_EXPORT void sc_operator_delete( void * addr, const char * file, const int line ); -SC_BASE_EXPORT void sc_operator_delete( void * addr ); - -#endif /* __cplusplus */ - -#ifndef SC_MEMMGR_CC - -#define sc_malloc(size) sc_malloc_fn(size, __FILE__, __LINE__) -#define sc_calloc(count, size) sc_calloc_fn(count, size, __FILE__, __LINE__) -#define sc_realloc(addr, size) sc_realloc_fn(addr, size, __FILE__, __LINE__) -#define sc_free(addr) sc_free_fn(addr) - -#ifdef __cplusplus - -#include - -inline void * operator new( size_t size, const char * file, const int line ) throw (std::bad_alloc) { - return sc_operator_new( size, file, line ); -} - -inline void * operator new[]( size_t size, const char * file, const int line ) throw (std::bad_alloc) { - return sc_operator_new( size, file, line ); -} - -inline void operator delete( void * addr, const char * file, const int line ) throw (std::bad_alloc) { - sc_operator_delete( addr, file, line ); -} - -inline void operator delete[]( void * addr, const char * file, const int line ) throw (std::bad_alloc) { - sc_operator_delete( addr, file, line ); -} - -inline void operator delete( void * addr ) throw () { - sc_operator_delete( addr ); -} - -inline void operator delete[]( void * addr ) throw () { - sc_operator_delete( addr ); -} - -#define new new(__FILE__, __LINE__) - -#endif /* __cplusplus */ - -#endif /* SC_MEMMGR_CC */ - -#else -#define sc_malloc(size) malloc(size) -#define sc_calloc(count, size) calloc(count, size) -#define sc_realloc(addr, size) realloc(addr, size) -#define sc_free(addr) free(addr) -#endif /* SC_MEMMGR_ENABLE_CHECKS */ - -#endif /* SC_MEMMGR_H */ diff --git a/src/base/sc_mkdir.c b/src/base/sc_mkdir.c deleted file mode 100644 index d0866f6e3..000000000 --- a/src/base/sc_mkdir.c +++ /dev/null @@ -1,32 +0,0 @@ -#define _XOPEN_SOURCE /* for S_IFDIR */ -#include "sc_mkdir.h" - -#include -#include -#include -#ifdef _WIN32 -# include -#endif /* _WIN32 */ - -/* cross-platform mkdir */ -int sc_mkdir( const char * path ) { - #ifdef _WIN32 - return mkdir( path ); - #else - return mkdir( path, 0777 ); - #endif /* _WIN32 */ -} - -/* return -1 if error, 0 if created, 1 if dir existed already */ -int mkDirIfNone( const char * path ) { - struct stat s; - if( stat( path, &s ) != 0 ) { - if( errno == ENOENT ) { - return sc_mkdir( path ); - } - } else if( s.st_mode & S_IFDIR ) { - return 1; - } - /* either stat returned an error other than ENOENT, or 'path' exists but isn't a dir */ - return -1; -} diff --git a/src/base/sc_mkdir.h b/src/base/sc_mkdir.h deleted file mode 100644 index 21c8d9c5c..000000000 --- a/src/base/sc_mkdir.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef SC_MKDIR -#define SC_MKDIR - -#include - -/** cross-platform mkdir() */ -SC_BASE_EXPORT int sc_mkdir( const char * path ); - -/** create a dir 'path' if 'path' doesn't exist - * \return -1 if error, 0 if created, 1 if dir existed already - * if it returns -1, check errno - */ -SC_BASE_EXPORT int mkDirIfNone( const char * path ); - -#endif /* SC_MKDIR */ diff --git a/src/base/sc_stdio.h b/src/base/sc_stdio.h deleted file mode 100644 index 78fefc53b..000000000 --- a/src/base/sc_stdio.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __SC_STDIO_H -#define __SC_STDIO_H - -/* - * https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 - * (NOTE: MSVC defines va_list as a char*, so this should be safe) - */ -#if defined(_MSC_VER) && _MSC_VER < 1900 - -#include - -static __inline int -c99_vsnprintf(char *buffer, size_t sz, const char *format, va_list ap) { - int count = -1; - - if (sz != 0) - count = _vsnprintf_s(buffer, sz, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - - return count; -} - -static __inline int -c99_snprintf(char *buffer, size_t sz, const char *format, ...) { - int count; - va_list ap; - - va_start(ap, format); - count = c99_vsnprintf(buffer, sz, format, ap); - va_end(ap); - - return count; -} - -#endif - -#endif /* __SC_STDIO_H */ - diff --git a/src/base/sc_strtoull.h b/src/base/sc_strtoull.h deleted file mode 100644 index b68b76707..000000000 --- a/src/base/sc_strtoull.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SC_STRTOULL_H -#define SC_STRTOULL_H - -#include - -#ifdef _WIN32 -# define strtoull _strtoui64 -# define ULLONG_MAX _UI64_MAX -#endif - -#endif /* SC_STRTOULL_H */ diff --git a/src/cldai/CMakeLists.txt b/src/cldai/CMakeLists.txt index 023ce1ab6..e37ac06d2 100644 --- a/src/cldai/CMakeLists.txt +++ b/src/cldai/CMakeLists.txt @@ -1,5 +1,4 @@ - -set(LIBSTEPDAI_SRCS +set(DAI_SRCS sdaiApplication_instance_set.cc sdaiBinary.cc sdaiDaObject.cc @@ -13,43 +12,24 @@ set(LIBSTEPDAI_SRCS sdaiString.cc ) -SET(SC_CLDAI_HDRS - sdaiApplication_instance_set.h - sdaiBinary.h - sdaiDaObject.h - sdaiEntity_extent.h - sdaiEntity_extent_set.h - sdaiEnum.h - sdaiModel_contents.h - sdaiModel_contents_list.h - sdaiObject.h - sdaiSession_instance.h - sdaiString.h - ) - include_directories( ${CMAKE_CURRENT_SOURCE_DIR} - ${SC_SOURCE_DIR}/src/base - ${SC_SOURCE_DIR}/src/clstepcore - ${SC_SOURCE_DIR}/src/clutils + ${CMAKE_SOURCE_DIR}/include/stepcode ) -set(_libdeps steputils base) +set(_libdeps steputils) if(BUILD_SHARED_LIBS) - SC_ADDLIB(stepdai SHARED SOURCES ${LIBSTEPDAI_SRCS} LINK_LIBRARIES ${_libdeps}) + SC_ADDLIB(stepdai SHARED SOURCES ${DAI_SRCS} LINK_LIBRARIES ${_libdeps}) if(WIN32) target_compile_definitions(stepdai PRIVATE SC_DAI_DLL_EXPORTS) endif() endif() if(BUILD_STATIC_LIBS) - SC_ADDLIB(stepdai-static STATIC SOURCES ${LIBSTEPDAI_SRCS} LINK_LIBRARIES $-static) + SC_ADDLIB(stepdai-static STATIC SOURCES ${DAI_SRCS} LINK_LIBRARIES $-static) endif() -install(FILES ${SC_CLDAI_HDRS} - DESTINATION ${INCLUDE_DIR}/stepcode/cldai) - # Local Variables: # tab-width: 8 # mode: cmake diff --git a/src/cldai/sdaiApplication_instance_set.cc b/src/cldai/sdaiApplication_instance_set.cc index 30a9103f4..f1733d40d 100644 --- a/src/cldai/sdaiApplication_instance_set.cc +++ b/src/cldai/sdaiApplication_instance_set.cc @@ -24,14 +24,13 @@ * UArray implementation. */ -//#include -#include +//#include "cldai/sdaiApplication_instance_set.h" +#include "clstepcore/sdai.h" #include #include -#include "sc_memmgr.h" -#include "sdaiApplication_instance.h" +#include "clstepcore/sdaiApplication_instance.h" // to help ObjectCenter #ifndef HAVE_MEMMOVE diff --git a/src/cldai/sdaiBinary.cc b/src/cldai/sdaiBinary.cc index 678add01c..d165d1ac0 100644 --- a/src/cldai/sdaiBinary.cc +++ b/src/cldai/sdaiBinary.cc @@ -10,8 +10,7 @@ */ #include -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" SDAI_Binary::SDAI_Binary( const char * str, int max ) { content = std::string( str, max ); @@ -122,17 +121,17 @@ Severity SDAI_Binary::ReadBinary( istream & in, ErrorDescriptor * err, int Assig if( !validDelimiters ) { err->GreaterSeverity( SEVERITY_WARNING ); if( needDelims ) - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), "Binary value missing double quote delimiters.\n" ); else - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), "Mismatched double quote delimiters for binary.\n" ); err->AppendToDetailMsg( messageBuf ); err->AppendToUserMsg( messageBuf ); } } else { err->GreaterSeverity( SEVERITY_WARNING ); - sprintf( messageBuf, "Invalid binary value.\n" ); + snprintf( messageBuf, sizeof(messageBuf), "Invalid binary value.\n" ); err->AppendToDetailMsg( messageBuf ); err->AppendToUserMsg( messageBuf ); } diff --git a/src/cldai/sdaiDaObject.cc b/src/cldai/sdaiDaObject.cc index 2f43ab284..52f06fc16 100644 --- a/src/cldai/sdaiDaObject.cc +++ b/src/cldai/sdaiDaObject.cc @@ -2,8 +2,7 @@ #include #include -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" // to help ObjectCenter #ifndef HAVE_MEMMOVE diff --git a/src/cldai/sdaiEntity_extent.cc b/src/cldai/sdaiEntity_extent.cc index 22db4e61b..7c27ea6e4 100644 --- a/src/cldai/sdaiEntity_extent.cc +++ b/src/cldai/sdaiEntity_extent.cc @@ -2,8 +2,7 @@ //#include -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" SDAI_Entity_extent::SDAI_Entity_extent( ) : _definition( 0 ), _definition_name( 0 ), _owned_by( 0 ) { diff --git a/src/cldai/sdaiEntity_extent_set.cc b/src/cldai/sdaiEntity_extent_set.cc index af3658222..4080e336b 100644 --- a/src/cldai/sdaiEntity_extent_set.cc +++ b/src/cldai/sdaiEntity_extent_set.cc @@ -26,8 +26,7 @@ #include #include -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" /* #include @@ -51,7 +50,7 @@ SDAI_Entity_extent__set::SDAI_Entity_extent__set( int defaultSize ) { } SDAI_Entity_extent__set::~SDAI_Entity_extent__set() { - delete _buf; + delete[] _buf; } void SDAI_Entity_extent__set::Check( int index ) { @@ -62,7 +61,7 @@ void SDAI_Entity_extent__set::Check( int index ) { _bufsize = ( index + 1 ) * 2; newbuf = new SDAI_Entity_extent_ptr[_bufsize]; memmove( newbuf, _buf, _count * sizeof( SDAI_Entity_extent_ptr ) ); - delete _buf; + delete[] _buf; _buf = newbuf; } } diff --git a/src/cldai/sdaiEnum.cc b/src/cldai/sdaiEnum.cc index b0336ac2d..2291144ac 100644 --- a/src/cldai/sdaiEnum.cc +++ b/src/cldai/sdaiEnum.cc @@ -1,6 +1,5 @@ -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" /* * NIST STEP Core Class Library @@ -212,10 +211,10 @@ Severity SDAI_LOGICAL::ReadEnum( istream & in, ErrorDescriptor * err, int Assign if( !validDelimiters ) { err->GreaterSeverity( SEVERITY_WARNING ); if( needDelims ) - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), "Enumerated value has invalid period delimiters.\n" ); else - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), "Mismatched period delimiters for enumeration.\n" ); err->AppendToDetailMsg( messageBuf ); err->AppendToUserMsg( messageBuf ); @@ -242,7 +241,7 @@ Severity SDAI_LOGICAL::ReadEnum( istream & in, ErrorDescriptor * err, int Assign } else { in.putback( c ); err->GreaterSeverity( SEVERITY_WARNING ); - sprintf( messageBuf, "Invalid enumeration value.\n" ); + snprintf( messageBuf, sizeof(messageBuf), "Invalid enumeration value.\n" ); err->AppendToDetailMsg( messageBuf ); err->AppendToUserMsg( messageBuf ); } @@ -490,10 +489,10 @@ Severity SDAI_Enum::ReadEnum( istream & in, ErrorDescriptor * err, int AssignVal if( !validDelimiters ) { err->GreaterSeverity( SEVERITY_WARNING ); if( needDelims ) - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), "Enumerated value has invalid period delimiters.\n" ); else - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), "Mismatched period delimiters for enumeration.\n" ); err->AppendToDetailMsg( messageBuf ); err->AppendToUserMsg( messageBuf ); @@ -520,7 +519,7 @@ Severity SDAI_Enum::ReadEnum( istream & in, ErrorDescriptor * err, int AssignVal } else { in.putback( c ); err->GreaterSeverity( SEVERITY_WARNING ); - sprintf( messageBuf, "Invalid enumeration value.\n" ); + snprintf( messageBuf, sizeof(messageBuf), "Invalid enumeration value.\n" ); err->AppendToDetailMsg( messageBuf ); err->AppendToUserMsg( messageBuf ); } diff --git a/src/cldai/sdaiModel_contents.cc b/src/cldai/sdaiModel_contents.cc index abe0386b2..3cb0828a0 100644 --- a/src/cldai/sdaiModel_contents.cc +++ b/src/cldai/sdaiModel_contents.cc @@ -1,6 +1,5 @@ -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" ///////// SDAI_Model_contents_instances diff --git a/src/cldai/sdaiModel_contents_list.cc b/src/cldai/sdaiModel_contents_list.cc index 8f6440e8e..62197b190 100644 --- a/src/cldai/sdaiModel_contents_list.cc +++ b/src/cldai/sdaiModel_contents_list.cc @@ -23,8 +23,7 @@ /* * UArray implementation. */ -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" // to help ObjectCenter #ifndef HAVE_MEMMOVE diff --git a/src/cldai/sdaiObject.cc b/src/cldai/sdaiObject.cc index 14cf6c26a..fd930881c 100644 --- a/src/cldai/sdaiObject.cc +++ b/src/cldai/sdaiObject.cc @@ -1,5 +1,4 @@ -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" SDAI_sdaiObject::SDAI_sdaiObject() { } diff --git a/src/cldai/sdaiSession_instance.cc b/src/cldai/sdaiSession_instance.cc index 6f48be442..291c0c21b 100644 --- a/src/cldai/sdaiSession_instance.cc +++ b/src/cldai/sdaiSession_instance.cc @@ -1,5 +1,4 @@ -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" SDAI_Session_instance::SDAI_Session_instance() { } diff --git a/src/cldai/sdaiString.cc b/src/cldai/sdaiString.cc index 87f29eebd..06f94d9e6 100644 --- a/src/cldai/sdaiString.cc +++ b/src/cldai/sdaiString.cc @@ -9,9 +9,8 @@ * and is not subject to copyright. */ -#include +#include "clstepcore/sdai.h" #include -#include "sc_memmgr.h" SDAI_String::SDAI_String( const char * str, size_t max ) { if( !str ) { diff --git a/src/cleditor/CMakeLists.txt b/src/cleditor/CMakeLists.txt index 6370bcacb..2b306068e 100644 --- a/src/cleditor/CMakeLists.txt +++ b/src/cleditor/CMakeLists.txt @@ -1,5 +1,4 @@ - -set(LIBSTEPEDITOR_SRCS +set(EDITOR_SRCS STEPfile.cc STEPfile.inline.cc cmdmgr.cc @@ -9,38 +8,22 @@ set(LIBSTEPEDITOR_SRCS SdaiSchemaInit.cc ) -SET(SC_CLEDITOR_HDRS - STEPfile.h - cmdmgr.h - editordefines.h - SdaiHeaderSchema.h - SdaiHeaderSchemaClasses.h - SdaiSchemaInit.h - seeinfodefault.h - ) - include_directories( ${CMAKE_CURRENT_SOURCE_DIR} - ${SC_SOURCE_DIR}/src/base - ${SC_SOURCE_DIR}/src/cldai - ${SC_SOURCE_DIR}/src/clstepcore - ${SC_SOURCE_DIR}/src/clutils + ${CMAKE_SOURCE_DIR}/include/stepcode ) if(BUILD_SHARED_LIBS) - SC_ADDLIB(stepeditor SHARED SOURCES ${LIBSTEPEDITOR_SRCS} LINK_LIBRARIES stepcore stepdai steputils base) + SC_ADDLIB(stepeditor SHARED SOURCES ${EDITOR_SRCS} LINK_LIBRARIES stepcore stepdai steputils) if(WIN32) target_compile_definitions(stepeditor PRIVATE SC_EDITOR_DLL_EXPORTS) endif() endif() if(BUILD_STATIC_LIBS) - SC_ADDLIB(stepeditor-static STATIC SOURCES ${LIBSTEPEDITOR_SRCS} LINK_LIBRARIES stepcore-static stepdai-static steputils-static base-static) + SC_ADDLIB(stepeditor-static STATIC SOURCES ${EDITOR_SRCS} LINK_LIBRARIES stepcore-static stepdai-static steputils-static) endif() -install(FILES ${SC_CLEDITOR_HDRS} - DESTINATION ${INCLUDE_DIR}/stepcode/cleditor) - # Local Variables: # tab-width: 8 # mode: cmake diff --git a/src/cleditor/STEPfile.cc b/src/cleditor/STEPfile.cc index cb1fe5bca..7254e8935 100644 --- a/src/cleditor/STEPfile.cc +++ b/src/cleditor/STEPfile.cc @@ -24,17 +24,15 @@ #include #include -#include -#include -#include -#include -#include +#include "cleditor/STEPfile.h" +#include "clstepcore/sdai.h" +#include "clstepcore/STEPcomplex.h" +#include "clstepcore/STEPattribute.h" +#include "cleditor/SdaiHeaderSchema.h" // STEPundefined contains // void PushPastString (istream& in, std::string &s, ErrorDescriptor *err) -#include - -#include "sc_memmgr.h" +#include "clstepcore/STEPundefined.h" /** * \returns The new file name for the class. @@ -117,7 +115,7 @@ Severity STEPfile::ReadHeader( istream & in ) { int fileid; std::string keywd; char c = '\0'; - char buf [BUFSIZ]; + char buf [BUFSIZ+1]; std::string strbuf; @@ -442,7 +440,7 @@ int STEPfile::ReadData1( istream & in ) { char c; int instance_count = 0; - char buf[BUFSIZ]; + char buf[BUFSIZ+1]; buf[0] = '\0'; std::string tmpbuf; @@ -530,7 +528,7 @@ int STEPfile::ReadData1( istream & in ) { } // end while loop if( _entsNotCreated ) { - sprintf( buf, + snprintf( buf, sizeof(buf), "STEPfile Reading File: Unable to create %d instances.\n\tIn first pass through DATA section. Check for invalid entity types.\n", _entsNotCreated ); _error.AppendToUserMsg( buf ); @@ -565,7 +563,7 @@ int STEPfile::ReadData2( istream & in, bool useTechCor ) { _warningCount = 0; // reset error count char c; - char buf[BUFSIZ]; + char buf[BUFSIZ+1]; buf[0] = '\0'; std::string tmpbuf; @@ -649,7 +647,7 @@ int STEPfile::ReadData2( istream & in, bool useTechCor ) { } // end while loop if( _entsInvalid ) { - sprintf( buf, + snprintf( buf, sizeof(buf), "%s \n\tTotal instances: %d \n\tInvalid instances: %d \n\tIncomplete instances (includes invalid instances): %d \n\t%s: %d.\n", "Second pass complete - instance summary:", total_instances, _entsInvalid, _entsIncomplete, "Warnings", @@ -730,7 +728,7 @@ int STEPfile::FindDataSection( istream & in ) { } int STEPfile::FindHeaderSection( istream & in ) { - char buf[BUFSIZ]; + char buf[BUFSIZ+1]; char * b = buf; *b = '\0'; @@ -851,6 +849,8 @@ SDAI_Application_instance * STEPfile::CreateInstance( istream & in, ostream & ou << " User Defined Entity in DATA section ignored.\n" << "\tData lost: \'!" << objnm << "\': " << tmpbuf << endl; + if (scopelist) + delete[] scopelist; return ENTITY_NULL; } else { schnm = schemaName(); @@ -879,6 +879,8 @@ SDAI_Application_instance * STEPfile::CreateInstance( istream & in, ostream & ou out << "ERROR: instance #" << fileid << " \'" << objnm << "\': " << result.UserMsg() << ".\n\tData lost: " << tmpbuf << "\n\n"; + if (scopelist) + delete[] scopelist; return ENTITY_NULL; } obj -> STEPfile_id = fileid; @@ -887,6 +889,10 @@ SDAI_Application_instance * STEPfile::CreateInstance( istream & in, ostream & ou SkipInstance( in, tmpbuf ); ReadTokenSeparator( in ); + + if (scopelist) + delete[] scopelist; + return obj; } @@ -1150,7 +1156,7 @@ SDAI_Application_instance * STEPfile::ReadInstance( istream & in, ostream & out, Severity sev = SEVERITY_NULL; std::string tmpbuf; - char errbuf[BUFSIZ]; + char errbuf[BUFSIZ+1]; errbuf[0] = '\0'; std::string currSch; std::string objnm; @@ -1315,7 +1321,7 @@ SDAI_Application_instance * STEPfile::ReadInstance( istream & in, ostream & out, } } else { if( node->CurrState() == completeSE ) { - sprintf( errbuf, "WARNING in WORKING FILE: changing instance #%d state from completeSE to incompleteSE.\n", fileid ); + snprintf( errbuf, sizeof(errbuf), "WARNING in WORKING FILE: changing instance #%d state from completeSE to incompleteSE.\n", fileid ); _error.AppendToUserMsg( errbuf ); if( _fileType != WORKING_SESSION ) { node->ChangeState( incompleteSE ); @@ -1531,9 +1537,11 @@ void STEPfile::WriteHeaderInstance( SDAI_Application_instance * obj, ostream & o void STEPfile::WriteHeaderInstanceFileName( ostream & out ) { // Get the FileName instance from _headerInstances SDAI_Application_instance * se = 0; + bool del_se = false; se = _headerInstances->GetApplication_instance( "File_Name" ); if( se == ENTITY_NULL ) { se = ( SDAI_Application_instance * )HeaderDefaultFileName(); + del_se = true; } //set some of the attribute values at time of output @@ -1553,6 +1561,9 @@ void STEPfile::WriteHeaderInstanceFileName( ostream & out ) { //output the values to the file WriteHeaderInstance( se, out ); + + if (del_se) + delete se; } void STEPfile::WriteHeaderInstanceFileDescription( ostream & out ) { @@ -1563,8 +1574,11 @@ void STEPfile::WriteHeaderInstanceFileDescription( ostream & out ) { // ERROR: no File_Name instance in _headerInstances // create a File_Name instance se = ( SDAI_Application_instance * )HeaderDefaultFileDescription(); + WriteHeaderInstance(se, out); + delete se; + } else { + WriteHeaderInstance( se, out ); } - WriteHeaderInstance( se, out ); } void STEPfile::WriteHeaderInstanceFileSchema( ostream & out ) { @@ -1575,8 +1589,11 @@ void STEPfile::WriteHeaderInstanceFileSchema( ostream & out ) { // ERROR: no File_Name instance in _headerInstances // create a File_Name instance se = ( SDAI_Application_instance * ) HeaderDefaultFileSchema(); + WriteHeaderInstance( se, out ); + delete se; + } else { + WriteHeaderInstance( se, out ); } - WriteHeaderInstance( se, out ); } void STEPfile::WriteData( ostream & out, int writeComments ) { @@ -1603,7 +1620,7 @@ void STEPfile::WriteValuePairsData( ostream & out, int writeComments, int mixedC Severity STEPfile::AppendFile( istream * in, bool useTechCor ) { Severity rval = SEVERITY_NULL; - char errbuf[BUFSIZ]; + char errbuf[BUFSIZ+1]; SetFileIdIncrement(); int total_insts = 0, valid_insts = 0; @@ -1626,7 +1643,7 @@ Severity STEPfile::AppendFile( istream * in, bool useTechCor ) { } SetFileType( WORKING_SESSION ); } else { - sprintf( errbuf, + snprintf( errbuf, sizeof(errbuf), "Faulty input at beginning of file. \"ISO-10303-21;\" or" " \"STEP_WORKING_SESSION;\" expected. File not read: %s\n", ( ( FileName().compare( "-" ) == 0 ) ? "standard input" : FileName().c_str() ) ); @@ -1641,14 +1658,14 @@ Severity STEPfile::AppendFile( istream * in, bool useTechCor ) { rval = ReadHeader( *in ); cout << "\nHEADER read:"; if( rval < SEVERITY_WARNING ) { - sprintf( errbuf, + snprintf( errbuf, sizeof(errbuf), "Error: non-recoverable error in reading header section. " "There were %d errors encountered. Rest of file is ignored.\n", _errorCount ); _error.AppendToUserMsg( errbuf ); return rval; } else if( rval != SEVERITY_NULL ) { - sprintf( errbuf, " %d ERRORS\t %d WARNINGS\n\n", + snprintf( errbuf, sizeof(errbuf), " %d ERRORS\t %d WARNINGS\n\n", _errorCount, _warningCount ); cout << errbuf; } else { @@ -1666,7 +1683,7 @@ Severity STEPfile::AppendFile( istream * in, bool useTechCor ) { cout << "\nFIRST PASS complete: " << total_insts << " instances created.\n"; - sprintf( errbuf, + snprintf( errbuf, sizeof(errbuf), " %d ERRORS\t %d WARNINGS\n\n", _errorCount, _warningCount ); cout << errbuf; @@ -1710,7 +1727,7 @@ Severity STEPfile::AppendFile( istream * in, bool useTechCor ) { //check for "ENDSEC;" ReadTokenSeparator( *in2 ); if( total_insts != valid_insts ) { - sprintf( errbuf, "%d invalid instances in file: %s\n", + snprintf( errbuf, sizeof(errbuf), "%d invalid instances in file: %s\n", total_insts - valid_insts, ( ( FileName().compare( "-" ) == 0 ) ? "standard input" : FileName().c_str() ) ); _error.AppendToUserMsg( errbuf ); CloseInputFile( in2 ); @@ -1719,7 +1736,7 @@ Severity STEPfile::AppendFile( istream * in, bool useTechCor ) { cout << "\nSECOND PASS complete: " << valid_insts << " instances valid.\n"; - sprintf( errbuf, + snprintf( errbuf, sizeof(errbuf), " %d ERRORS\t %d WARNINGS\n\n", _errorCount, _warningCount ); _error.AppendToUserMsg( errbuf ); diff --git a/src/cleditor/STEPfile.inline.cc b/src/cleditor/STEPfile.inline.cc index 0c5b937e0..a34149048 100644 --- a/src/cleditor/STEPfile.inline.cc +++ b/src/cleditor/STEPfile.inline.cc @@ -11,13 +11,12 @@ * and is not subject to copyright. */ -#include -#include -#include +#include "cleditor/STEPfile.h" +#include "cleditor/SdaiHeaderSchema.h" +#include "clstepcore/STEPaggregate.h" #include #include -#include "sc_memmgr.h" extern void HeaderSchemaInit( Registry & reg ); @@ -179,8 +178,8 @@ istream * STEPfile::OpenInputFile( const std::string filename ) { return( 0 ); } else { if( SetFileName( filename ).empty() && ( filename.compare( "-" ) != 0 ) ) { - char msg[BUFSIZ]; - sprintf( msg, "Unable to find file for input: \'%s\'. File not read.\n", filename.c_str() ); + char msg[BUFSIZ+1]; + snprintf( msg, sizeof(msg), "Unable to find file for input: \'%s\'. File not read.\n", filename.c_str() ); _error.AppendToUserMsg( msg ); _error.GreaterSeverity( SEVERITY_INPUT_ERROR ); return( 0 ); @@ -196,8 +195,8 @@ istream * STEPfile::OpenInputFile( const std::string filename ) { } if( !in || !( in -> good() ) ) { - char msg[BUFSIZ]; - sprintf( msg, "Unable to open file for input: \'%s\'. File not read.\n", filename.c_str() ); + char msg[BUFSIZ+1]; + snprintf( msg, sizeof(msg), "Unable to open file for input: \'%s\'. File not read.\n", filename.c_str() ); _error.AppendToUserMsg( msg ); _error.GreaterSeverity( SEVERITY_INPUT_ERROR ); return ( 0 ); @@ -231,8 +230,8 @@ ofstream * STEPfile::OpenOutputFile( std::string filename ) { } } else { if( SetFileName( filename ).empty() ) { - char msg[BUFSIZ]; - sprintf( msg, "can't find file: %s\nFile not written.\n", filename.c_str() ); + char msg[BUFSIZ+1]; + snprintf( msg, sizeof(msg), "can't find file: %s\nFile not written.\n", filename.c_str() ); _error.AppendToUserMsg( msg ); _error.GreaterSeverity( SEVERITY_INPUT_ERROR ); } diff --git a/src/cleditor/SdaiHeaderSchema.cc b/src/cleditor/SdaiHeaderSchema.cc index cea95b42f..73212bc48 100644 --- a/src/cleditor/SdaiHeaderSchema.cc +++ b/src/cleditor/SdaiHeaderSchema.cc @@ -10,10 +10,9 @@ extern ofstream * logStream; #define SCLLOGFILE "scl.log" #endif -#include -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/STEPattribute.h" +#include "cleditor/SdaiHeaderSchema.h" Schema * s_header_section_schema = 0; diff --git a/src/cleditor/SdaiHeaderSchemaAll.cc b/src/cleditor/SdaiHeaderSchemaAll.cc index 3a469c7d3..cf88eb3aa 100644 --- a/src/cleditor/SdaiHeaderSchemaAll.cc +++ b/src/cleditor/SdaiHeaderSchemaAll.cc @@ -4,8 +4,7 @@ // it since your modifications will be lost if exp2cxx is used to // regenerate it. -#include -#include "sc_memmgr.h" +#include "cleditor/SdaiHeaderSchema.h" void HeaderInitSchemasAndEnts( Registry & reg ) { Uniqueness_rule_ptr ur; diff --git a/src/cleditor/SdaiHeaderSchemaInit.cc b/src/cleditor/SdaiHeaderSchemaInit.cc index 35099d805..32b1655d1 100644 --- a/src/cleditor/SdaiHeaderSchemaInit.cc +++ b/src/cleditor/SdaiHeaderSchemaInit.cc @@ -4,11 +4,10 @@ // it since your modifications will be lost if exp2cxx is used to // regenerate it. -#include -#include -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/Registry.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/STEPattribute.h" +#include "cleditor/SdaiHeaderSchema.h" void SdaiHEADER_SECTION_SCHEMAInit( Registry & reg ) { header_section_schemat_time_stamp_text->ReferentType( t_sdaiSTRING ); diff --git a/src/cleditor/SdaiSchemaInit.cc b/src/cleditor/SdaiSchemaInit.cc index 05790a09c..82323987a 100644 --- a/src/cleditor/SdaiSchemaInit.cc +++ b/src/cleditor/SdaiSchemaInit.cc @@ -4,8 +4,7 @@ // it since your modifications will be lost if exp2cxx is used to // regenerate it. -#include -#include "sc_memmgr.h" +#include "cleditor/SdaiSchemaInit.h" void HeaderSchemaInit( Registry & reg ) { HeaderInitSchemasAndEnts( reg ); diff --git a/src/cleditor/cmdmgr.cc b/src/cleditor/cmdmgr.cc index 7c015ce47..4b78d4f90 100644 --- a/src/cleditor/cmdmgr.cc +++ b/src/cleditor/cmdmgr.cc @@ -10,8 +10,7 @@ * and is not subject to copyright. */ -#include -#include "sc_memmgr.h" +#include "cleditor/cmdmgr.h" ReplicateLinkNode * ReplicateList::FindNode( MgrNode * mn ) { ReplicateLinkNode * rln = ( ReplicateLinkNode * )GetHead(); @@ -72,6 +71,16 @@ CmdMgr::CmdMgr() { replicateList = new ReplicateList(); } +CmdMgr::~CmdMgr() { + delete completeList; + delete incompleteList; + delete deleteList; + delete mappedWriteList; + delete mappedViewList; + delete closeList; + delete replicateList; +} + void CmdMgr::ReplicateCmdList( MgrNode * mn ) { if( !( replicateList->IsOnList( mn ) ) ) { replicateList->AddNode( mn ); diff --git a/src/cllazyfile/CMakeLists.txt b/src/cllazyfile/CMakeLists.txt index b5e763628..c56e8dbbc 100644 --- a/src/cllazyfile/CMakeLists.txt +++ b/src/cllazyfile/CMakeLists.txt @@ -1,55 +1,35 @@ - -set( clLazyFile_SRCS +set(LAZY_SRCS lazyDataSectionReader.cc lazyFileReader.cc lazyInstMgr.cc p21HeaderSectionReader.cc sectionReader.cc lazyP21DataSectionReader.cc - ) - -set( SC_CLLAZYFILE_HDRS - headerSectionReader.h - lazyFileReader.h - lazyP21DataSectionReader.h - p21HeaderSectionReader.h - lazyDataSectionReader.h - lazyInstMgr.h - lazyTypes.h - sectionReader.h - instMgrHelper.h + judy.c ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} - ${SC_SOURCE_DIR}/src/cleditor - ${SC_SOURCE_DIR}/src/cldai - ${SC_SOURCE_DIR}/src/clstepcore - ${SC_SOURCE_DIR}/src/clutils - ${SC_SOURCE_DIR}/src/base - ${SC_SOURCE_DIR}/src/base/judy/src + ${CMAKE_SOURCE_DIR}/include/stepcode ) -set(_libdeps stepcore stepdai steputils base stepeditor) +set(_libdeps stepcore stepdai steputils stepeditor) if(BUILD_SHARED_LIBS) - SC_ADDLIB(steplazyfile SHARED SOURCES ${clLazyFile_SRCS} LINK_LIBRARIES ${_libdeps}) + SC_ADDLIB(steplazyfile SHARED SOURCES ${LAZY_SRCS} LINK_LIBRARIES ${_libdeps}) if(WIN32) target_compile_definitions(steplazyfile PRIVATE SC_LAZYFILE_DLL_EXPORTS) endif() endif() if(BUILD_STATIC_LIBS) - set(_libdeps stepcore-static stepdai-static steputils-static base-static stepeditor-static) - SC_ADDLIB(steplazyfile-static STATIC SOURCES ${clLazyFile_SRCS} LINK_LIBRARIES ${_libdeps}) + set(_libdeps stepcore-static stepdai-static steputils-static stepeditor-static) + SC_ADDLIB(steplazyfile-static STATIC SOURCES ${LAZY_SRCS} LINK_LIBRARIES ${_libdeps}) endif() -SC_ADDEXEC(lazy_test SOURCES lazy_test.cc LINK_LIBRARIES steplazyfile stepeditor NO_INSTALL) +SC_ADDEXEC(lazy_test SOURCES "lazy_test.cc;sc_benchmark.cc" LINK_LIBRARIES steplazyfile stepeditor NO_INSTALL) target_compile_definitions(lazy_test PRIVATE NO_REGISTRY) -install(FILES ${SC_CLLAZYFILE_HDRS} - DESTINATION ${INCLUDE_DIR}/stepcode/cllazyfile) - # Local Variables: # tab-width: 8 # mode: cmake diff --git a/src/base/judy/src/judy.c b/src/cllazyfile/judy.c similarity index 99% rename from src/base/judy/src/judy.c rename to src/cllazyfile/judy.c index 91380cead..f3bba2b7e 100644 --- a/src/base/judy/src/judy.c +++ b/src/cllazyfile/judy.c @@ -60,7 +60,7 @@ # endif #endif -#include "judy.h" +#include "cllazyfile/judy.h" #include #include diff --git a/src/cllazyfile/lazyDataSectionReader.cc b/src/cllazyfile/lazyDataSectionReader.cc index 4b1bc1785..6de006fe4 100644 --- a/src/cllazyfile/lazyDataSectionReader.cc +++ b/src/cllazyfile/lazyDataSectionReader.cc @@ -1,6 +1,6 @@ -#include "lazyDataSectionReader.h" -#include "lazyFileReader.h" -#include "lazyInstMgr.h" +#include "cllazyfile/lazyDataSectionReader.h" +#include "cllazyfile/lazyFileReader.h" +#include "cllazyfile/lazyInstMgr.h" #include lazyDataSectionReader::lazyDataSectionReader( lazyFileReader * parent, std::ifstream & file, diff --git a/src/cllazyfile/lazyFileReader.cc b/src/cllazyfile/lazyFileReader.cc index 9cc294df0..fed35c6f5 100644 --- a/src/cllazyfile/lazyFileReader.cc +++ b/src/cllazyfile/lazyFileReader.cc @@ -1,10 +1,10 @@ #include -#include "lazyFileReader.h" -#include "lazyDataSectionReader.h" -#include "headerSectionReader.h" -#include "lazyInstMgr.h" +#include "cllazyfile/lazyFileReader.h" +#include "cllazyfile/lazyDataSectionReader.h" +#include "cllazyfile/headerSectionReader.h" +#include "cllazyfile/lazyInstMgr.h" void lazyFileReader::initP21() { _header = new p21HeaderSectionReader( this, _file, 0, -1 ); diff --git a/src/cllazyfile/lazyInstMgr.cc b/src/cllazyfile/lazyInstMgr.cc index 7ce253ee9..65f3e7558 100644 --- a/src/cllazyfile/lazyInstMgr.cc +++ b/src/cllazyfile/lazyInstMgr.cc @@ -1,12 +1,12 @@ -#include "lazyTypes.h" -#include "lazyInstMgr.h" -#include "Registry.h" -#include -#include "SdaiSchemaInit.h" -#include "instMgrHelper.h" +#include "cllazyfile/lazyTypes.h" +#include "cllazyfile/lazyInstMgr.h" +#include "clstepcore/Registry.h" +#include "clstepcore/SubSuperIterators.h" +#include "cleditor/SdaiSchemaInit.h" +#include "cllazyfile/instMgrHelper.h" #include "lazyRefs.h" -#include "sdaiApplication_instance.h" +#include "clstepcore/sdaiApplication_instance.h" lazyInstMgr::lazyInstMgr() { _headerRegistry = new Registry( HeaderSchemaInit ); diff --git a/src/cllazyfile/lazyP21DataSectionReader.cc b/src/cllazyfile/lazyP21DataSectionReader.cc index 9e9df2070..0716f5c5f 100644 --- a/src/cllazyfile/lazyP21DataSectionReader.cc +++ b/src/cllazyfile/lazyP21DataSectionReader.cc @@ -1,7 +1,7 @@ #include #include -#include "lazyP21DataSectionReader.h" -#include "lazyInstMgr.h" +#include "cllazyfile/lazyP21DataSectionReader.h" +#include "cllazyfile/lazyInstMgr.h" lazyP21DataSectionReader::lazyP21DataSectionReader( lazyFileReader * parent, std::ifstream & file, std::streampos start, sectionID sid ): @@ -49,6 +49,7 @@ const namedLazyInstance lazyP21DataSectionReader::nextInstance() { namedLazyInstance i; i.refs = 0; + i.loc.section = 0; i.loc.begin = _file.tellg(); i.loc.instance = readInstanceNumber(); if( ( _file.good() ) && ( i.loc.instance > 0 ) ) { diff --git a/src/cllazyfile/lazyRefs.h b/src/cllazyfile/lazyRefs.h index 723dd0998..b8daff295 100644 --- a/src/cllazyfile/lazyRefs.h +++ b/src/cllazyfile/lazyRefs.h @@ -7,12 +7,12 @@ #include #include "sc_export.h" -#include "lazyTypes.h" -#include "lazyInstMgr.h" -#include "ExpDict.h" -#include "SubSuperIterators.h" -#include -#include +#include "cllazyfile/lazyTypes.h" +#include "cllazyfile/lazyInstMgr.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/SubSuperIterators.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/STEPaggregate.h" #ifdef _WIN32 #define strcasecmp _strcmpi diff --git a/src/cllazyfile/lazy_test.cc b/src/cllazyfile/lazy_test.cc index 71786bb59..d5ce6081a 100644 --- a/src/cllazyfile/lazy_test.cc +++ b/src/cllazyfile/lazy_test.cc @@ -1,8 +1,7 @@ -#include "lazyInstMgr.h" -#include -#include "SdaiSchemaInit.h" -#include "sc_memmgr.h" -#include +#include "cllazyfile/lazyInstMgr.h" +#include "./sc_benchmark.h" +#include "cleditor/SdaiSchemaInit.h" +#include "config.h" #ifndef NO_REGISTRY # include "schema.h" diff --git a/src/cllazyfile/p21HeaderSectionReader.cc b/src/cllazyfile/p21HeaderSectionReader.cc index bcb78ac83..037604fc4 100644 --- a/src/cllazyfile/p21HeaderSectionReader.cc +++ b/src/cllazyfile/p21HeaderSectionReader.cc @@ -1,11 +1,11 @@ #include #include -#include "p21HeaderSectionReader.h" -#include "headerSectionReader.h" -#include "sectionReader.h" -#include "lazyInstMgr.h" -#include "judyL2Array.h" +#include "cllazyfile/p21HeaderSectionReader.h" +#include "cllazyfile/headerSectionReader.h" +#include "cllazyfile/sectionReader.h" +#include "cllazyfile/lazyInstMgr.h" +#include "cllazyfile/judyL2Array.h" void p21HeaderSectionReader::findSectionStart() { @@ -33,6 +33,7 @@ const namedLazyInstance p21HeaderSectionReader::nextInstance() { namedLazyInstance i; static instanceID nextFreeInstance = 4; // 1-3 are reserved per 10303-21 + i.refs = 0; i.loc.begin = _file.tellg(); i.loc.section = _sectionID; skipWS(); diff --git a/src/base/sc_benchmark.cc b/src/cllazyfile/sc_benchmark.cc similarity index 99% rename from src/base/sc_benchmark.cc rename to src/cllazyfile/sc_benchmark.cc index 44f085f2f..2f00cd5a4 100644 --- a/src/base/sc_benchmark.cc +++ b/src/cllazyfile/sc_benchmark.cc @@ -1,7 +1,6 @@ /// \file sc_benchmark.cc memory info, timers, etc for benchmarking -#include "sc_benchmark.h" -#include "sc_memmgr.h" +#include "./sc_benchmark.h" #ifdef _WIN32 #include diff --git a/src/base/sc_benchmark.h b/src/cllazyfile/sc_benchmark.h similarity index 93% rename from src/base/sc_benchmark.h rename to src/cllazyfile/sc_benchmark.h index 8512bd892..5b77317c4 100644 --- a/src/base/sc_benchmark.h +++ b/src/cllazyfile/sc_benchmark.h @@ -2,14 +2,11 @@ #define SC_BENCHMARK_H /// \file sc_benchmark.h memory info, timers, etc for benchmarking -#include "sc_export.h" - #ifdef __cplusplus #include #include #include -#include "sc_memmgr.h" extern "C" { #endif @@ -23,7 +20,7 @@ extern "C" { * * not yet implemented for OSX or Windows. */ - SC_BASE_EXPORT benchVals getMemAndTime( ); + benchVals getMemAndTime( ); #ifdef __cplusplus } @@ -39,7 +36,7 @@ extern "C" { * depends on getMemAndTime() above - may not work on all platforms. */ -class SC_BASE_EXPORT benchmark { +class benchmark { protected: benchVals initialVals, laterVals; #ifdef _MSC_VER diff --git a/src/cllazyfile/sectionReader.cc b/src/cllazyfile/sectionReader.cc index 0384efd4c..bfa8a2a12 100644 --- a/src/cllazyfile/sectionReader.cc +++ b/src/cllazyfile/sectionReader.cc @@ -5,18 +5,23 @@ #include #include #include +#include -#include "Registry.h" -#include "sc_strtoull.h" -#include "sdaiApplication_instance.h" -#include "read_func.h" -#include "SdaiSchemaInit.h" -#include "STEPcomplex.h" +#ifdef _WIN32 +# define strtoull _strtoui64 +# define ULLONG_MAX _UI64_MAX +#endif -#include "sectionReader.h" -#include "lazyFileReader.h" -#include "lazyInstMgr.h" -#include "lazyTypes.h" +#include "clstepcore/Registry.h" +#include "clstepcore/sdaiApplication_instance.h" +#include "clstepcore/read_func.h" +#include "cleditor/SdaiSchemaInit.h" +#include "clstepcore/STEPcomplex.h" + +#include "cllazyfile/sectionReader.h" +#include "cllazyfile/lazyFileReader.h" +#include "cllazyfile/lazyInstMgr.h" +#include "cllazyfile/lazyTypes.h" #include "current_function.hpp" @@ -26,11 +31,14 @@ sectionReader::sectionReader( lazyFileReader * parent, std::ifstream & file, std _error = new ErrorDescriptor(); } +sectionReader::~sectionReader() { + delete _error; +} std::streampos sectionReader::findNormalString( const std::string & str, bool semicolon ) { std::streampos found = -1, startPos = _file.tellg(), nextTry = startPos; int i = 0, l = str.length(); - char c; + int c; //i is reset every time a character doesn't match; if i == l, this means that we've found the entire string while( i < l || semicolon ) { @@ -84,7 +92,7 @@ std::streampos sectionReader::findNormalString( const std::string & str, bool se // returns pointer to the contents of a static std::string const char * sectionReader::getDelimitedKeyword( const char * delimiters ) { static std::string str; - char c; + int c; str.clear(); str.reserve( 100 ); skipWS(); @@ -114,7 +122,7 @@ const char * sectionReader::getDelimitedKeyword( const char * delimiters ) { /// be the opening parenthesis; otherwise, it is likely to fail. ///NOTE *must* check return value! std::streampos sectionReader::seekInstanceEnd( instanceRefs ** refs ) { - char c; + int c; int parenDepth = 0; while( c = _file.get(), _file.good() ) { switch( c ) { @@ -176,7 +184,7 @@ void sectionReader::locateAllInstances() { } instanceID sectionReader::readInstanceNumber() { - char c; + int c; size_t digits = 0; instanceID id = 0; @@ -221,7 +229,7 @@ instanceID sectionReader::readInstanceNumber() { _error->UserMsg( "A very large instance ID encountered" ); _error->DetailMsg( errorMsg.str() ); - delete buffer; + delete[] buffer; return 0; } @@ -251,7 +259,7 @@ instanceID sectionReader::readInstanceNumber() { */ SDAI_Application_instance * sectionReader::getRealInstance( const Registry * reg, long int begin, instanceID instance, const std::string & typeName, const std::string & schName, bool header ) { - char c; + int c; const char * tName = 0, * sName = 0; //these are necessary since typeName and schName are const std::string comment; Severity sev = SEVERITY_NULL; diff --git a/src/clstepcore/CMakeLists.txt b/src/clstepcore/CMakeLists.txt index 910235973..e31f8ad8e 100644 --- a/src/clstepcore/CMakeLists.txt +++ b/src/clstepcore/CMakeLists.txt @@ -1,5 +1,4 @@ - -set(LIBSTEPCORE_SRCS +set(CORE_SRCS aggrTypeDescriptor.cc attrDescriptor.cc attrDescriptorList.cc @@ -62,91 +61,24 @@ set(LIBSTEPCORE_SRCS whereRule.cc ) -set(SC_CLSTEPCORE_HDRS - aggrTypeDescriptor.h - attrDescriptor.h - attrDescriptorList.h - baseType.h - complexSupport.h - create_Aggr.h - derivedAttribute.h - dictSchema.h - dictdefs.h - dictionaryInstance.h - dispnode.h - dispnodelist.h - entityDescriptor.h - entityDescriptorList.h - enumTypeDescriptor.h - ExpDict.h - explicitItemId.h - globalRule.h - implicitItemId.h - instmgr.h - interfaceSpec.h - interfacedItem.h - inverseAttribute.h - inverseAttributeList.h - mgrnode.h - mgrnodearray.h - mgrnodelist.h - needFunc.h - read_func.h - realTypeDescriptor.h - Registry.h - schRename.h - sdai.h - sdaiApplication_instance.h - sdaiSelect.h - selectTypeDescriptor.h - SingleLinkList.h - STEPaggregate.h - STEPaggrBinary.h - STEPaggrEntity.h - STEPaggrEnum.h - STEPaggrGeneric.h - STEPaggrInt.h - STEPaggrReal.h - STEPaggrSelect.h - STEPaggrString.h - STEPattribute.h - STEPattributeList.h - STEPcomplex.h - STEPinvAttrList.h - STEPundefined.h - stringTypeDescriptor.h - SubSuperIterators.h - typeDescriptor.h - typeDescriptorList.h - typeOrRuleVar.h - uniquenessRule.h - whereRule.h -) - include_directories( ${CMAKE_CURRENT_SOURCE_DIR} - ${SC_SOURCE_DIR}/src/base - ${SC_SOURCE_DIR}/src/cldai - ${SC_SOURCE_DIR}/src/cleditor - ${SC_SOURCE_DIR}/src/clutils + ${CMAKE_SOURCE_DIR}/include/stepcode ) -set(_libdeps steputils stepdai base) +set(_libdeps steputils stepdai) if(BUILD_SHARED_LIBS) - SC_ADDLIB(stepcore SHARED SOURCES ${LIBSTEPCORE_SRCS} LINK_LIBRARIES ${_libdeps}) + SC_ADDLIB(stepcore SHARED SOURCES ${CORE_SRCS} LINK_LIBRARIES ${_libdeps}) if(WIN32) target_compile_definitions(stepcore PRIVATE SC_CORE_DLL_EXPORTS) endif() endif() if(BUILD_STATIC_LIBS) - SC_ADDLIB(stepcore-static STATIC SOURCES ${LIBSTEPCORE_SRCS} LINK_LIBRARIES $-static) + SC_ADDLIB(stepcore-static STATIC SOURCES ${CORE_SRCS} LINK_LIBRARIES $-static) endif() -install(FILES ${SC_CLSTEPCORE_HDRS} - DESTINATION ${INCLUDE_DIR}/stepcode/clstepcore) - if(SC_ENABLE_TESTING) add_subdirectory(test) endif(SC_ENABLE_TESTING) diff --git a/src/clstepcore/Registry.cc b/src/clstepcore/Registry.cc index 2e5eb490f..9eeb975e0 100644 --- a/src/clstepcore/Registry.cc +++ b/src/clstepcore/Registry.cc @@ -9,9 +9,8 @@ * and is not subject to copyright. */ -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/Registry.h" /* these may be shared between multiple Registry instances, so don't create/destroy in Registry ctor/dtor * Name, FundamentalType, Originating Schema, Description */ @@ -79,7 +78,7 @@ void Registry::DeleteContents() { const EntityDescriptor * Registry::FindEntity( const char * e, const char * schNm, int check_case ) const { const EntityDescriptor * entd; const SchRename * altlist; - char schformat[BUFSIZ], altName[BUFSIZ]; + char schformat[BUFSIZ+1], altName[BUFSIZ+1]; if( check_case ) { entd = ( EntityDescriptor * )SC_HASHfind( primordialSwamp, ( char * )e ); @@ -235,13 +234,13 @@ void Registry::RemoveType( const char * n ) { */ void Registry::RemoveClones( const EntityDescriptor & e ) { const SchRename * alts = e.AltNameList(); - struct Element * tmp; while( alts ) { - tmp = new Element; + struct Element * tmp = new Element; tmp->key = ( char * ) alts->objName(); SC_HASHsearch( primordialSwamp, tmp, HASH_DELETE ); alts = alts->next; + delete tmp; } } diff --git a/src/clstepcore/STEPaggrBinary.cc b/src/clstepcore/STEPaggrBinary.cc index fd7302748..f1170926c 100644 --- a/src/clstepcore/STEPaggrBinary.cc +++ b/src/clstepcore/STEPaggrBinary.cc @@ -1,4 +1,4 @@ -#include "STEPaggrBinary.h" +#include "clstepcore/STEPaggrBinary.h" #include /** \file STEPaggrBinary.cc diff --git a/src/clstepcore/STEPaggrEntity.cc b/src/clstepcore/STEPaggrEntity.cc index bda8f6db5..a29150873 100644 --- a/src/clstepcore/STEPaggrEntity.cc +++ b/src/clstepcore/STEPaggrEntity.cc @@ -1,6 +1,6 @@ -#include "STEPaggrEntity.h" -#include "STEPattribute.h" -#include "typeDescriptor.h" +#include "clstepcore/STEPaggrEntity.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/typeDescriptor.h" #include /** \file STEPaggrEntity.cc @@ -21,9 +21,10 @@ Severity EntityAggregate::ReadValue( istream & in, ErrorDescriptor * err, int addFileId, int assignVal, int exchangeFileFormat, const char * ) { ErrorDescriptor errdesc; - char errmsg[BUFSIZ]; + char errmsg[BUFSIZ+1]; int value_cnt = 0; std::string buf; + bool free_item = false; if( assignVal ) { Empty(); // read new values and discard existing ones @@ -67,6 +68,7 @@ Severity EntityAggregate::ReadValue( istream & in, ErrorDescriptor * err, // It is used to read the values else if( !assignVal ) { item = new EntityNode(); + free_item = true; } while( in.good() && ( c != ')' ) ) { @@ -89,7 +91,7 @@ Severity EntityAggregate::ReadValue( istream & in, ErrorDescriptor * err, CheckRemainingInput( in, &errdesc, buf, ",)" ); if( errdesc.severity() < SEVERITY_INCOMPLETE ) { - sprintf( errmsg, " index: %d\n", value_cnt ); + snprintf( errmsg, sizeof(errmsg), " index: %d\n", value_cnt ); errdesc.PrependToDetailMsg( errmsg ); err->AppendFromErrorArg( &errdesc ); } @@ -114,8 +116,12 @@ Severity EntityAggregate::ReadValue( istream & in, ErrorDescriptor * err, } else { // expectation for end paren delim has not been met err->GreaterSeverity( SEVERITY_INPUT_ERROR ); err->AppendToUserMsg( "Missing close paren for aggregate value" ); + if (free_item) + delete item; return SEVERITY_INPUT_ERROR; } + if (free_item) + delete item; return err->severity(); } @@ -215,7 +221,7 @@ const char * EntityNode::asStr( std::string & s ) { return ""; } else { // otherwise return entity id char tmp [64]; - sprintf( tmp, "#%d", node->STEPfile_id ); + snprintf( tmp, sizeof(tmp), "#%d", node->STEPfile_id ); s = tmp; } return const_cast( s.c_str() ); diff --git a/src/clstepcore/STEPaggrEnum.cc b/src/clstepcore/STEPaggrEnum.cc index 41b77aa21..01ac21e4a 100644 --- a/src/clstepcore/STEPaggrEnum.cc +++ b/src/clstepcore/STEPaggrEnum.cc @@ -1,4 +1,4 @@ -#include "STEPaggrEnum.h" +#include "clstepcore/STEPaggrEnum.h" #include /** \file StepaggrEnum.cc diff --git a/src/clstepcore/STEPaggrGeneric.cc b/src/clstepcore/STEPaggrGeneric.cc index 899d6c656..5db812b27 100644 --- a/src/clstepcore/STEPaggrGeneric.cc +++ b/src/clstepcore/STEPaggrGeneric.cc @@ -1,4 +1,4 @@ -#include "STEPaggrGeneric.h" +#include "clstepcore/STEPaggrGeneric.h" #include /** \file STEPaggrGeneric.cc diff --git a/src/clstepcore/STEPaggrInt.cc b/src/clstepcore/STEPaggrInt.cc index 2e61a1504..7d9e86884 100644 --- a/src/clstepcore/STEPaggrInt.cc +++ b/src/clstepcore/STEPaggrInt.cc @@ -1,4 +1,4 @@ -#include "STEPaggrInt.h" +#include "clstepcore/STEPaggrInt.h" IntAggregate::IntAggregate() { @@ -94,9 +94,9 @@ const char * IntNode::asStr( std::string & s ) { } const char * IntNode::STEPwrite( std::string & s, const char * ) { - char tmp[BUFSIZ]; + char tmp[BUFSIZ+1]; if( value != S_INT_NULL ) { - sprintf( tmp, "%ld", value ); + snprintf( tmp, sizeof(tmp), "%ld", value ); s = tmp; } else { s.clear(); diff --git a/src/clstepcore/STEPaggrReal.cc b/src/clstepcore/STEPaggrReal.cc index 7d05c1333..96ae53406 100644 --- a/src/clstepcore/STEPaggrReal.cc +++ b/src/clstepcore/STEPaggrReal.cc @@ -1,4 +1,4 @@ -#include "STEPaggrReal.h" +#include "clstepcore/STEPaggrReal.h" /** \file STEPaggrReal.cc * implementation of classes RealAggregate and RealNode diff --git a/src/clstepcore/STEPaggrSelect.cc b/src/clstepcore/STEPaggrSelect.cc index 02970479c..5047e8bf3 100644 --- a/src/clstepcore/STEPaggrSelect.cc +++ b/src/clstepcore/STEPaggrSelect.cc @@ -1,5 +1,5 @@ -#include "STEPaggrSelect.h" -#include "typeDescriptor.h" +#include "clstepcore/STEPaggrSelect.h" +#include "clstepcore/typeDescriptor.h" #include /** \file STEPaggrSelect.cc @@ -19,7 +19,7 @@ Severity SelectAggregate::ReadValue( istream & in, ErrorDescriptor * err, int addFileId, int assignVal, int exchangeFileFormat, const char * currSch ) { ErrorDescriptor errdesc; - char errmsg[BUFSIZ]; + char errmsg[BUFSIZ+1]; int value_cnt = 0; std::string buf; @@ -87,7 +87,7 @@ Severity SelectAggregate::ReadValue( istream & in, ErrorDescriptor * err, CheckRemainingInput( in, &errdesc, buf, ",)" ); if( errdesc.severity() < SEVERITY_INCOMPLETE ) { - sprintf( errmsg, " index: %d\n", value_cnt ); + snprintf( errmsg, sizeof(errmsg), " index: %d\n", value_cnt ); errdesc.PrependToDetailMsg( errmsg ); err->AppendFromErrorArg( &errdesc ); } diff --git a/src/clstepcore/STEPaggrString.cc b/src/clstepcore/STEPaggrString.cc index fd9285ad3..1aaf752e1 100644 --- a/src/clstepcore/STEPaggrString.cc +++ b/src/clstepcore/STEPaggrString.cc @@ -1,4 +1,4 @@ -#include "STEPaggrString.h" +#include "clstepcore/STEPaggrString.h" #include /** \file STEPaggrString.cc diff --git a/src/clstepcore/STEPaggregate.cc b/src/clstepcore/STEPaggregate.cc index db3bbf819..ef08778a4 100644 --- a/src/clstepcore/STEPaggregate.cc +++ b/src/clstepcore/STEPaggregate.cc @@ -12,12 +12,11 @@ #include -#include -#include -#include -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/read_func.h" +#include "clstepcore/STEPaggregate.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/instmgr.h" +#include "clstepcore/ExpDict.h" /** @@ -106,7 +105,7 @@ Severity STEPaggregate::ReadValue( istream & in, ErrorDescriptor * err, (void) addFileId; //not used in ReadValue() for this class ErrorDescriptor errdesc; - char errmsg[BUFSIZ]; + char errmsg[BUFSIZ+1]; int value_cnt = 0; std::string buf; @@ -175,7 +174,7 @@ Severity STEPaggregate::ReadValue( istream & in, ErrorDescriptor * err, CheckRemainingInput( in, &errdesc, buf, ",)" ); if( errdesc.severity() < SEVERITY_INCOMPLETE ) { - sprintf( errmsg, " index: %d\n", value_cnt ); + snprintf( errmsg, sizeof(errmsg), " index: %d\n", value_cnt ); errdesc.PrependToDetailMsg( errmsg ); err->AppendFromErrorArg( &errdesc ); } diff --git a/src/clstepcore/STEPattribute.cc b/src/clstepcore/STEPattribute.cc index e25409dec..487865687 100644 --- a/src/clstepcore/STEPattribute.cc +++ b/src/clstepcore/STEPattribute.cc @@ -12,14 +12,13 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/read_func.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/instmgr.h" +#include "clstepcore/STEPundefined.h" +#include "clstepcore/STEPaggregate.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/sdai.h" // REAL_NUM_PRECISION is defined in STEPattribute.h, and is also used // in aggregate real handling (STEPaggregate.cc) -- IMS 6 Jun 95 @@ -1263,20 +1262,20 @@ ostream & operator<< ( ostream & out, STEPattribute & a ) { * value. ******************************************************************/ void STEPattribute::AddErrorInfo() { - char errStr[BUFSIZ]; + char errStr[BUFSIZ+1]; errStr[0] = '\0'; if( SEVERITY_INPUT_ERROR < _error.severity() && _error.severity() < SEVERITY_NULL ) { - sprintf( errStr, " Warning: ATTRIBUTE '%s : %s : %d' - ", - Name(), TypeName(), Type() ); + snprintf( errStr, sizeof(errStr), " Warning: ATTRIBUTE '%s : %s : %d' - ", + Name(), TypeName().c_str(), Type() ); _error.PrependToDetailMsg( errStr ); } else if( _error.severity() == SEVERITY_INPUT_ERROR ) { - sprintf( errStr, " Error: ATTRIBUTE '%s : %s : %d' - ", - Name(), TypeName(), Type() ); + snprintf( errStr, sizeof(errStr), " Error: ATTRIBUTE '%s : %s : %d' - ", + Name(), TypeName().c_str(), Type() ); _error.PrependToDetailMsg( errStr ); } else if( _error.severity() <= SEVERITY_BUG ) { - sprintf( errStr, " BUG: ATTRIBUTE '%s : %s : %d' - ", - Name(), TypeName(), Type() ); + snprintf( errStr, sizeof(errStr), " BUG: ATTRIBUTE '%s : %s : %d' - ", + Name(), TypeName().c_str(), Type() ); _error.PrependToDetailMsg( errStr ); } } @@ -1293,7 +1292,7 @@ char STEPattribute::SkipBadAttr( istream & in, char * StopChars ) { // read bad data until end of this attribute or entity. char * foundCh = 0; char c = '\0'; - char errStr[BUFSIZ]; + char errStr[BUFSIZ+1]; errStr[0] = '\0'; _error.GreaterSeverity( SEVERITY_WARNING ); @@ -1303,13 +1302,13 @@ char STEPattribute::SkipBadAttr( istream & in, char * StopChars ) { } if( in.eof() ) { _error.GreaterSeverity( SEVERITY_INPUT_ERROR ); - sprintf( errStr, " Error: attribute '%s : %s : %d' - %s.\n", - Name(), TypeName(), Type(), + snprintf( errStr, sizeof(errStr), " Error: attribute '%s : %s : %d' - %s.\n", + Name(), TypeName().c_str(), Type(), "Unexpected EOF when skipping bad attr value" ); _error.AppendToDetailMsg( errStr ); } else { - sprintf( errStr, " Error: attribute '%s : %s : %d' - %s.\n", - Name(), TypeName(), Type(), "Invalid value" ); + snprintf( errStr, sizeof(errStr), " Error: attribute '%s : %s : %d' - %s.\n", + Name(), TypeName().c_str(), Type(), "Invalid value" ); _error.AppendToDetailMsg( errStr ); } in.putback( c ); @@ -1465,11 +1464,11 @@ const char * STEPattribute::Name() const { return aDesc->Name(); } -const char * STEPattribute::TypeName() const { +std::string STEPattribute::TypeName() const { if( _redefAttr ) { return _redefAttr->TypeName(); } - return aDesc->TypeName().c_str(); + return aDesc->TypeName(); } BASE_TYPE STEPattribute::Type() const { diff --git a/src/clstepcore/STEPattributeList.cc b/src/clstepcore/STEPattributeList.cc index 7774321b2..2fce6592b 100644 --- a/src/clstepcore/STEPattributeList.cc +++ b/src/clstepcore/STEPattributeList.cc @@ -10,9 +10,8 @@ * and is not subject to copyright. */ -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/STEPattributeList.h" +#include "clstepcore/STEPattribute.h" AttrListNode::AttrListNode( STEPattribute * a ) { attr = a; @@ -42,10 +41,14 @@ STEPattribute & STEPattributeList::operator []( int n ) { return *( a->attr ); } - // else + // else - error case: return a static error object to avoid undefined behavior + // The error object allows calling code to detect the error condition + static STEPattribute errorAttr; cerr << "\nERROR in STEP Core library: " << __FILE__ << ":" << __LINE__ << "\n" << _POC_ << "\n\n"; - return *( STEPattribute * ) 0; + errorAttr.Error().AppendToDetailMsg( "STEPattributeList::operator[] - index out of bounds" ); + errorAttr.Error().severity( SEVERITY_BUG ); + return errorAttr; } int STEPattributeList::list_length() { diff --git a/src/clstepcore/STEPcomplex.cc b/src/clstepcore/STEPcomplex.cc index 5daf31ab7..719ffb1c4 100644 --- a/src/clstepcore/STEPcomplex.cc +++ b/src/clstepcore/STEPcomplex.cc @@ -1,12 +1,11 @@ #include -#include -#include -#include -#include +#include "clstepcore/STEPcomplex.h" +#include "clstepcore/complexSupport.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/STEPaggregate.h" #include -#include "sc_memmgr.h" extern const char * ReadStdKeyword( istream & in, std::string & buf, int skipInitWS ); @@ -20,7 +19,7 @@ STEPcomplex::STEPcomplex( Registry * registry, int fileid ) STEPcomplex::STEPcomplex( Registry * registry, const std::string ** names, int fileid, const char * schnm ) : SDAI_Application_instance( fileid, true ), sc( 0 ), _registry( registry ), visited( 0 ) { - char * nms[BUFSIZ]; + char * nms[BUFSIZ+1]; int j, k; head = this; @@ -61,7 +60,7 @@ void STEPcomplex::Initialize( const char ** names, const char * schnm ) { EntNode * ents = new EntNode( names ), *eptr = ents, *prev = NULL, *enext; const EntityDescriptor * enDesc; - char nm[BUFSIZ]; + char nm[BUFSIZ+1]; bool invalid = false, outOfOrder = false; // Splice out the invalid names from our list: @@ -659,10 +658,10 @@ const char * STEPcomplex::WriteExtMapEntities( std::string & buf, const char * c void STEPcomplex::CopyAs( SDAI_Application_instance * se ) { if( !se->IsComplex() ) { - char errStr[BUFSIZ]; + char errStr[BUFSIZ+1]; cerr << "STEPcomplex::CopyAs() called with non-complex entity: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; - sprintf( errStr, + snprintf( errStr, sizeof(errStr), "STEPcomplex::CopyAs(): %s - entity #%d.\n", "Programming ERROR - called with non-complex entity", STEPfile_id ); @@ -700,10 +699,10 @@ SDAI_Application_instance * STEPcomplex::Replicate() { } nameList[i] = ( std::string * )0; if( i == 63 ) { - char errStr[BUFSIZ]; + char errStr[BUFSIZ+1]; cerr << "STEPcomplex::Replicate() name buffer too small: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; - sprintf( errStr, + snprintf( errStr, sizeof(errStr), "STEPcomplex::Replicate(): %s - entity #%d.\n", "Programming ERROR - name buffer too small", STEPfile_id ); diff --git a/src/clstepcore/STEPinvAttrList.cc b/src/clstepcore/STEPinvAttrList.cc index 52bdf1ee5..3eaa9d352 100644 --- a/src/clstepcore/STEPinvAttrList.cc +++ b/src/clstepcore/STEPinvAttrList.cc @@ -3,9 +3,8 @@ * derived from STEPattributeList.cc */ -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/STEPinvAttrList.h" +#include "clstepcore/ExpDict.h" invAttrListNodeI::invAttrListNodeI(Inverse_attribute* a, setterI_t s, getterI_t g): invAttrListNode(a), set( s ), get( g ) {} invAttrListNodeA::invAttrListNodeA(Inverse_attribute* a, setterA_t s, getterA_t g): invAttrListNode(a), set( s ), get( g ) {} diff --git a/src/clstepcore/STEPundefined.cc b/src/clstepcore/STEPundefined.cc index 6ca378099..19c63f37d 100644 --- a/src/clstepcore/STEPundefined.cc +++ b/src/clstepcore/STEPundefined.cc @@ -11,9 +11,8 @@ */ #include // to get the BUFSIZ #define -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/STEPundefined.h" /** \class SCLundefined ** helper functions for reading unknown types diff --git a/src/clstepcore/SingleLinkList.cc b/src/clstepcore/SingleLinkList.cc index b13e2061d..19a1f82e7 100644 --- a/src/clstepcore/SingleLinkList.cc +++ b/src/clstepcore/SingleLinkList.cc @@ -10,8 +10,7 @@ * and is not subject to copyright. */ -#include -#include "sc_memmgr.h" +#include "clstepcore/SingleLinkList.h" #include @@ -95,7 +94,7 @@ void SingleLinkList::AppendNode( SingleLinkNode * item ) { } void SingleLinkList::DeleteNode( SingleLinkNode * item ) { - if( head ) { + if( head && item ) { SingleLinkNode * trailer = 0; SingleLinkNode * leader = head; while( leader ) { @@ -111,6 +110,7 @@ void SingleLinkList::DeleteNode( SingleLinkNode * item ) { tail = trailer; } delete item; + return; } else { if( trailer ) { trailer = trailer->NextNode(); diff --git a/src/clstepcore/aggrTypeDescriptor.cc b/src/clstepcore/aggrTypeDescriptor.cc index 91bed40be..b61b08f72 100644 --- a/src/clstepcore/aggrTypeDescriptor.cc +++ b/src/clstepcore/aggrTypeDescriptor.cc @@ -1,4 +1,4 @@ -#include "aggrTypeDescriptor.h" +#include "clstepcore/aggrTypeDescriptor.h" STEPaggregate * AggrTypeDescriptor::CreateAggregate() { if( CreateNewAggr ) { diff --git a/src/clstepcore/attrDescriptor.cc b/src/clstepcore/attrDescriptor.cc index 329d90393..a6a71b65a 100644 --- a/src/clstepcore/attrDescriptor.cc +++ b/src/clstepcore/attrDescriptor.cc @@ -1,4 +1,4 @@ -#include "attrDescriptor.h" +#include "clstepcore/attrDescriptor.h" AttrDescriptor::AttrDescriptor( const char * name, const TypeDescriptor * domainType, Logical optional, Logical unique, AttrType_Enum at, diff --git a/src/clstepcore/attrDescriptorList.cc b/src/clstepcore/attrDescriptorList.cc index c197ac5e2..903180c5b 100644 --- a/src/clstepcore/attrDescriptorList.cc +++ b/src/clstepcore/attrDescriptorList.cc @@ -1,6 +1,6 @@ -#include "attrDescriptorList.h" +#include "clstepcore/attrDescriptorList.h" -#include "attrDescriptor.h" +#include "clstepcore/attrDescriptor.h" AttrDescriptorList::AttrDescriptorList() { } diff --git a/src/clstepcore/collect.cc b/src/clstepcore/collect.cc index b6abef73c..7a952f556 100644 --- a/src/clstepcore/collect.cc +++ b/src/clstepcore/collect.cc @@ -11,8 +11,7 @@ * Date: 11/14/96 * *****************************************************************************/ -#include "complexSupport.h" -#include "sc_memmgr.h" +#include "clstepcore/complexSupport.h" /** * Inserts a new ComplexList to our list. The ComplexLists are ordered by diff --git a/src/clstepcore/complexlist.cc b/src/clstepcore/complexlist.cc index 2fc289381..3dcdff482 100644 --- a/src/clstepcore/complexlist.cc +++ b/src/clstepcore/complexlist.cc @@ -10,8 +10,7 @@ * Date: 01/07/97 * *****************************************************************************/ -#include "complexSupport.h" -#include "sc_memmgr.h" +#include "clstepcore/complexSupport.h" /** * Destructor for ComplexList. diff --git a/src/clstepcore/create_Aggr.cc b/src/clstepcore/create_Aggr.cc index 72f6adb53..e71cfbc86 100644 --- a/src/clstepcore/create_Aggr.cc +++ b/src/clstepcore/create_Aggr.cc @@ -1,5 +1,5 @@ -#include "create_Aggr.h" -#include +#include "clstepcore/create_Aggr.h" +#include "clstepcore/STEPaggregate.h" EnumAggregate * create_EnumAggregate() { return new EnumAggregate; diff --git a/src/clstepcore/derivedAttribute.cc b/src/clstepcore/derivedAttribute.cc index 7fca3b16f..8d21b0884 100644 --- a/src/clstepcore/derivedAttribute.cc +++ b/src/clstepcore/derivedAttribute.cc @@ -1,4 +1,4 @@ -#include "derivedAttribute.h" +#include "clstepcore/derivedAttribute.h" Derived_attribute::Derived_attribute( const char * name, const TypeDescriptor * domainType, Logical optional, Logical unique, AttrType_Enum at, const EntityDescriptor & owner ) diff --git a/src/clstepcore/dictSchema.cc b/src/clstepcore/dictSchema.cc index 11170d4df..aa87b4586 100644 --- a/src/clstepcore/dictSchema.cc +++ b/src/clstepcore/dictSchema.cc @@ -1,7 +1,7 @@ -#include "dictSchema.h" +#include "clstepcore/dictSchema.h" -#include "typeDescriptor.h" -#include "entityDescriptor.h" +#include "clstepcore/typeDescriptor.h" +#include "clstepcore/entityDescriptor.h" Schema::Schema( const char * schemaName ) : _use_interface_list( new Interface_spec__set ), diff --git a/src/clstepcore/dispnode.cc b/src/clstepcore/dispnode.cc index 2590e034c..15f249d37 100644 --- a/src/clstepcore/dispnode.cc +++ b/src/clstepcore/dispnode.cc @@ -12,13 +12,12 @@ /* $Id: dispnode.cc,v 3.0.1.2 1997/11/05 22:11:39 sauderd DP3.1 $ */ -#include -#include +#include "clutils/gennode.h" +#include "clutils/gennodelist.h" //#include -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/dispnode.h" +#include "clstepcore/dispnodelist.h" // define this to be the name of the display object class StepEntityEditor; diff --git a/src/clstepcore/dispnodelist.cc b/src/clstepcore/dispnodelist.cc index f4d00a6aa..7fbd788c3 100644 --- a/src/clstepcore/dispnodelist.cc +++ b/src/clstepcore/dispnodelist.cc @@ -12,14 +12,13 @@ /* $Id: dispnodelist.cc,v 3.0.1.2 1997/11/05 22:11:40 sauderd DP3.1 $ */ -#include -#include - -#include -#include -#include -#include -#include "sc_memmgr.h" +#include "clutils/gennode.h" +#include "clutils/gennodelist.h" + +#include "clstepcore/mgrnode.h" +#include "clstepcore/mgrnodelist.h" +#include "clstepcore/dispnode.h" +#include "clstepcore/dispnodelist.h" void DisplayNodeList::Remove( GenericNode * node ) { GenNodeList::Remove( node ); diff --git a/src/clstepcore/entityDescriptor.cc b/src/clstepcore/entityDescriptor.cc index 0e58c4db6..764d77066 100644 --- a/src/clstepcore/entityDescriptor.cc +++ b/src/clstepcore/entityDescriptor.cc @@ -1,10 +1,10 @@ #include -#include "entityDescriptor.h" -#include "Registry.h" -#include "attrDescriptor.h" -#include "inverseAttribute.h" -#include "SubSuperIterators.h" +#include "clstepcore/entityDescriptor.h" +#include "clstepcore/Registry.h" +#include "clstepcore/attrDescriptor.h" +#include "clstepcore/inverseAttribute.h" +#include "clstepcore/SubSuperIterators.h" EntityDescriptor::EntityDescriptor( ) : _abstractEntity( LUnknown ), _extMapping( LUnknown ), diff --git a/src/clstepcore/entityDescriptorList.cc b/src/clstepcore/entityDescriptorList.cc index 86d937c76..e23baeabb 100644 --- a/src/clstepcore/entityDescriptorList.cc +++ b/src/clstepcore/entityDescriptorList.cc @@ -1,4 +1,4 @@ -#include "entityDescriptorList.h" +#include "clstepcore/entityDescriptorList.h" EntityDescLinkNode::EntityDescLinkNode() { _entityDesc = 0; diff --git a/src/clstepcore/entlist.cc b/src/clstepcore/entlist.cc index 0dd35803a..e7c0d7c89 100644 --- a/src/clstepcore/entlist.cc +++ b/src/clstepcore/entlist.cc @@ -13,8 +13,7 @@ * Date: 9/18/96 * *****************************************************************************/ -#include "complexSupport.h" -#include "sc_memmgr.h" +#include "clstepcore/complexSupport.h" /** * Returns the number of EntLists in this's list (EntList->next, next->next diff --git a/src/clstepcore/entnode.cc b/src/clstepcore/entnode.cc index 792489e4b..bc2141360 100644 --- a/src/clstepcore/entnode.cc +++ b/src/clstepcore/entnode.cc @@ -11,8 +11,7 @@ * Date: 9/18/96 * *****************************************************************************/ -#include "complexSupport.h" -#include "sc_memmgr.h" +#include "clstepcore/complexSupport.h" /** * Given a list of entity names, creates a sorted linked list of EntNodes diff --git a/src/clstepcore/enumTypeDescriptor.cc b/src/clstepcore/enumTypeDescriptor.cc index 9200b196f..61c4eef0f 100644 --- a/src/clstepcore/enumTypeDescriptor.cc +++ b/src/clstepcore/enumTypeDescriptor.cc @@ -1,4 +1,4 @@ -#include "enumTypeDescriptor.h" +#include "clstepcore/enumTypeDescriptor.h" /* * why have EnumTypeDescriptor + EnumerationTypeDescriptor ??? @@ -25,7 +25,7 @@ SDAI_Enum * EnumTypeDescriptor::CreateEnum() { } const char * EnumTypeDescriptor::GenerateExpress( std::string & buf ) const { - char tmp[BUFSIZ]; + char tmp[BUFSIZ+1]; buf = "TYPE "; buf.append( StrToLower( Name(), tmp ) ); buf.append( " = ENUMERATION OF \n (" ); diff --git a/src/clstepcore/explicitItemId.cc b/src/clstepcore/explicitItemId.cc index c229f6369..b7177c189 100644 --- a/src/clstepcore/explicitItemId.cc +++ b/src/clstepcore/explicitItemId.cc @@ -1,4 +1,4 @@ -#include "explicitItemId.h" +#include "clstepcore/explicitItemId.h" Explicit_item_id::Explicit_item_id() { _local_definition = 0; diff --git a/src/clstepcore/globalRule.cc b/src/clstepcore/globalRule.cc index b6fdeb19a..227562faa 100644 --- a/src/clstepcore/globalRule.cc +++ b/src/clstepcore/globalRule.cc @@ -1,4 +1,4 @@ -#include "globalRule.h" +#include "clstepcore/globalRule.h" Global_rule::Global_rule() : _entities( 0 ), _where_rules( 0 ), _parent_schema( 0 ) { diff --git a/src/clstepcore/implicitItemId.cc b/src/clstepcore/implicitItemId.cc index 1961727af..963844314 100644 --- a/src/clstepcore/implicitItemId.cc +++ b/src/clstepcore/implicitItemId.cc @@ -1,4 +1,4 @@ -#include "implicitItemId.h" +#include "clstepcore/implicitItemId.h" Implicit_item_id::Implicit_item_id() { _local_definition = 0; diff --git a/src/clstepcore/instmgr.cc b/src/clstepcore/instmgr.cc index 702ea0869..61212d4d6 100644 --- a/src/clstepcore/instmgr.cc +++ b/src/clstepcore/instmgr.cc @@ -16,9 +16,8 @@ // ////////////////////////////////////////////////////////////////////////////// -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" +#include "clstepcore/instmgr.h" /////////////////////////////////////////////////////////////////////////////// // debug_level >= 2 => tells when a command is chosen @@ -94,7 +93,7 @@ void InstMgr::DeleteInstances() { enum Severity InstMgr::VerifyInstances( ErrorDescriptor & err ) { int errorCount = 0; - char errbuf[BUFSIZ]; + char errbuf[BUFSIZ+1]; int n = InstanceCount(); MgrNode * mn; @@ -116,11 +115,11 @@ InstMgr::VerifyInstances( ErrorDescriptor & err ) { if( !mn ) { ++errorCount; if( errorCount == 1 ) - sprintf( errbuf, + snprintf( errbuf, sizeof(errbuf), "VerifyInstances: Unable to verify the following instances: node %d", i ); else { - sprintf( errbuf, ", node %d", i ); + snprintf( errbuf, sizeof(errbuf), ", node %d", i ); } err.AppendToDetailMsg( errbuf ); @@ -140,18 +139,18 @@ InstMgr::VerifyInstances( ErrorDescriptor & err ) { } ++errorCount; if( errorCount == 1 ) - sprintf( errbuf, + snprintf( errbuf, sizeof(errbuf), "VerifyInstances: Unable to verify the following instances: #%d", se->StepFileId() ); else { - sprintf( errbuf, ", #%d", se->StepFileId() ); + snprintf( errbuf, sizeof(errbuf), ", #%d", se->StepFileId() ); } err.AppendToDetailMsg( errbuf ); } } } if( errorCount ) { - sprintf( errbuf, + snprintf( errbuf, sizeof(errbuf), "VerifyInstances: %d invalid instances in list.\n", errorCount ); err.AppendToUserMsg( errbuf ); diff --git a/src/clstepcore/interfaceSpec.cc b/src/clstepcore/interfaceSpec.cc index eb0fecf3a..b0ed39bc5 100644 --- a/src/clstepcore/interfaceSpec.cc +++ b/src/clstepcore/interfaceSpec.cc @@ -1,4 +1,4 @@ -#include "interfaceSpec.h" +#include "clstepcore/interfaceSpec.h" Interface_spec__set::Interface_spec__set( int defaultSize ) { _bufsize = defaultSize; diff --git a/src/clstepcore/interfacedItem.cc b/src/clstepcore/interfacedItem.cc index 749a5922e..9ddb5b5a5 100644 --- a/src/clstepcore/interfacedItem.cc +++ b/src/clstepcore/interfacedItem.cc @@ -1,4 +1,4 @@ -#include "interfacedItem.h" +#include "clstepcore/interfacedItem.h" Interfaced_item::Interfaced_item() { } diff --git a/src/clstepcore/inverseAttribute.cc b/src/clstepcore/inverseAttribute.cc index eeccec90a..512c71c34 100644 --- a/src/clstepcore/inverseAttribute.cc +++ b/src/clstepcore/inverseAttribute.cc @@ -1,4 +1,4 @@ -#include "inverseAttribute.h" +#include "clstepcore/inverseAttribute.h" #include const char * Inverse_attribute::AttrExprDefStr( std::string & s ) const { diff --git a/src/clstepcore/inverseAttributeList.cc b/src/clstepcore/inverseAttributeList.cc index 22591d41c..2dd7d46b0 100644 --- a/src/clstepcore/inverseAttributeList.cc +++ b/src/clstepcore/inverseAttributeList.cc @@ -1,5 +1,5 @@ -#include "inverseAttributeList.h" -#include "inverseAttribute.h" +#include "clstepcore/inverseAttributeList.h" +#include "clstepcore/inverseAttribute.h" Inverse_attributeLinkNode::Inverse_attributeLinkNode() { _invAttr = 0; diff --git a/src/clstepcore/match-ors.cc b/src/clstepcore/match-ors.cc index 5f17f7d93..72427ca6b 100644 --- a/src/clstepcore/match-ors.cc +++ b/src/clstepcore/match-ors.cc @@ -13,8 +13,7 @@ * Date: 10/17/96 * *****************************************************************************/ -#include "complexSupport.h" -#include "sc_memmgr.h" +#include "clstepcore/complexSupport.h" /** * Loops through descendants of this, invoking their matchOR functions. diff --git a/src/clstepcore/mgrnode.cc b/src/clstepcore/mgrnode.cc index 8e44443ee..a7d13b538 100644 --- a/src/clstepcore/mgrnode.cc +++ b/src/clstepcore/mgrnode.cc @@ -12,17 +12,16 @@ /* $Id: mgrnode.cc,v 3.0.1.3 1997/11/05 22:11:37 sauderd DP3.1 $ */ -#include -#include -#include -#include +#include "clstepcore/mgrnode.h" +#include "clstepcore/mgrnodelist.h" +#include "clstepcore/dispnode.h" +#include "clstepcore/dispnodelist.h" -#include +#include "clstepcore/instmgr.h" //#include -#include +#include "clstepcore/sdai.h" #include -#include "sc_memmgr.h" void * MgrNode::SEE() { return ( di ? di->SEE() : 0 ); diff --git a/src/clstepcore/mgrnodearray.cc b/src/clstepcore/mgrnodearray.cc index 23069f02b..d777b596f 100644 --- a/src/clstepcore/mgrnodearray.cc +++ b/src/clstepcore/mgrnodearray.cc @@ -32,12 +32,11 @@ static int PrintFunctionTrace = 2; // values within functions get printed out //static int PrintValues = 3; -#include +#include "clstepcore/mgrnodearray.h" //#include -#include +#include "clstepcore/sdai.h" #include // to get bcopy() - ANSI -#include "sc_memmgr.h" ////////////////////////////////////////////////////////////////////////////// // class MgrNodeArray member functions diff --git a/src/clstepcore/mgrnodelist.cc b/src/clstepcore/mgrnodelist.cc index 9bff8e254..77ee20100 100644 --- a/src/clstepcore/mgrnodelist.cc +++ b/src/clstepcore/mgrnodelist.cc @@ -12,11 +12,10 @@ /* $Id: mgrnodelist.cc,v 3.0.1.2 1997/11/05 22:11:39 sauderd DP3.1 $ */ -#include -#include -#include -#include -#include "sc_memmgr.h" +#include "clstepcore/mgrnode.h" +#include "clstepcore/mgrnodelist.h" +#include "clstepcore/dispnode.h" +#include "clstepcore/dispnodelist.h" MgrNodeList::MgrNodeList( stateEnum type ) : GenNodeList( new MgrNode() ) { // if(debug_level >= PrintFunctionTrace) diff --git a/src/clstepcore/multlist.cc b/src/clstepcore/multlist.cc index 959720ed0..b36488377 100644 --- a/src/clstepcore/multlist.cc +++ b/src/clstepcore/multlist.cc @@ -13,8 +13,7 @@ * Date: 9/18/96 * *****************************************************************************/ -#include "complexSupport.h" -#include "sc_memmgr.h" +#include "clstepcore/complexSupport.h" /** * Deletes the childList of this, before this is deleted. diff --git a/src/clstepcore/needFunc.cc b/src/clstepcore/needFunc.cc index eea46ddb5..e72215fed 100644 --- a/src/clstepcore/needFunc.cc +++ b/src/clstepcore/needFunc.cc @@ -1,5 +1,4 @@ -#include -#include "sc_memmgr.h" +#include "clstepcore/needFunc.h" /////////////////////////////////////////////////////////////////////////////// // Function defined as a stub (necessary to use the scl) diff --git a/src/clstepcore/non-ors.cc b/src/clstepcore/non-ors.cc index 14607f606..14b6a4f6c 100644 --- a/src/clstepcore/non-ors.cc +++ b/src/clstepcore/non-ors.cc @@ -10,8 +10,7 @@ * Date: 10/17/96 * *****************************************************************************/ -#include "complexSupport.h" -#include "sc_memmgr.h" +#include "clstepcore/complexSupport.h" /** * Checks if we match the nodes of ents. If only one unmarked is left diff --git a/src/clstepcore/orlist.cc b/src/clstepcore/orlist.cc index b820bea53..f5fa185b0 100644 --- a/src/clstepcore/orlist.cc +++ b/src/clstepcore/orlist.cc @@ -10,8 +10,7 @@ * Date: 9/18/96 * *****************************************************************************/ -#include "complexSupport.h" -#include "sc_memmgr.h" +#include "clstepcore/complexSupport.h" /** * Check if we matched nm. We have two possibilities here: If we have a diff --git a/src/clstepcore/print.cc b/src/clstepcore/print.cc index 2139d1f61..63759b9fc 100644 --- a/src/clstepcore/print.cc +++ b/src/clstepcore/print.cc @@ -7,8 +7,7 @@ * Date: 10/31/96 * *****************************************************************************/ -#include "complexSupport.h" -#include "sc_memmgr.h" +#include "clstepcore/complexSupport.h" // Local function prototypes: static char * joinText( JoinType, char * ); diff --git a/src/clstepcore/read_func.cc b/src/clstepcore/read_func.cc index 395e52cfd..f834251a7 100644 --- a/src/clstepcore/read_func.cc +++ b/src/clstepcore/read_func.cc @@ -1,11 +1,10 @@ -#include +#include "clutils/errordesc.h" #include -#include -#include -#include -#include "Str.h" -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" +#include "clstepcore/read_func.h" +#include "clstepcore/STEPattribute.h" +#include "clutils/Str.h" const int RealNumPrecision = REAL_NUM_PRECISION; @@ -154,7 +153,7 @@ std::string WriteReal( SDAI_Real val ) { // Also use G instead of g since G writes uppercase E (E instead of e // is also required by Part 21) when scientific notation is used - DAS - sprintf( rbuf, "%.*G", ( int ) RealNumPrecision, val ); + snprintf( rbuf, sizeof(rbuf), "%.*G", ( int ) RealNumPrecision, val ); if( !strchr( rbuf, '.' ) ) { if( strchr( rbuf, 'E' ) || strchr( rbuf, 'e' ) ) { char * expon = strchr( rbuf, 'E' ); @@ -467,7 +466,7 @@ void PushPastString( istream & in, std::string & s, ErrorDescriptor * err ) { * This is used to read aggregates that are part of multidimensional aggregates. */ void PushPastImbedAggr( istream & in, std::string & s, ErrorDescriptor * err ) { - char messageBuf[BUFSIZ]; + char messageBuf[BUFSIZ+1]; messageBuf[0] = '\0'; char c; @@ -491,7 +490,7 @@ void PushPastImbedAggr( istream & in, std::string & s, ErrorDescriptor * err ) { } if( c != ')' ) { err->GreaterSeverity( SEVERITY_INPUT_ERROR ); - sprintf( messageBuf, "Invalid aggregate value.\n" ); + snprintf( messageBuf, sizeof(messageBuf), "Invalid aggregate value.\n" ); err->AppendToDetailMsg( messageBuf ); s.append( ")" ); } else { @@ -506,7 +505,7 @@ void PushPastImbedAggr( istream & in, std::string & s, ErrorDescriptor * err ) { * to contain an aggregate as an element. */ void PushPastAggr1Dim( istream & in, std::string & s, ErrorDescriptor * err ) { - char messageBuf[BUFSIZ]; + char messageBuf[BUFSIZ+1]; messageBuf[0] = '\0'; char c; @@ -519,7 +518,7 @@ void PushPastAggr1Dim( istream & in, std::string & s, ErrorDescriptor * err ) { while( in.good() && ( c != ')' ) ) { if( c == '(' ) { err->GreaterSeverity( SEVERITY_WARNING ); - sprintf( messageBuf, "Invalid aggregate value.\n" ); + snprintf( messageBuf, sizeof(messageBuf), "Invalid aggregate value.\n" ); err->AppendToDetailMsg( messageBuf ); } @@ -533,7 +532,7 @@ void PushPastAggr1Dim( istream & in, std::string & s, ErrorDescriptor * err ) { } if( c != ')' ) { err->GreaterSeverity( SEVERITY_INPUT_ERROR ); - sprintf( messageBuf, "Invalid aggregate value.\n" ); + snprintf( messageBuf, sizeof(messageBuf), "Invalid aggregate value.\n" ); err->AppendToDetailMsg( messageBuf ); s.append( ")" ); } else { diff --git a/src/clstepcore/schRename.cc b/src/clstepcore/schRename.cc index b7159a6e0..6e5e12686 100644 --- a/src/clstepcore/schRename.cc +++ b/src/clstepcore/schRename.cc @@ -1,4 +1,4 @@ -#include "schRename.h" +#include "clstepcore/schRename.h" /** diff --git a/src/clstepcore/sdai.cc b/src/clstepcore/sdai.cc index 731a381f5..ec96a63b3 100644 --- a/src/clstepcore/sdai.cc +++ b/src/clstepcore/sdai.cc @@ -1,8 +1,7 @@ #include #include -#include -#include "sc_memmgr.h" +#include "clstepcore/sdai.h" const char * SCLversion = "STEPcode, github.com/stepcode/stepcode"; diff --git a/src/clstepcore/sdaiApplication_instance.cc b/src/clstepcore/sdaiApplication_instance.cc index c6635fd61..0b0b4427a 100644 --- a/src/clstepcore/sdaiApplication_instance.cc +++ b/src/clstepcore/sdaiApplication_instance.cc @@ -11,13 +11,13 @@ */ #include -#include -#include -#include -#include -#include //for ReadTokenSeparator, used when comments are inside entities +#include "clstepcore/sdai.h" +#include "clstepcore/instmgr.h" +#include "clstepcore/STEPcomplex.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/read_func.h" //for ReadTokenSeparator, used when comments are inside entities -#include "sdaiApplication_instance.h" +#include "clstepcore/sdaiApplication_instance.h" #include "superInvAttrIter.h" SDAI_Application_instance NilSTEPentity; @@ -102,11 +102,11 @@ void SDAI_Application_instance::InitIAttrs() { } SDAI_Application_instance * SDAI_Application_instance::Replicate() { - char errStr[BUFSIZ]; + char errStr[BUFSIZ+1]; if( IsComplex() ) { cerr << "STEPcomplex::Replicate() should be called: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; - sprintf( errStr, + snprintf( errStr, sizeof(errStr), "SDAI_Application_instance::Replicate(): %s - entity #%d.\n", "Programming ERROR - STEPcomplex::Replicate() should be called", STEPfile_id ); @@ -151,7 +151,7 @@ void SDAI_Application_instance::STEPwrite_reference( ostream & out ) { const char * SDAI_Application_instance::STEPwrite_reference( std::string & buf ) { char tmp[64]; - sprintf( tmp, "#%d", STEPfile_id ); + snprintf( tmp, sizeof(tmp), "#%d", STEPfile_id ); buf = tmp; return const_cast( buf.c_str() ); } @@ -416,10 +416,10 @@ void SDAI_Application_instance::WriteValuePairs( ostream & out, const char * SDAI_Application_instance::STEPwrite( std::string & buf, const char * currSch ) { buf.clear(); - char instanceInfo[BUFSIZ]; + char instanceInfo[BUFSIZ+1]; std::string tmp; - sprintf( instanceInfo, "#%d=%s(", STEPfile_id, StrToUpper( EntityName( currSch ), tmp ) ); + snprintf( instanceInfo, sizeof(instanceInfo), "#%d=%s(", STEPfile_id, StrToUpper( EntityName( currSch ), tmp ) ); buf.append( instanceInfo ); int n = attributes.list_length(); @@ -438,12 +438,12 @@ const char * SDAI_Application_instance::STEPwrite( std::string & buf, const char } void SDAI_Application_instance::PrependEntityErrMsg() { - char errStr[BUFSIZ]; + char errStr[BUFSIZ+1]; errStr[0] = '\0'; if( _error.severity() == SEVERITY_NULL ) { // if there is not an error already - sprintf( errStr, "\nERROR: ENTITY #%d %s\n", GetFileId(), + snprintf( errStr, sizeof(errStr), "\nERROR: ENTITY #%d %s\n", GetFileId(), EntityName() ); _error.PrependToDetailMsg( errStr ); } @@ -459,20 +459,20 @@ void SDAI_Application_instance::PrependEntityErrMsg() { ******************************************************************/ void SDAI_Application_instance::STEPread_error( char c, int i, istream & in, const char * schnm ) { (void) in; - char errStr[BUFSIZ]; + char errStr[BUFSIZ+1]; errStr[0] = '\0'; if( _error.severity() == SEVERITY_NULL ) { // if there is not an error already - sprintf( errStr, "\nERROR: ENTITY #%d %s\n", GetFileId(), + snprintf( errStr, sizeof(errStr), "\nERROR: ENTITY #%d %s\n", GetFileId(), EntityName() ); _error.PrependToDetailMsg( errStr ); } if( ( i >= 0 ) && ( i < attributes.list_length() ) ) { // i is an attribute Error().GreaterSeverity( SEVERITY_WARNING ); - sprintf( errStr, " invalid data before type \'%s\'\n", - attributes[i].TypeName() ); + snprintf( errStr, sizeof(errStr), " invalid data before type \'%s\'\n", + attributes[i].TypeName().c_str() ); _error.AppendToDetailMsg( errStr ); } else { Error().GreaterSeverity( SEVERITY_INPUT_ERROR ); @@ -487,7 +487,7 @@ void SDAI_Application_instance::STEPread_error( char c, int i, istream & in, con _error.AppendToDetailMsg( c ); _error.AppendToDetailMsg( '\n' ); - sprintf( errStr, "\nfinished reading #%d\n", STEPfile_id ); + snprintf( errStr, sizeof(errStr), "\nfinished reading #%d\n", STEPfile_id ); _error.AppendToDetailMsg( errStr ); return; } @@ -511,7 +511,7 @@ Severity SDAI_Application_instance::STEPread( int id, int idIncr, const char * currSch, bool useTechCor, bool strict ) { STEPfile_id = id; char c = '\0'; - char errStr[BUFSIZ]; + char errStr[BUFSIZ+1]; errStr[0] = '\0'; Severity severe; int i = 0; @@ -552,7 +552,7 @@ Severity SDAI_Application_instance::STEPread( int id, int idIncr, // set the severity for this entity _error.GreaterSeverity( severe ); - sprintf( errStr, " %s : ", attributes[i].Name() ); + snprintf( errStr, sizeof(errStr), " %s : ", attributes[i].Name() ); _error.AppendToDetailMsg( errStr ); // add attr name _error.AppendToDetailMsg( "Since using pre-technical corrigendum... missing asterisk for redefined attr.\n" ); @@ -583,7 +583,7 @@ Severity SDAI_Application_instance::STEPread( int id, int idIncr, // set the severity for this entity _error.GreaterSeverity( severe ); - sprintf( errStr, " %s : ", attributes[i].Name() ); + snprintf( errStr, sizeof(errStr), " %s : ", attributes[i].Name() ); _error.AppendToDetailMsg( errStr ); // add attr name _error.AppendToDetailMsg( attributes[i].Error().DetailMsg() ); // add attr error _error.AppendToUserMsg( attributes[i].Error().UserMsg() ); @@ -653,7 +653,7 @@ Severity SDAI_Application_instance::STEPread( int id, int idIncr, } } _error.AppendToDetailMsg( tmp.c_str() ); - sprintf( errStr, "\nfinished reading #%d\n", STEPfile_id ); + snprintf( errStr, sizeof(errStr), "\nfinished reading #%d\n", STEPfile_id ); _error.AppendToDetailMsg( errStr ); // end of imported code return _error.severity(); @@ -663,7 +663,7 @@ Severity SDAI_Application_instance::STEPread( int id, int idIncr, SDAI_Application_instance * ReadEntityRef( istream & in, ErrorDescriptor * err, const char * tokenList, InstMgrBase * instances, int addFileId ) { char c; - char errStr[BUFSIZ]; + char errStr[BUFSIZ+1]; errStr[0] = '\0'; in >> ws; @@ -678,7 +678,7 @@ SDAI_Application_instance * ReadEntityRef( istream & in, ErrorDescriptor * err, int id = -1; in >> id; if( in.fail() ) { // there's been an error in input - sprintf( errStr, "Invalid entity reference value.\n" ); + snprintf( errStr, sizeof(errStr), "Invalid entity reference value.\n" ); err->AppendToDetailMsg( errStr ); err->AppendToUserMsg( errStr ); err->GreaterSeverity( SEVERITY_WARNING ); @@ -692,7 +692,7 @@ SDAI_Application_instance * ReadEntityRef( istream & in, ErrorDescriptor * err, if( !instances ) { cerr << "Internal error: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; - sprintf( errStr, + snprintf( errStr, sizeof(errStr), "STEPread_reference(): %s - entity #%d %s.\n", "BUG - cannot read reference without the InstMgr", id, "is unknown" ); @@ -714,7 +714,7 @@ SDAI_Application_instance * ReadEntityRef( istream & in, ErrorDescriptor * err, } else { cerr << "Internal error: " << __FILE__ << __LINE__ << "\n" << _POC_ "\n"; - sprintf( errStr, + snprintf( errStr, sizeof(errStr), "STEPread_reference(): %s - entity #%d %s.\n", "BUG - MgrNode::GetSTEPentity returned NULL pointer", id, "is unknown" ); @@ -724,7 +724,7 @@ SDAI_Application_instance * ReadEntityRef( istream & in, ErrorDescriptor * err, return S_ENTITY_NULL; } } else { - sprintf( errStr, "Reference to non-existent ENTITY #%d.\n", + snprintf( errStr, sizeof(errStr), "Reference to non-existent ENTITY #%d.\n", id ); err->AppendToDetailMsg( errStr ); err->AppendToUserMsg( errStr ); @@ -756,12 +756,12 @@ Severity EntityValidLevel( SDAI_Application_instance * se, // to match. (this must be an // EntityDescriptor) ErrorDescriptor * err ) { - char messageBuf [BUFSIZ]; + char messageBuf [BUFSIZ+1]; messageBuf[0] = '\0'; if( !ed || ( ed->NonRefType() != ENTITY_TYPE ) ) { err->GreaterSeverity( SEVERITY_BUG ); - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), " BUG: EntityValidLevel() called with %s", "missing or invalid EntityDescriptor\n" ); err->AppendToUserMsg( messageBuf ); @@ -772,7 +772,7 @@ Severity EntityValidLevel( SDAI_Application_instance * se, } if( !se || ( se == S_ENTITY_NULL ) ) { err->GreaterSeverity( SEVERITY_BUG ); - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), " BUG: EntityValidLevel() called with null pointer %s\n", "for SDAI_Application_instance argument." ); err->AppendToUserMsg( messageBuf ); @@ -800,7 +800,7 @@ Severity EntityValidLevel( SDAI_Application_instance * se, } } err->GreaterSeverity( SEVERITY_WARNING ); - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), " Entity #%d exists but is not a %s or descendant.\n", se->STEPfile_id, ed->Name() ); err->AppendToUserMsg( messageBuf ); @@ -809,7 +809,7 @@ Severity EntityValidLevel( SDAI_Application_instance * se, } } else { err->GreaterSeverity( SEVERITY_BUG ); - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), " BUG: EntityValidLevel(): SDAI_Application_instance #%d has a %s", se->STEPfile_id, "missing or invalid EntityDescriptor\n" ); err->AppendToUserMsg( messageBuf ); @@ -825,7 +825,7 @@ Severity EntityValidLevel( SDAI_Application_instance * se, * DAVE: Is this needed will sscanf return 1 if assignment suppression is used? */ int SetErrOnNull( const char * attrValue, ErrorDescriptor * error ) { - char scanBuf[BUFSIZ]; + char scanBuf[BUFSIZ+1]; scanBuf[0] = '\0'; std::stringstream fmtstr; @@ -853,9 +853,9 @@ Severity EntityValidLevel( const char * attrValue, // string contain entity ref // to match. (this must be an // EntityDescriptor) ErrorDescriptor * err, InstMgrBase * im, int clearError ) { - char tmp [BUFSIZ]; + char tmp [BUFSIZ+1]; tmp[0] = '\0'; - char messageBuf [BUFSIZ]; + char messageBuf [BUFSIZ+1]; messageBuf[0] = '\0'; std::stringstream fmtstr1, fmtstr2; @@ -893,7 +893,7 @@ Severity EntityValidLevel( const char * attrValue, // string contain entity ref SDAI_Application_instance * se = mn->GetSTEPentity(); return EntityValidLevel( se, ed, err ); } else { - sprintf( messageBuf, + snprintf( messageBuf, sizeof(messageBuf), " Attribute's Entity Reference %s does not exist.\n", attrValue ); err->AppendToUserMsg( messageBuf ); @@ -908,7 +908,7 @@ Severity EntityValidLevel( const char * attrValue, // string contain entity ref return err->severity(); } - sprintf( messageBuf, "Invalid attribute entity reference value: '%s'.\n", + snprintf( messageBuf, sizeof(messageBuf), "Invalid attribute entity reference value: '%s'.\n", attrValue ); err->AppendToUserMsg( messageBuf ); err->AppendToDetailMsg( messageBuf ); diff --git a/src/clstepcore/sdaiSelect.cc b/src/clstepcore/sdaiSelect.cc index 08e789a6d..95e6d83bc 100644 --- a/src/clstepcore/sdaiSelect.cc +++ b/src/clstepcore/sdaiSelect.cc @@ -11,11 +11,11 @@ */ #include // to get the BUFSIZ #define -#include +#include "clstepcore/ExpDict.h" #include #include -#include -#include +#include "clstepcore/sdai.h" +#include "clstepcore/STEPattribute.h" #ifdef SC_LOGGING #include diff --git a/src/clstepcore/selectTypeDescriptor.cc b/src/clstepcore/selectTypeDescriptor.cc index a7c0ad032..e143a3a30 100644 --- a/src/clstepcore/selectTypeDescriptor.cc +++ b/src/clstepcore/selectTypeDescriptor.cc @@ -1,4 +1,4 @@ -#include "selectTypeDescriptor.h" +#include "clstepcore/selectTypeDescriptor.h" /////////////////////////////////////////////////////////////////////////////// // SelectTypeDescriptor functions diff --git a/src/clstepcore/superInvAttrIter.h b/src/clstepcore/superInvAttrIter.h index bfe73dc17..6228b67be 100644 --- a/src/clstepcore/superInvAttrIter.h +++ b/src/clstepcore/superInvAttrIter.h @@ -1,8 +1,8 @@ #ifndef SUPERINVATTRITER_H #define SUPERINVATTRITER_H -#include "SubSuperIterators.h" -#include "ExpDict.h" +#include "clstepcore/SubSuperIterators.h" +#include "clstepcore/ExpDict.h" /** * this class implements an iterator for inverse attributes in an EntityDescriptor's supertypes diff --git a/src/clstepcore/test/CMakeLists.txt b/src/clstepcore/test/CMakeLists.txt index f9f353e26..ea37cb0cd 100644 --- a/src/clstepcore/test/CMakeLists.txt +++ b/src/clstepcore/test/CMakeLists.txt @@ -3,7 +3,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.12) include_directories( ${SC_SOURCE_DIR}/src/cldai ${SC_SOURCE_DIR}/src/cleditor - ${SC_SOURCE_DIR}/src/clutils ${SC_SOURCE_DIR}/src/base ${SC_SOURCE_DIR}/src/clstepcore ) @@ -21,10 +20,10 @@ function(add_stepcore_test name libs) set_tests_properties(test_${name} PROPERTIES LABELS cpp_unit_stepcore DEPENDS build_cpp_${name}) endfunction(add_stepcore_test name libs) -add_stepcore_test("SupertypesIterator" "stepcore;steputils;stepeditor;stepdai;base") #all these libs are necessary? -add_stepcore_test("operators_STEPattribute" "stepcore;steputils;stepeditor;stepdai;base") -add_stepcore_test("operators_SDAI_Select" "stepcore;steputils;stepeditor;stepdai;base") -add_stepcore_test("null_attr" "stepcore;steputils;stepeditor;stepdai;base") +add_stepcore_test("SupertypesIterator" "stepcore;steputils;stepeditor;stepdai") #all these libs are necessary? +add_stepcore_test("operators_STEPattribute" "stepcore;steputils;stepeditor;stepdai") +add_stepcore_test("operators_SDAI_Select" "stepcore;steputils;stepeditor;stepdai") +add_stepcore_test("null_attr" "stepcore;steputils;stepeditor;stepdai") # Local Variables: # tab-width: 8 diff --git a/src/clstepcore/test/test_SupertypesIterator.cc b/src/clstepcore/test/test_SupertypesIterator.cc index f557d7c72..084189bf0 100644 --- a/src/clstepcore/test/test_SupertypesIterator.cc +++ b/src/clstepcore/test/test_SupertypesIterator.cc @@ -4,8 +4,8 @@ //subtypesiterator shouldn't need tested separately from supertypesiterator since there is very little difference -#include "SubSuperIterators.h" -#include "ExpDict.h" +#include "clstepcore/SubSuperIterators.h" +#include "clstepcore/ExpDict.h" #include int main( int /*argc*/, char ** /*argv*/ ) { diff --git a/src/clstepcore/test/test_null_attr.cc b/src/clstepcore/test/test_null_attr.cc index 0c96c5798..95c7dcd02 100644 --- a/src/clstepcore/test/test_null_attr.cc +++ b/src/clstepcore/test/test_null_attr.cc @@ -1,6 +1,6 @@ -#include -#include -#include +#include "clstepcore/ExpDict.h" +#include "clstepcore/STEPattribute.h" +#include "cldai/sdaiString.h" AttrDescriptor *ad = 0; EntityDescriptor *ed = 0; diff --git a/src/clstepcore/test/test_operators_SDAI_Select.cc b/src/clstepcore/test/test_operators_SDAI_Select.cc index fcb6cde4d..b82d20ddc 100644 --- a/src/clstepcore/test/test_operators_SDAI_Select.cc +++ b/src/clstepcore/test/test_operators_SDAI_Select.cc @@ -6,9 +6,9 @@ #include -#include "ExpDict.h" -#include "baseType.h" -#include "sdaiSelect.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/baseType.h" +#include "clstepcore/sdaiSelect.h" using namespace std; diff --git a/src/clstepcore/test/test_operators_STEPattribute.cc b/src/clstepcore/test/test_operators_STEPattribute.cc index abd396816..a64d274de 100644 --- a/src/clstepcore/test/test_operators_STEPattribute.cc +++ b/src/clstepcore/test/test_operators_STEPattribute.cc @@ -1,7 +1,7 @@ ///test constructors, destructor, shallow copy, assignment operators for STEPattribute -#include -#include +#include "clstepcore/STEPattribute.h" +#include "clstepcore/ExpDict.h" #include diff --git a/src/clstepcore/trynext.cc b/src/clstepcore/trynext.cc index 145af7699..dd2941edd 100644 --- a/src/clstepcore/trynext.cc +++ b/src/clstepcore/trynext.cc @@ -11,8 +11,7 @@ * Date: 10/24/96 * *****************************************************************************/ -#include "complexSupport.h" -#include "sc_memmgr.h" +#include "clstepcore/complexSupport.h" // Local function prototypes: static EntList * firstCandidate( EntList * ); diff --git a/src/clstepcore/typeDescriptor.cc b/src/clstepcore/typeDescriptor.cc index e37d931bb..1d654f609 100644 --- a/src/clstepcore/typeDescriptor.cc +++ b/src/clstepcore/typeDescriptor.cc @@ -1,4 +1,4 @@ -#include "typeDescriptor.h" +#include "clstepcore/typeDescriptor.h" TypeDescriptor::TypeDescriptor( ) : _name( 0 ), altNames( 0 ), _fundamentalType( UNKNOWN_TYPE ), @@ -75,7 +75,7 @@ bool TypeDescriptor::CurrName( const char * other, const char * schNm ) const { // other better = the alt name. return ( !StrCmpIns( _altname, other ) ); } else { - // If we have no desginated alternate name when the current schema = + // If we have no designated alternate name when the current schema = // schNm, other must = our _name. return ( OurName( other ) ); } @@ -132,7 +132,7 @@ void TypeDescriptor::AttrTypeName( std::string & buf, const char * schnm ) const } const char * TypeDescriptor::GenerateExpress( std::string & buf ) const { - char tmp[BUFSIZ]; + char tmp[BUFSIZ+1]; buf = "TYPE "; buf.append( StrToLower( Name(), tmp ) ); buf.append( " = " ); diff --git a/src/clstepcore/typeDescriptorList.cc b/src/clstepcore/typeDescriptorList.cc index f47e8f502..bbc91de9e 100644 --- a/src/clstepcore/typeDescriptorList.cc +++ b/src/clstepcore/typeDescriptorList.cc @@ -1,4 +1,4 @@ -#include "typeDescriptorList.h" +#include "clstepcore/typeDescriptorList.h" TypeDescLinkNode::TypeDescLinkNode() { _typeDesc = 0; diff --git a/src/clstepcore/typeOrRuleVar.cc b/src/clstepcore/typeOrRuleVar.cc index 0b06f1949..c9b823cbf 100644 --- a/src/clstepcore/typeOrRuleVar.cc +++ b/src/clstepcore/typeOrRuleVar.cc @@ -1,4 +1,4 @@ -#include "typeOrRuleVar.h" +#include "clstepcore/typeOrRuleVar.h" #include diff --git a/src/clstepcore/uniquenessRule.cc b/src/clstepcore/uniquenessRule.cc index 038f1a68f..d22bf2c2c 100644 --- a/src/clstepcore/uniquenessRule.cc +++ b/src/clstepcore/uniquenessRule.cc @@ -1,4 +1,4 @@ -#include "uniquenessRule.h" +#include "clstepcore/uniquenessRule.h" #include diff --git a/src/clstepcore/whereRule.cc b/src/clstepcore/whereRule.cc index e60c64940..191b1ec36 100644 --- a/src/clstepcore/whereRule.cc +++ b/src/clstepcore/whereRule.cc @@ -1,4 +1,4 @@ -#include "whereRule.h" +#include "clstepcore/whereRule.h" Where_rule::Where_rule() { _type_or_rule = 0; diff --git a/src/clutils/CMakeLists.txt b/src/clutils/CMakeLists.txt index 514980ad9..27cb08745 100644 --- a/src/clutils/CMakeLists.txt +++ b/src/clutils/CMakeLists.txt @@ -1,5 +1,4 @@ - -set(LIBSTEPUTILS_SRCS +set(UTILS_SRCS Str.cc dirobj.cc gennode.cc @@ -9,24 +8,13 @@ set(LIBSTEPUTILS_SRCS errordesc.cc ) -set(SC_CLUTILS_HDRS - dirobj.h - errordesc.h - gennodearray.h - gennode.h - gennodelist.h - sc_hash.h - Str.h - ) - include_directories( - ${SC_SOURCE_DIR}/src/base ${SC_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR} ) if(BUILD_SHARED_LIBS) - SC_ADDLIB(steputils SHARED SOURCES ${LIBSTEPUTILS_SRCS} LINK_LIBRARIES base) + SC_ADDLIB(steputils SHARED SOURCES ${UTILS_SRCS}) if(WIN32) target_compile_definitions(steputils PRIVATE SC_UTILS_DLL_EXPORTS) target_link_libraries(steputils shlwapi) @@ -34,15 +22,12 @@ if(BUILD_SHARED_LIBS) endif() if(BUILD_STATIC_LIBS) - SC_ADDLIB(steputils-static STATIC SOURCES ${LIBSTEPUTILS_SRCS} LINK_LIBRARIES base-static) + SC_ADDLIB(steputils-static STATIC SOURCES ${UTILS_SRCS}) if(WIN32) target_link_libraries(steputils-static shlwapi) endif() endif() -install(FILES ${SC_CLUTILS_HDRS} - DESTINATION ${INCLUDE_DIR}/stepcode/clutils) - # Local Variables: # tab-width: 8 # mode: cmake diff --git a/src/clutils/Str.cc b/src/clutils/Str.cc index a14f0dc08..1f6a3dce3 100644 --- a/src/clutils/Str.cc +++ b/src/clutils/Str.cc @@ -9,7 +9,7 @@ * and is not subject to copyright. */ -#include "Str.h" +#include "clutils/Str.h" #include #include @@ -53,7 +53,7 @@ char * StrToLower( const char * strOld, char * strNew ) { } const char * StrToLower( const char * word, std::string & s ) { - char newword [BUFSIZ]; + char newword [BUFSIZ+1]; int i = 0; while( word [i] != '\0' ) { @@ -66,7 +66,7 @@ const char * StrToLower( const char * word, std::string & s ) { } const char * StrToUpper( const char * word, std::string & s ) { - char newword [BUFSIZ]; + char newword [BUFSIZ+1]; int i = 0; while( word [i] != '\0' ) { @@ -79,7 +79,7 @@ const char * StrToUpper( const char * word, std::string & s ) { } const char * StrToConstant( const char * word, std::string & s ) { - char newword [BUFSIZ]; + char newword [BUFSIZ+1]; int i = 0; while( word [i] != '\0' ) { @@ -179,7 +179,7 @@ std::string GetLiteralStr( istream & in, ErrorDescriptor * err ) { ******************************************************************/ const char * PrettyTmpName( const char * oldname ) { int i = 0; - static char newname [BUFSIZ]; + static char newname [BUFSIZ+1]; newname [0] = '\0'; while( ( oldname [i] != '\0' ) && ( i < BUFSIZ ) ) { newname [i] = ToLower( oldname [i] ); diff --git a/src/clutils/dirobj.cc b/src/clutils/dirobj.cc index 337774342..e0e3f970a 100644 --- a/src/clutils/dirobj.cc +++ b/src/clutils/dirobj.cc @@ -39,8 +39,8 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include +#include "config.h" +#include "clutils/dirobj.h" #ifdef HAVE_DIRENT_H # include #endif @@ -58,8 +58,6 @@ #include #endif -#include - /////////////////////////////////////////////////////////////////////////////// // // Create a new DirObj object. @@ -257,10 +255,11 @@ std::string DirObj::Normalize( const std::string & path ) { const char * DirObj::ValidDirectories( const char * path ) { #ifdef _WIN32 static char buf[MAX_PATH + 1]; + strncpy(buf, path, MAX_PATH); #else static char buf[MAXPATHLEN + 1]; + strncpy(buf, path, MAXPATHLEN); #endif - strcpy( buf, path ); int i = strlen( path ); while( !IsADirectory( RealPath( buf ) ) && i >= 0 ) { @@ -326,8 +325,8 @@ void DirObj::InsertFile( const char * f, int index ) { void DirObj::RemoveFile( int index ) { if( index < --fileCount ) { + free(fileList[index]); const char ** spot = ( const char ** )&fileList[index]; - delete spot; memmove( spot, spot + 1, ( fileCount - index )*sizeof( char * ) ); } } diff --git a/src/clutils/errordesc.cc b/src/clutils/errordesc.cc index c5a998c8c..17a2de465 100644 --- a/src/clutils/errordesc.cc +++ b/src/clutils/errordesc.cc @@ -10,9 +10,8 @@ * and is not subject to copyright. */ -#include -#include -#include +#include "clutils/errordesc.h" +#include "clutils/Str.h" DebugLevel ErrorDescriptor::_debug_level = DEBUG_OFF; ostream * ErrorDescriptor::_out = 0; diff --git a/src/clutils/gennode.cc b/src/clutils/gennode.cc index 3036ab19d..c8a993632 100644 --- a/src/clutils/gennode.cc +++ b/src/clutils/gennode.cc @@ -12,9 +12,8 @@ /* $Id: gennode.cc,v 3.0.1.4 1997/11/05 22:33:47 sauderd DP3.1 $ */ -#include -#include -#include +#include "clutils/gennode.h" +#include "clutils/gennodelist.h" ////////////////////////////////////////////////////////////////////////////// // class GenericNode inline functions that depend on other classes diff --git a/src/clutils/gennodearray.cc b/src/clutils/gennodearray.cc index f78acbd14..22a9a73d3 100644 --- a/src/clutils/gennodearray.cc +++ b/src/clutils/gennodearray.cc @@ -11,12 +11,11 @@ */ -#include +#include "config.h" -#include -#include -#include -#include +#include "clutils/gennode.h" +#include "clutils/gennodelist.h" +#include "clutils/gennodearray.h" #ifndef HAVE_MEMMOVE extern "C" { diff --git a/src/clutils/gennodelist.cc b/src/clutils/gennodelist.cc index 9560a72b1..c75d7a712 100644 --- a/src/clutils/gennodelist.cc +++ b/src/clutils/gennodelist.cc @@ -12,11 +12,10 @@ /* $Id: gennodelist.cc,v 3.0.1.2 1997/11/05 22:33:49 sauderd DP3.1 $ */ -#include -#include +#include "clutils/gennode.h" +#include "clutils/gennodelist.h" //#include -#include -#include +#include "clutils/gennodearray.h" // inserts after existNode void GenNodeList::InsertAfter( GenericNode * newNode, diff --git a/src/clutils/sc_hash.cc b/src/clutils/sc_hash.cc index ddbe06a0b..8ed4c54ab 100644 --- a/src/clutils/sc_hash.cc +++ b/src/clutils/sc_hash.cc @@ -5,11 +5,10 @@ * also, hcreate/hdestroy routines added to simulate hsearch(3). */ -#include +#include "clutils/sc_hash.h" #include #include #include -#include /* constants */ #define HASH_NULL (Hash_TableP)NULL @@ -50,6 +49,7 @@ void * SC_HASHfind( Hash_TableP t, char * s ) { e.key = s; e.symbol = 0; /* initialize to 0 - 25-Apr-1994 - kcm */ + e.type = '*'; ep = SC_HASHsearch( t, &e, HASH_FIND ); return( ep ? ep->data : 0 ); } @@ -61,6 +61,7 @@ void SC_HASHinsert( Hash_TableP t, char * s, void * data ) { e.key = s; e.data = data; e.symbol = 0; + e.type = '*'; e2 = SC_HASHsearch( t, &e, HASH_INSERT ); if( e2 ) { fprintf( stderr, "%s: Redeclaration of %s\n", __func__, s ); @@ -258,6 +259,9 @@ struct Element * SC_HASHsearch( Hash_TableP table, const struct Element * item, /*STRINGfree(deleteme->key);*/ SC_HASH_Element_destroy( deleteme ); --table->KeyCount; + // TODO - we shouldn't be returning this pointer - it invites a + // USE_AFTER_FREE error. Could we just replace SC_HASH completely + // with one of the C++ containers? return( deleteme ); /* of course, user shouldn't deref this! */ case HASH_INSERT: /* if trying to insert it (twice), let them know */ diff --git a/src/exp2cxx/CMakeLists.txt b/src/exp2cxx/CMakeLists.txt index 93cf8c911..d8fae04cc 100644 --- a/src/exp2cxx/CMakeLists.txt +++ b/src/exp2cxx/CMakeLists.txt @@ -5,6 +5,7 @@ set(FEDEX_COMMON_SRCS set(exp2cxx_SOURCES ${FEDEX_COMMON_SRCS} + trace_fprintf.c fedex_main.c classes_wrapper.cc classes.c @@ -31,13 +32,17 @@ set(exp2cxx_SOURCES ) include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} ${SC_SOURCE_DIR}/include ${SC_SOURCE_DIR}/include/exppp ${SC_SOURCE_DIR}/include/express - ${SC_SOURCE_DIR}/src/base ) -SC_ADDEXEC(exp2cxx SOURCES ${exp2cxx_SOURCES} LINK_LIBRARIES libexppp express base) +if(BUILD_SHARED_LIBS) + SC_ADDEXEC(exp2cxx SOURCES ${exp2cxx_SOURCES} LINK_LIBRARIES libexppp express) +else() + SC_ADDEXEC(exp2cxx SOURCES ${exp2cxx_SOURCES} LINK_LIBRARIES libexppp-static express-static) +endif() if(SC_ENABLE_TESTING) add_subdirectory(test) diff --git a/src/exp2cxx/class_strings.c b/src/exp2cxx/class_strings.c index d1736a644..7058e4719 100644 --- a/src/exp2cxx/class_strings.c +++ b/src/exp2cxx/class_strings.c @@ -6,7 +6,7 @@ const char * ClassName( const char * oldname ) { int i = 0, j = 0; - static char newname [BUFSIZ]; + static char newname [BUFSIZ+1]; if( !oldname ) { return ( "" ); } @@ -152,12 +152,12 @@ const char * TYPE_get_ctype( const Type t, char * retval, size_t buf_siz ) { } const char * TYPEget_ctype( const Type t ) { - static char retval [BUFSIZ] = {0}; + static char retval [BUFSIZ+1] = {0}; return TYPE_get_ctype( t, retval, BUFSIZ ); } const char * TypeName( Type t ) { - static char name [BUFSIZ]; + static char name [BUFSIZ+1]; strcpy( name, TYPE_PREFIX ); if( TYPEget_name( t ) ) { strncat( name, FirstToUpper( TYPEget_name( t ) ), BUFSIZ - strlen( TYPE_PREFIX ) - 1 ); @@ -185,7 +185,7 @@ char ToUpper( char c ) { } const char * StrToLower( const char * word ) { - static char newword [MAX_LEN]; + static char newword [MAX_LEN+1]; int i = 0; if( !word ) { return 0; @@ -200,7 +200,7 @@ const char * StrToLower( const char * word ) { } const char * StrToUpper( const char * word ) { - static char newword [MAX_LEN]; + static char newword [MAX_LEN+1]; int i = 0; while( word [i] != '\0' ) { @@ -212,7 +212,7 @@ const char * StrToUpper( const char * word ) { } const char * StrToConstant( const char * word ) { - static char newword[MAX_LEN]; + static char newword[MAX_LEN+1]; int i = 0; while( word [i] != '\0' ) { @@ -229,7 +229,7 @@ const char * StrToConstant( const char * word ) { } const char * FirstToUpper( const char * word ) { - static char newword [MAX_LEN]; + static char newword [MAX_LEN+1]; strncpy( newword, word, MAX_LEN ); newword[0] = ToUpper( newword[0] ); diff --git a/src/exp2cxx/classes.c b/src/exp2cxx/classes.c index 0f1494ded..42f6c02c0 100644 --- a/src/exp2cxx/classes.c +++ b/src/exp2cxx/classes.c @@ -25,14 +25,12 @@ N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. /* this is used to add new dictionary calls */ /* #define NEWDICT */ -#include #include #include -#include #include "classes.h" #include -#include +#include "./trace_fprintf.h" int multiple_inheritance = 1; int print_logging = 0; @@ -96,7 +94,7 @@ void format_for_std_stringout( FILE * f, char * orig_buf ) { optr++; } fprintf( f, "%s", s_end ); - sc_free( orig_buf ); + free( orig_buf ); } void USEREFout( Schema schema, Dictionary refdict, Linked_List reflist, char * type, FILE * file ) { @@ -104,8 +102,8 @@ void USEREFout( Schema schema, Dictionary refdict, Linked_List reflist, char * t DictionaryEntry de; struct Rename * r; Linked_List list; - char td_name[BUFSIZ]; - char sch_name[BUFSIZ]; + char td_name[BUFSIZ+1]; + char sch_name[BUFSIZ+1]; strncpy( sch_name, PrettyTmpName( SCHEMAget_name( schema ) ), BUFSIZ ); @@ -161,19 +159,19 @@ void USEREFout( Schema schema, Dictionary refdict, Linked_List reflist, char * t first_time = false; } if( re->type == OBJ_TYPE ) { - sprintf( td_name, "%s", TYPEtd_name( ( Type )re->object ) ); + snprintf( td_name, sizeof(td_name), "%s", TYPEtd_name( ( Type )re->object ) ); } else if( re->type == OBJ_FUNCTION ) { - sprintf( td_name, "/* Function not implemented */ 0" ); + snprintf( td_name, sizeof(td_name), "/* Function not implemented */ 0" ); } else if( re->type == OBJ_PROCEDURE ) { - sprintf( td_name, "/* Procedure not implemented */ 0" ); + snprintf( td_name, sizeof(td_name), "/* Procedure not implemented */ 0" ); } else if( re->type == OBJ_RULE ) { - sprintf( td_name, "/* Rule not implemented */ 0" ); + snprintf( td_name, sizeof(td_name), "/* Rule not implemented */ 0" ); } else if( re->type == OBJ_ENTITY ) { - sprintf( td_name, "%s%s%s", + snprintf( td_name, sizeof(td_name), "%s%s%s", SCOPEget_name( ( ( Entity )re->object )->superscope ), ENT_PREFIX, ENTITYget_name( ( Entity )re->object ) ); } else { - sprintf( td_name, "/* %c from OBJ_? in expbasic.h not implemented */ 0", re->type ); + snprintf( td_name, sizeof(td_name), "/* %c from OBJ_? in expbasic.h not implemented */ 0", re->type ); } if( re->old != re->nnew ) { fprintf( file, " // object %s AS %s\n", re->old->name, diff --git a/src/exp2cxx/classes_attribute.c b/src/exp2cxx/classes_attribute.c index f304ba176..cf2de189d 100644 --- a/src/exp2cxx/classes_attribute.c +++ b/src/exp2cxx/classes_attribute.c @@ -10,22 +10,15 @@ The conventions used in this binding follow the proposed specification for the STEP Standard Data Access Interface as defined in document N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. *******************************************************************/ -#include #include #include #include -#include #include #include #include "classes.h" #include "classes_attribute.h" -#include - -#if defined(_MSC_VER) && _MSC_VER < 1900 -# include "sc_stdio.h" -# define snprintf c99_snprintf -#endif +#include "./trace_fprintf.h" extern int old_accessors; extern int print_logging; @@ -64,7 +57,7 @@ char * generate_attribute_name( Variable a, char * out ) { } } *q = '\0'; - sc_free( temp ); + free( temp ); return out; } @@ -102,7 +95,7 @@ bool attrIsObj( Type t ) { * \p attr_count_tmp is a _copy_ of attr_count */ void ATTRnames_print( Entity entity, FILE* file ) { - char attrnm [BUFSIZ]; + char attrnm [BUFSIZ+1]; LISTdo( ENTITYget_attributes( entity ), v, Variable ) { generate_attribute_name( v, attrnm ); @@ -121,7 +114,7 @@ void ATTRnames_print( Entity entity, FILE* file ) { * \param file file being written to */ void DataMemberPrintAttr( Entity entity, Variable a, FILE * file ) { - char attrnm [BUFSIZ]; + char attrnm [BUFSIZ+1]; const char * ctype, * etype; if( !VARget_inverse( a ) && ( VARget_initializer( a ) == EXPRESSION_NULL ) ) { ctype = TYPEget_ctype( VARget_type( a ) ); @@ -130,11 +123,24 @@ void DataMemberPrintAttr( Entity entity, Variable a, FILE * file ) { fprintf( stderr, "Warning: in entity %s, the type for attribute %s is not fully implemented\n", ENTITYget_name( entity ), attrnm ); } if( TYPEis_entity( VARget_type( a ) ) ) { - fprintf( file, " SDAI_Application_instance_ptr _%s;", attrnm ); + fprintf( file, " SDAI_Application_instance_ptr _%s = NULL;", attrnm ); } else if( TYPEis_aggregate( VARget_type( a ) ) ) { - fprintf( file, " %s_ptr _%s;", ctype, attrnm ); + fprintf( file, " %s_ptr _%s = NULL;", ctype, attrnm ); } else { - fprintf( file, " %s _%s;", ctype, attrnm ); + Class_Of_Type class = TYPEget_type(VARget_type(a)); + switch (class) { + case boolean_: + fprintf(file, " %s _%s = false;", ctype, attrnm); + break; + case integer_: + fprintf(file, " %s _%s = 0;", ctype, attrnm); + break; + case real_: + fprintf(file, " %s _%s = 0.0;", ctype, attrnm); + break; + default: + fprintf(file, " %s _%s;", ctype, attrnm); + } } if( VARget_optional( a ) ) { fprintf( file, " // OPTIONAL" ); @@ -165,8 +171,8 @@ void DataMemberPrintAttr( Entity entity, Variable a, FILE * file ) { void ATTRsign_access_methods( Variable a, FILE * file ) { Type t = VARget_type( a ); - char ctype [BUFSIZ]; - char attrnm [BUFSIZ]; + char ctype [BUFSIZ+1]; + char attrnm [BUFSIZ+1]; generate_attribute_func_name( a, attrnm ); @@ -208,8 +214,8 @@ void ATTRsign_access_methods( Variable a, FILE * file ) { ******************************************************************/ void ATTRprint_access_methods_get_head( const char * classnm, Variable a, FILE * file, bool returnsConst ) { Type t = VARget_type( a ); - char ctype [BUFSIZ]; /* return type of the get function */ - char funcnm [BUFSIZ]; /* name of member function */ + char ctype [BUFSIZ+1]; /* return type of the get function */ + char funcnm [BUFSIZ+1]; /* name of member function */ generate_attribute_func_name( a, funcnm ); strncpy( ctype, AccessType( t ), BUFSIZ ); ctype[BUFSIZ-1] = '\0'; @@ -240,8 +246,8 @@ void ATTRprint_access_methods_get_head( const char * classnm, Variable a, FILE * void ATTRprint_access_methods_put_head( const char * entnm, Variable a, FILE * file ) { Type t = VARget_type( a ); - char ctype [BUFSIZ]; - char funcnm [BUFSIZ]; + char ctype [BUFSIZ+1]; + char funcnm [BUFSIZ+1]; generate_attribute_func_name( a, funcnm ); @@ -442,7 +448,7 @@ void ATTRprint_access_methods_log_bool( const char * entnm, const char * attrnm, /** print access methods for inverse attrs, using iAMap */ void INVprint_access_methods( const char * entnm, const char * attrnm, const char * funcnm, const char * nm, const char * ctype, Variable a, FILE * file, Schema schema ) { - char iaName[BUFSIZ] = {0}; + char iaName[BUFSIZ+1] = {0}; snprintf( iaName, BUFSIZ - 1, "%s::%s%d%s%s", SCHEMAget_name( schema ), ATTR_PREFIX, a->idx, /* can it ever be anything but "I"? */ ( VARis_derived( a ) ? "D" : ( VARis_type_shifter( a ) ? "R" : ( VARget_inverse( a ) ? "I" : "" ) ) ), attrnm ); @@ -490,12 +496,12 @@ void INVprint_access_methods( const char * entnm, const char * attrnm, const cha void ATTRprint_access_methods( const char * entnm, Variable a, FILE * file, Schema schema ) { Type t = VARget_type( a ); Class_Of_Type classType; - char ctype [BUFSIZ]; /* type of data member */ - char attrnm [BUFSIZ]; - char membernm[BUFSIZ]; - char funcnm [BUFSIZ]; /* name of member function */ + char ctype [BUFSIZ+1]; /* type of data member */ + char attrnm [BUFSIZ+1]; + char membernm[BUFSIZ+1]; + char funcnm [BUFSIZ+1]; /* name of member function */ - char nm [BUFSIZ]; + char nm [BUFSIZ+1]; /* I believe nm has the name of the underlying type without Sdai in front of it */ if( TYPEget_name( t ) ) { strncpy( nm, FirstToUpper( TYPEget_name( t ) ), BUFSIZ - 1 ); diff --git a/src/exp2cxx/classes_entity.c b/src/exp2cxx/classes_entity.c index 10a6af92c..fe8b8e113 100644 --- a/src/exp2cxx/classes_entity.c +++ b/src/exp2cxx/classes_entity.c @@ -14,11 +14,16 @@ N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. /* this is used to add new dictionary calls */ /* #define NEWDICT */ -#include +#define _XOPEN_SOURCE /* for S_IFDIR */ +#include +#include +#include +#ifdef _WIN32 +# include +#endif /* _WIN32 */ #include -#include +#include #include -#include #include "classes.h" #include "classes_entity.h" #include "class_strings.h" @@ -26,11 +31,34 @@ N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. #include #include "rules.h" -#include +#include "./trace_fprintf.h" extern int multiple_inheritance; extern int old_accessors; +/* cross-platform mkdir */ +static int sc_mkdir( const char * path ) { + #ifdef _WIN32 + return mkdir( path ); + #else + return mkdir( path, 0777 ); + #endif /* _WIN32 */ +} + +/* return -1 if error, 0 if created, 1 if dir existed already */ +static int mkDirIfNone( const char * path ) { + struct stat s; + if( stat( path, &s ) != 0 ) { + if( errno == ENOENT ) { + return sc_mkdir( path ); + } + } else if( s.st_mode & S_IFDIR ) { + return 1; + } + /* either stat returned an error other than ENOENT, or 'path' exists but isn't a dir */ + return -1; +} + /* attribute numbering used to use a global variable attr_count. * it could be tricky keep the numbering consistent when making * changes, so this has been replaced with an added member in the @@ -59,7 +87,7 @@ void ENTITYnames_print( Entity entity, FILE * file ) { * \param schema schema being processed */ void LIBdescribe_entity( Entity entity, FILE * file, Schema schema ) { - char attrnm [BUFSIZ]; + char attrnm [BUFSIZ+1]; fprintf( file, "EntityDescriptor * %s::%s%s = 0;\n", SCHEMAget_name( schema ), ENT_PREFIX, ENTITYget_name( entity ) ); LISTdo( ENTITYget_attributes( entity ), v, Variable ) { @@ -81,7 +109,7 @@ void LIBdescribe_entity( Entity entity, FILE * file, Schema schema ) { void LIBmemberFunctionPrint( Entity entity, Linked_List neededAttr, FILE * file, Schema schema ) { Linked_List attr_list; - char entnm [BUFSIZ]; + char entnm [BUFSIZ+1]; strncpy( entnm, ENTITYget_classname( entity ), BUFSIZ ); /* assign entnm */ @@ -149,7 +177,7 @@ int get_attribute_number( Entity entity ) { * \p file file being written to */ void ENTITYhead_print( Entity entity, FILE * file ) { - char entnm [BUFSIZ]; + char entnm [BUFSIZ+1]; Linked_List list; Entity super = 0; @@ -180,7 +208,7 @@ void ENTITYhead_print( Entity entity, FILE * file ) { * skip inverse attrs */ void DataMemberInit( bool * first, Variable a, FILE * lib ) { - char attrnm [BUFSIZ]; + char attrnm [BUFSIZ+1]; if( VARis_derived( a ) || VARget_inverse( a ) ) { return; } @@ -244,7 +272,7 @@ void MemberFunctionSign( Entity entity, Linked_List neededAttr, FILE * file ) { Linked_List attr_list; static int entcode = 0; - char entnm [BUFSIZ]; + char entnm [BUFSIZ+1]; strncpy( entnm, ENTITYget_classname( entity ), BUFSIZ ); /* assign entnm */ entnm[BUFSIZ-1] = '\0'; @@ -328,7 +356,7 @@ void initializeAttrs( Entity e, FILE* file ) { void LIBstructor_print( Entity entity, Linked_List neededAttr, FILE * file, Schema schema ) { Linked_List attr_list; Type t; - char attrnm [BUFSIZ]; + char attrnm [BUFSIZ+1]; Linked_List list; Entity principalSuper = 0; @@ -489,13 +517,13 @@ void LIBstructor_print( Entity entity, Linked_List neededAttr, FILE * file, Sche void LIBstructor_print_w_args( Entity entity, Linked_List neededAttr, FILE * file, Schema schema ) { Linked_List attr_list; Type t; - char attrnm [BUFSIZ]; + char attrnm [BUFSIZ+1]; Linked_List list; int super_cnt = 0; /* added for calling parents constructor if there is one */ - char parentnm [BUFSIZ]; + char parentnm [BUFSIZ+1]; char * parent = 0; const char * entnm; @@ -599,8 +627,8 @@ void LIBstructor_print_w_args( Entity entity, Linked_List neededAttr, FILE * fil fprintf( file, " /* Put attribute on this class' attributes list so the access functions still work. */\n" ); fprintf( file, " attributes.push( a );\n" ); - fprintf( file, " /* Put attribute on the attributes list for the main inheritance hierarchy. **\n" ); - fprintf( file, " ** The push method rejects duplicates found by comparing attrDescriptor's. */\n" ); + fprintf( file, " /* Put attribute on the attributes list for the main inheritance hierarchy. */\n" ); + fprintf( file, " /* The push method rejects duplicates found by comparing attrDescriptor's. */\n" ); fprintf( file, " if( addAttrs ) {\n" ); fprintf( file, " se->attributes.push( a );\n }\n" ); @@ -676,7 +704,7 @@ char * generate_dict_attr_name( Variable a, char * out ) { } *q = '\0'; - sc_free( temp ); + free( temp ); return out; } @@ -690,8 +718,8 @@ char * generate_dict_attr_name( Variable a, char * out ) { void ENTITYincode_print( Entity entity, FILE * header, FILE * impl, Schema schema ) { #define entity_name ENTITYget_name(entity) #define schema_name SCHEMAget_name(schema) - char attrnm [BUFSIZ]; - char dict_attrnm [BUFSIZ]; + char attrnm [BUFSIZ+1]; + char dict_attrnm [BUFSIZ+1]; const char * super_schema; char * tmp, *tmp2; bool hasInverse = false; @@ -827,8 +855,8 @@ void ENTITYincode_print( Entity entity, FILE * header, FILE * impl, Schema schem ); } else { /* manufacture new one(s) on the spot */ - char typename_buf[MAX_LEN]; - print_typechain( header, impl, v->type, typename_buf, schema, v->name->symbol.name ); + char typename_buf[MAX_LEN+1]; + print_typechain( header, impl, v->type, typename_buf, sizeof(typename_buf), schema, v->name->symbol.name ); fprintf( impl, " %s::%s%d%s%s =\n new %s" "(\"%s\",%s,%s,%s%s,\n *%s::%s%s);\n", SCHEMAget_name( schema ), ATTR_PREFIX, v->idx, @@ -864,15 +892,15 @@ void ENTITYincode_print( Entity entity, FILE * header, FILE * impl, Schema schem if( VARis_derived( v ) && v->initializer ) { tmp = EXPRto_string( v->initializer ); - tmp2 = ( char * )sc_malloc( sizeof( char ) * ( strlen( tmp ) + BUFSIZ ) ); + tmp2 = ( char * )malloc( sizeof( char ) * ( strlen( tmp ) + BUFSIZ ) ); fprintf( impl, " %s::%s%d%s%s->initializer_(\"%s\");\n", schema_name, ATTR_PREFIX, v->idx, ( VARis_derived( v ) ? "D" : ( VARis_type_shifter( v ) ? "R" : ( VARget_inverse( v ) ? "I" : "" ) ) ), attrnm, format_for_stringout( tmp, tmp2 ) ); - sc_free( tmp ); - sc_free( tmp2 ); + free( tmp ); + free( tmp2 ); } if( VARget_inverse( v ) ) { fprintf( impl, " %s::%s%d%s%s->inverted_attr_id_(\"%s\");\n", @@ -957,7 +985,6 @@ void ENTITYPrint_cc( const Entity entity, FILE * createall, FILE * header, FILE DEBUG( "Entering ENTITYPrint_cc for %s\n", name ); fprintf( impl, "#include \"schema.h\"\n" ); - fprintf( impl, "#include \"sc_memmgr.h\"\n" ); fprintf( impl, "#include \"entity/%s.h\"\n\n", name ); LIBdescribe_entity( entity, impl, schema ); diff --git a/src/exp2cxx/classes_misc.c b/src/exp2cxx/classes_misc.c index 4b5226912..2b492a124 100644 --- a/src/exp2cxx/classes_misc.c +++ b/src/exp2cxx/classes_misc.c @@ -1,9 +1,7 @@ #define CLASSES_MISC_C -#include #include #include "classes.h" -#include #include "class_strings.h" /** \file classes_misc.c @@ -70,7 +68,7 @@ int isAggregateType( const Type t ) { /** \returns a pointer to a static buffer, containing a string which is the type used by the c++ data member access functions */ const char * AccessType( Type t ) { Class_Of_Type class; - static char nm [BUFSIZ]; + static char nm [BUFSIZ+1]; strncpy( nm, TypeName( t ), BUFSIZ - 4 ); if( TYPEis_entity( t ) ) { strcat( nm, "_ptr" ); @@ -102,7 +100,7 @@ const char * AccessType( Type t ) { */ const char * PrettyTmpName( const char * oldname ) { int i = 0; - static char newname [BUFSIZ]; + static char newname [BUFSIZ+1]; newname [0] = '\0'; while( ( oldname [i] != '\0' ) && ( i < BUFSIZ ) ) { newname [i] = ToLower( oldname [i] ); @@ -123,7 +121,7 @@ const char * PrettyTmpName( const char * oldname ) { /* This function is out of date DAS */ const char * EnumName( const char * oldname ) { int j = 0; - static char newname [MAX_LEN]; + static char newname [MAX_LEN+1]; if( !oldname ) { return ( "" ); } @@ -139,7 +137,7 @@ const char * EnumName( const char * oldname ) { const char * SelectName( const char * oldname ) { int j = 0; - static char newname [MAX_LEN]; + static char newname [MAX_LEN+1]; if( !oldname ) { return ( "" ); } @@ -203,7 +201,7 @@ const char * FundamentalType( const Type t, int report_reftypes ) { * TypeDescriptor or subtype of TypeDescriptor to represent Type t in the dictionary. */ const char * TypeDescriptorName( Type t ) { - static char b [BUFSIZ]; + static char b [BUFSIZ+1]; Schema parent = t->superscope; /* NOTE - I corrected a prev bug here in which the *current* schema was ** passed to this function. Now we take "parent" - the schema in which @@ -217,7 +215,7 @@ const char * TypeDescriptorName( Type t ) { ** by following through the entity they reference, as above. */ } - sprintf( b, "%s::%s%s", SCHEMAget_name( parent ), TYPEprefix( t ), + snprintf( b, sizeof(b), "%s::%s%s", SCHEMAget_name( parent ), TYPEprefix( t ), TYPEget_name( t ) ); return b; } @@ -322,7 +320,7 @@ Entity ENTITYput_superclass( Entity entity ) { LISTod; } - tag = ( EntityTag ) sc_malloc( sizeof( struct EntityTag_ ) ); + tag = ( EntityTag ) malloc( sizeof( struct EntityTag_ ) ); tag -> superclass = super; TYPEput_clientData( ENTITYget_type( entity ), ( ClientData ) tag ); return super; @@ -386,10 +384,10 @@ Variable VARis_type_shifter( Variable a ) { temp = EXPRto_string( VARget_name( a ) ); if( ! strncmp( StrToLower( temp ), "self\\", 5 ) ) { /* a is a type shifter */ - sc_free( temp ); + free( temp ); return a; } - sc_free( temp ); + free( temp ); return 0; } diff --git a/src/exp2cxx/classes_type.c b/src/exp2cxx/classes_type.c index 95c76dbb0..b4abdb034 100644 --- a/src/exp2cxx/classes_type.c +++ b/src/exp2cxx/classes_type.c @@ -14,18 +14,25 @@ N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. /* this is used to add new dictionary calls */ /* #define NEWDICT */ -#include -#include +#define _XOPEN_SOURCE /* for S_IFDIR */ +#include +#include +#include +#ifdef _WIN32 +# include +#endif /* _WIN32 */ + +#include #include +#include #include -#include #include "classes.h" #include "class_strings.h" #include "genCxxFilenames.h" #include #include "rules.h" -#include +#include "./trace_fprintf.h" static int type_count; /**< number each temporary type for same reason as \sa attr_count */ @@ -36,13 +43,66 @@ static void printEnumCreateBody( FILE *, const Type ); static void printEnumAggrCrHdr( FILE *, const Type ); static void printEnumAggrCrBody( FILE *, const Type ); -int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ); +int TYPEget_RefTypeVarNm( const Type t, char * buf, size_t buflen, Schema schema ); int isMultiDimAggregateType( const Type t ); void Type_Description( const Type, char * ); void TypeBody_Description( TypeBody body, char * buf ); +/* cross-platform mkdir */ +static int sc_mkdir( const char * path ) { + #ifdef _WIN32 + return mkdir( path ); + #else + return mkdir( path, 0777 ); + #endif /* _WIN32 */ +} + +/* return -1 if error, 0 if created, 1 if dir existed already */ +static int mkDirIfNone( const char * path ) { + struct stat s; + if( stat( path, &s ) != 0 ) { + if( errno == ENOENT ) { + return sc_mkdir( path ); + } + } else if( s.st_mode & S_IFDIR ) { + return 1; + } + /* either stat returned an error other than ENOENT, or 'path' exists but isn't a dir */ + return -1; +} + +#ifdef _WIN32 +/* for windows, rewrite backslashes in paths + * that will be written to generated code + */ +static const char * path2str_fn( const char * fileMacro ) { + static char * result = 0; + static size_t rlen = 0; + char * p; + if( rlen < strlen( fileMacro ) ) { + if( result ) { + free( result ); + } + rlen = strlen( fileMacro ); + result = ( char * )malloc( rlen * sizeof( char ) + 1 ); + } + strcpy( result, fileMacro ); + p = result; + while( *p ) { + if( *p == '\\' ) { + *p = '/'; + } + p++; + } + return result; +} +# define path2str(path) path2str_fn(path) +#else +# define path2str(path) path +#endif + /** write representation of expression to end of buf * * TODO: add buflen arg and check for overflow @@ -62,7 +122,7 @@ void strcat_expr( Expression e, char * buf ) { strcat( buf, TYPEget_name( e ) ); } else if( TYPEget_body( e->type )->type == integer_ ) { char tmpbuf[30]; - sprintf( tmpbuf, "%d", e->u.integer ); + snprintf( tmpbuf, sizeof(tmpbuf), "%d", e->u.integer ); strcat( buf, tmpbuf ); } else { strcat( buf, "??" ); @@ -101,16 +161,15 @@ void strcat_bounds( TypeBody b, char * buf ) { ** Change Date: 5/22/91 CD ******************************************************************/ const char * EnumCElementName( Type type, Expression expr ) { - static char buf [BUFSIZ]; - sprintf( buf, "%s__", + static char buf [BUFSIZ+1]; + snprintf( buf, sizeof(buf), "%s__", EnumName( TYPEget_name( type ) ) ); - strcat( buf, StrToLower( EXPget_name( expr ) ) ); - + strncat( buf, StrToLower( EXPget_name( expr ) ), BUFSIZ ); return buf; } char * CheckEnumSymbol( char * s ) { - static char b [BUFSIZ]; + static char b [BUFSIZ+1]; if( strcmp( s, "sdaiTRUE" ) && strcmp( s, "sdaiFALSE" ) && strcmp( s, "sdaiUNKNOWN" ) ) { @@ -153,8 +212,8 @@ char * TypeDescription( const Type t ) { void TYPEenum_inc_print( const Type type, FILE * inc ) { Expression expr; - char tdnm[BUFSIZ], - enumAggrNm[BUFSIZ]; + char tdnm[BUFSIZ+1], + enumAggrNm[BUFSIZ+1]; const char * n; /* pointer to class name */ int cnt = 0; @@ -221,7 +280,7 @@ void TYPEenum_inc_print( const Type type, FILE * inc ) { /* DAS brandnew above */ /* print things for aggregate class */ - sprintf( enumAggrNm, "%s_agg", n ); + snprintf( enumAggrNm, sizeof(enumAggrNm), "%s_agg", n ); fprintf( inc, "\nclass %s_agg : public EnumAggregate {\n", n ); @@ -250,7 +309,7 @@ void TYPEenum_lib_print( const Type type, FILE * f ) { DictionaryEntry de; Expression expr; const char * n; /* pointer to class name */ - char c_enum_ele [BUFSIZ]; + char c_enum_ele [BUFSIZ+1]; n = TYPEget_ctype( type ); @@ -318,7 +377,6 @@ void TYPEPrint_cc( const Type type, const filenames_t * names, FILE * hdr, FILE DEBUG( "Entering TYPEPrint_cc for %s\n", names->impl ); fprintf( impl, "#include \"schema.h\"\n" ); - fprintf( impl, "#include \"sc_memmgr.h\"\n" ); fprintf( impl, "#include \"%s\"\n\n", names->header ); if ( TYPEis_enumeration( type ) ) { @@ -380,7 +438,7 @@ static void printEnumCreateHdr( FILE * inc, const Type type ) { /** See header comment above by printEnumCreateHdr. */ static void printEnumCreateBody( FILE * lib, const Type type ) { const char * nm = TYPEget_ctype( type ); - char tdnm[BUFSIZ]; + char tdnm[BUFSIZ+1]; tdnm[BUFSIZ-1] = '\0'; strncpy( tdnm, TYPEtd_name( type ), BUFSIZ ); @@ -399,7 +457,7 @@ static void printEnumAggrCrHdr( FILE * inc, const Type type ) { static void printEnumAggrCrBody( FILE * lib, const Type type ) { const char * n = TYPEget_ctype( type ); - char tdnm[BUFSIZ]; + char tdnm[BUFSIZ+1]; strncpy( tdnm, TYPEtd_name( type ), BUFSIZ ); tdnm[BUFSIZ-1] = '\0'; @@ -424,7 +482,7 @@ static void printEnumAggrCrBody( FILE * lib, const Type type ) { ** Dec 2011 - MAP - remove goto **************************************************************************/ void TYPEprint_typedefs( Type t, FILE * classes ) { - char nm [BUFSIZ]; + char nm [BUFSIZ+1]; Type i; bool aggrNot1d = true; /* added so I can get rid of a goto */ @@ -506,10 +564,10 @@ void TYPEprint_typedefs( Type t, FILE * classes ) { TYPEprint_init() (below) which is done in exp2cxx's 1st pass only.) *****/ void TYPEprint_descriptions( const Type type, FILES * files, Schema schema ) { - char tdnm [BUFSIZ], - typename_buf [MAX_LEN], - base [BUFSIZ], - nm [BUFSIZ]; + char tdnm [BUFSIZ+1], + typename_buf [MAX_LEN+1], + base [BUFSIZ+1], + nm [BUFSIZ+1]; Type i; strncpy( tdnm, TYPEtd_name( type ), BUFSIZ ); @@ -552,7 +610,7 @@ void TYPEprint_descriptions( const Type type, FILES * files, Schema schema ) { return; } - if( !TYPEget_RefTypeVarNm( type, typename_buf, schema ) ) { + if( !TYPEget_RefTypeVarNm( type, typename_buf, sizeof(typename_buf), schema ) ) { if( TYPEis_enumeration( type ) ) { TYPEPrint( type, files, schema ); } /* so we don't do anything for non-enums??? */ @@ -563,8 +621,8 @@ void TYPEprint_descriptions( const Type type, FILES * files, Schema schema ) { } void TYPEprint_init( const Type type, FILE * header, FILE * impl, Schema schema ) { - char tdnm [BUFSIZ]; - char typename_buf[MAX_LEN]; + char tdnm [BUFSIZ+1]; + char typename_buf[MAX_LEN+1]; strncpy( tdnm, TYPEtd_name( type ), BUFSIZ ); @@ -575,7 +633,7 @@ void TYPEprint_init( const Type type, FILE * header, FILE * impl, Schema schema /* fill in the TD's values in the SchemaInit function (it is already declared with basic values) */ - if( TYPEget_RefTypeVarNm( type, typename_buf, schema ) ) { + if( TYPEget_RefTypeVarNm( type, typename_buf, sizeof(typename_buf), schema ) ) { fprintf( impl, " %s->ReferentType(%s);\n", tdnm, typename_buf ); } else { switch( TYPEget_body( type )->type ) { @@ -586,7 +644,7 @@ void TYPEprint_init( const Type type, FILE * header, FILE * impl, Schema schema case list_: { if( isMultiDimAggregateType( type ) ) { print_typechain( header, impl, TYPEget_body( type )->base, - typename_buf, schema, type->symbol.name ); + typename_buf, sizeof(typename_buf), schema, type->symbol.name ); fprintf( impl, " %s->ReferentType(%s);\n", tdnm, typename_buf ); } @@ -635,7 +693,7 @@ void TYPEprint_new( const Type type, FILE * create, Schema schema, bool needWR ) char * temp; temp = non_unique_types_string( type ); fprintf( create, " %s = new SelectTypeDescriptor (\n ~%s, //unique elements,\n", TYPEtd_name( type ), temp ); - sc_free( temp ); + free( temp ); TYPEprint_nm_ft_desc( schema, type, create, "," ); fprintf( create, " (SelectCreator) create_%s); // Creator function\n", SelectName( TYPEget_name( type ) ) ); } else { @@ -706,7 +764,10 @@ void TYPEprint_new( const Type type, FILE * create, Schema schema, bool needWR ) Nov 2011 - MAP - modified to insert scope operator into variable name. Reason: use of namespace for global variables */ -int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ) { +int TYPEget_RefTypeVarNm( const Type t, char * buf, size_t buflen, Schema schema ) { + + if (!buf || !buflen) + return 0; /* It looks like TYPEget_head(t) is true when processing a type that refers to another type. e.g. when processing "name" in: @@ -716,7 +777,7 @@ int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ) { it refers to another Express TYPE stmt */ /* it would be a reference_ type */ /* a TypeDescriptor of the form t_ */ - sprintf( buf, "%s::%s%s", + snprintf( buf, buflen, "%s::%s%s", SCHEMAget_name( TYPEget_head( t )->superscope ), TYPEprefix( t ), TYPEget_name( TYPEget_head( t ) ) ); return 1; @@ -731,7 +792,7 @@ int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ) { case number_: /* one of the SCL builtin TypeDescriptors of the form t_STRING_TYPE, or t_REAL_TYPE */ - sprintf( buf, "%s%s", TD_PREFIX, FundamentalType( t, 0 ) ); + snprintf( buf, buflen, "%s%s", TD_PREFIX, FundamentalType( t, 0 ) ); return 1; break; @@ -742,7 +803,7 @@ int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ) { break; case entity_: - sprintf( buf, "%s", TYPEtd_name( t ) ); + snprintf( buf, buflen, "%s", TYPEtd_name( t ) ); /* following assumes we are not in a nested entity */ /* otherwise we should search upward for schema */ return 1; @@ -758,7 +819,7 @@ int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ) { if( isMultiDimAggregateType( t ) ) { if( TYPEget_name( TYPEget_body( t )->base ) ) { - sprintf( buf, "%s::%s%s", + snprintf( buf, buflen, "%s::%s%s", SCHEMAget_name( TYPEget_body( t )->base->superscope ), TYPEprefix( t ), TYPEget_name( TYPEget_body( t )->base ) ); return 1; @@ -775,19 +836,19 @@ int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ) { if( TYPEget_body( TYPEget_body( t )->base )->type == enumeration_ || TYPEget_body( TYPEget_body( t )->base )->type == select_ ) { - sprintf( buf, "%s", TYPEtd_name( TYPEget_body( t )->base ) ); + snprintf( buf, buflen, "%s", TYPEtd_name( TYPEget_body( t )->base ) ); return 1; } else if( TYPEget_name( TYPEget_body( t )->base ) ) { if( TYPEget_body( TYPEget_body( t )->base )->type == entity_ ) { - sprintf( buf, "%s", TYPEtd_name( TYPEget_body( t )->base ) ); + snprintf( buf, buflen, "%s", TYPEtd_name( TYPEget_body( t )->base ) ); return 1; } - sprintf( buf, "%s::%s%s", + snprintf( buf, buflen, "%s::%s%s", SCHEMAget_name( TYPEget_body( t )->base->superscope ), TYPEprefix( t ), TYPEget_name( TYPEget_body( t )->base ) ); return 1; } - return TYPEget_RefTypeVarNm( TYPEget_body( t )->base, buf, schema ); + return TYPEget_RefTypeVarNm( TYPEget_body( t )->base, buf, buflen, schema ); } break; default: @@ -825,14 +886,14 @@ int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ) { that can be referenced to refer to the type that was created for Type t. */ -void print_typechain( FILE * header, FILE * impl, const Type t, char * buf, Schema schema, const char * type_name ) { +void print_typechain( FILE * header, FILE * impl, const Type t, char * buf, size_t buflen, Schema schema, const char * type_name ) { /* if we've been called, current type has no name */ /* nor is it a built-in type */ /* the type_count variable is there for debugging purposes */ const char * ctype = TYPEget_ctype( t ); int count = type_count++; - char name_buf[MAX_LEN]; + char name_buf[MAX_LEN+1]; int s; switch( TYPEget_body( t )->type ) { @@ -850,7 +911,7 @@ void print_typechain( FILE * header, FILE * impl, const Type t, char * buf, Sche " %s%d->AssignAggrCreator((AggregateCreator) create_%s);%s", TD_PREFIX, count, ctype, " // Creator function\n" ); - s = sprintf( name_buf, "%s%d", TD_PREFIX, count ); + s = snprintf( name_buf, sizeof(name_buf), "%s%d", TD_PREFIX, count ); assert( ( s > 0 ) && ( s < MAX_LEN ) ); AGGRprint_init( header, impl, t, name_buf, type_name ); @@ -873,19 +934,19 @@ void print_typechain( FILE * header, FILE * impl, const Type t, char * buf, Sche /* DAS ORIG SCHEMA FIX */ fprintf( impl, " %s%d->OriginatingSchema(%s::schema);\n", TD_PREFIX, count, SCHEMAget_name( schema ) ); - if( TYPEget_RefTypeVarNm( t, name_buf, schema ) ) { + if( TYPEget_RefTypeVarNm( t, name_buf, sizeof(name_buf), schema ) ) { fprintf( impl, " %s%d->ReferentType(%s);\n", TD_PREFIX, count, name_buf ); } else { Type base = 0; /* no name, recurse */ - char callee_buffer[MAX_LEN]; + char callee_buffer[MAX_LEN+1]; if( TYPEget_body( t ) ) { base = TYPEget_body( t )->base; } - print_typechain( header, impl, base, callee_buffer, schema, type_name ); + print_typechain( header, impl, base, callee_buffer, sizeof(callee_buffer), schema, type_name ); fprintf( impl, " %s%d->ReferentType(%s);\n", TD_PREFIX, count, callee_buffer ); } - sprintf( buf, "%s%d", TD_PREFIX, count ); + snprintf( buf, buflen, "%s%d", TD_PREFIX, count ); /* Types */ fprintf( impl, " %s::schema->AddUnnamedType(%s%d);\n", SCHEMAget_name( schema ), TD_PREFIX, count ); @@ -1026,10 +1087,10 @@ void TypeBody_Description( TypeBody body, char * buf ) { } const char * IdlEntityTypeName( Type t ) { - static char name [BUFSIZ]; - strcpy( name, TYPE_PREFIX ); + static char name [BUFSIZ+1]; + strncpy( name, TYPE_PREFIX, BUFSIZ ); if( TYPEget_name( t ) ) { - strcpy( name, FirstToUpper( TYPEget_name( t ) ) ); + strncpy( name, FirstToUpper( TYPEget_name( t ) ), BUFSIZ ); } else { return TYPEget_ctype( t ); } @@ -1039,7 +1100,7 @@ const char * IdlEntityTypeName( Type t ) { const char * GetAggrElemType( const Type type ) { Class_Of_Type class; Type bt; - static char retval [BUFSIZ]; + static char retval [BUFSIZ+1]; if( isAggregateType( type ) ) { bt = TYPEget_nonaggregate_base_type( type ); @@ -1062,14 +1123,14 @@ const char * GetAggrElemType( const Type type ) { /* case TYPE_ENTITY: */ if( class == entity_ ) { - strcpy( retval, IdlEntityTypeName( bt ) ); + strncpy( retval, IdlEntityTypeName( bt ), BUFSIZ ); } /* case TYPE_ENUM: */ /* case TYPE_SELECT: */ if( ( class == enumeration_ ) || ( class == select_ ) ) { - strcpy( retval, TYPEget_ctype( bt ) ); + strncpy( retval, TYPEget_ctype( bt ), BUFSIZ ); } /* case TYPE_LOGICAL: */ @@ -1097,7 +1158,7 @@ const char * GetAggrElemType( const Type type ) { const char * TYPEget_idl_type( const Type t ) { Class_Of_Type class; - static char retval [BUFSIZ]; + static char retval [BUFSIZ+1]; /* aggregates are based on their base type case TYPE_ARRAY: @@ -1166,18 +1227,14 @@ const char * TYPEget_idl_type( const Type t ) { /* case TYPE_ENTITY: */ if( class == entity_ ) { /* better do this because the return type might go away */ - strcpy( retval, IdlEntityTypeName( t ) ); + strncpy( retval, IdlEntityTypeName( t ), BUFSIZ - 4 ); strcat( retval, "_ptr" ); return retval; } /* case TYPE_ENUM: */ /* case TYPE_SELECT: */ if( class == enumeration_ ) { - strncpy( retval, EnumName( TYPEget_name( t ) ), BUFSIZ - 2 ); - - strcat( retval, " /*" ); - strcat( retval, IdlEntityTypeName( t ) ); - strcat( retval, "*/ " ); + snprintf( retval, BUFSIZ, "%s /*%s*/ ", EnumName(TYPEget_name(t)), IdlEntityTypeName(t) ); return retval; } if( class == select_ ) { @@ -1202,9 +1259,8 @@ const char * TYPEget_idl_type( const Type t ) { char * TYPEget_express_type( const Type t ) { Class_Of_Type class; Type bt; - char retval [BUFSIZ]; - char * n, * permval, * aggr_type; - + char retval [BUFSIZ+1] = {'\0'}; + char * n = NULL, * permval = NULL, * aggr_type = NULL; /* 1. "DEFINED" types */ /* case TYPE_ENUM: */ @@ -1272,12 +1328,12 @@ char * TYPEget_express_type( const Type t ) { aggr_type = "Bag"; } - sprintf( retval, "%s of %s", + snprintf( retval, sizeof(retval), "%s of %s", aggr_type, TYPEget_express_type( bt ) ); /* this will declare extra memory when aggregate is > 1D */ - permval = ( char * )sc_malloc( strlen( retval ) * sizeof( char ) + 1 ); + permval = ( char * )malloc( strlen( retval ) * sizeof( char ) + 1 ); strcpy( permval, retval ); return permval; @@ -1294,7 +1350,9 @@ char * TYPEget_express_type( const Type t ) { void AGGRprint_bound( FILE * header, FILE * impl, const char * var_name, const char * aggr_name, const char * cname, Expression bound, int boundNr ) { if( bound->symbol.resolved ) { if( bound->type == Type_Funcall ) { - fprintf( impl, " %s->SetBound%dFromExpressFuncall( \"%s\" );\n", var_name, boundNr, EXPRto_string( bound ) ); + char *bound_str = EXPRto_string(bound); + fprintf( impl, " %s->SetBound%dFromExpressFuncall( \"%s\" );\n", var_name, boundNr, bound_str ); + free(bound_str); } else { fprintf( impl, " %s->SetBound%d( %d );\n", var_name, boundNr, bound->u.integer ); } diff --git a/src/exp2cxx/classes_type.h b/src/exp2cxx/classes_type.h index a15815b07..f2fc0370c 100644 --- a/src/exp2cxx/classes_type.h +++ b/src/exp2cxx/classes_type.h @@ -26,6 +26,6 @@ void TYPEselect_lib_print( const Type type, FILE * f ); void AGGRprint_init( FILE * header, FILE * impl, const Type t, const char * var_name, const char * aggr_name ); -void print_typechain( FILE * header, FILE * impl, const Type t, char * buf, Schema schema, const char * type_name ); +void print_typechain( FILE * header, FILE * impl, const Type t, char * buf, size_t buflen, Schema schema, const char * type_name ); #endif diff --git a/src/exp2cxx/classes_wrapper.cc b/src/exp2cxx/classes_wrapper.cc index 874491ee7..e99f27e39 100644 --- a/src/exp2cxx/classes_wrapper.cc +++ b/src/exp2cxx/classes_wrapper.cc @@ -4,9 +4,8 @@ #include "complexSupport.h" #include "class_strings.h" -#include -#include +#include "./trace_fprintf.h" /******************************************************************* ** FedEx parser output module for generating C++ class definitions @@ -76,12 +75,12 @@ void print_file_header( FILES * files ) { fprintf( files->incall, "#include \n" ); fprintf( files->incall, "#endif\n" ); - fprintf( files->incall, "#include \n\n" ); - fprintf( files->incall, "\n#include \n" ); - fprintf( files->incall, "\n#include \n" ); - fprintf( files->incall, "\n#include \n" ); - fprintf( files->incall, "\n#include \n" ); - fprintf( files->incall, "\n#include \n" ); + fprintf( files->incall, "#include \"clstepcore/sdai.h\"\n\n" ); + fprintf( files->incall, "\n#include \"clstepcore/Registry.h\"\n" ); + fprintf( files->incall, "\n#include \"clstepcore/STEPaggregate.h\"\n" ); + fprintf( files->incall, "\n#include \"clstepcore/STEPundefined.h\"\n" ); + fprintf( files->incall, "\n#include \"clstepcore/ExpDict.h\"\n" ); + fprintf( files->incall, "\n#include \"clstepcore/STEPattribute.h\"\n" ); fprintf( files->incall, "\n#include \n" ); @@ -91,7 +90,6 @@ void print_file_header( FILES * files ) { files -> initall = FILEcreate( "schema.cc" ); fprintf( files->initall, "\n// in the exp2cxx source code, this file is generally referred to as files->initall or schemainit\n" ); fprintf( files->initall, "#include \"schema.h\"\n" ); - fprintf( files->initall, "#include \"sc_memmgr.h\"\n" ); fprintf( files->initall, "class Registry;\n" ); fprintf( files->initall, "\nvoid SchemaInit (Registry & reg) {\n" ); @@ -105,7 +103,6 @@ void print_file_header( FILES * files ) { files -> create = FILEcreate( "SdaiAll.cc" ); fprintf( files->create, "\n// in the exp2cxx source code, this file is generally referred to as files->create or createall\n" ); fprintf( files->create, "#include \"schema.h\"\n" ); - fprintf( files->create, "#include \"sc_memmgr.h\"\n" ); fprintf( files->create, "\nvoid InitSchemasAndEnts (Registry & reg) {\n" ); // This file declares all entity classes as incomplete types. This will @@ -386,7 +383,8 @@ void INITFileFinish( FILE * initfile, Schema schema ) { ******************************************************************/ void SCHEMAprint( Schema schema, FILES * files, void * complexCol, int suffix ) { int ocnt = 0; - char schnm[MAX_LEN], sufnm[MAX_LEN], fnm[MAX_LEN], *np; + size_t remaining; + char schnm[MAX_LEN+1], sufnm[MAX_LEN+1], fnm[MAX_LEN+1], *np; /* sufnm = schema name + suffix */ FILE * libfile, * incfile, @@ -401,7 +399,7 @@ void SCHEMAprint( Schema schema, FILES * files, void * complexCol, int suffix ) /********** create files based on name of schema ***********/ /* return if failure */ /* 1. header file */ - sprintf( schnm, "%s%s", SCHEMA_FILE_PREFIX, StrToUpper( SCHEMAget_name( schema ) ) ); //TODO change file names to CamelCase? + snprintf( schnm, sizeof(schnm), "%s%s", SCHEMA_FILE_PREFIX, StrToUpper( SCHEMAget_name( schema ) ) ); //TODO change file names to CamelCase? if( suffix == 0 ) { ocnt = snprintf( sufnm, MAX_LEN, "%s", schnm ); if( ocnt > MAX_LEN ) { @@ -424,14 +422,14 @@ void SCHEMAprint( Schema schema, FILES * files, void * complexCol, int suffix ) fprintf( files->inc, "\n// in the exp2cxx source code, this file is generally referred to as files->inc or incfile\n" ); fprintf( incfile, "#include \"schema.h\"\n" ); - fprintf( incfile, "#include \"sc_memmgr.h\"\n" ); np = fnm + strlen( fnm ) - 1; /* point to end of constant part of string */ + remaining = (size_t)(fnm + sizeof(fnm) - np); /* 1.9 open/init unity files which allow faster compilation with fewer translation units */ initUnityFiles( sufnm, files ); /* 2. class source file */ - sprintf( np, "cc" ); + snprintf( np, remaining, "cc" ); if( !( libfile = ( files -> lib ) = FILEcreate( fnm ) ) ) { return; } @@ -440,12 +438,11 @@ void SCHEMAprint( Schema schema, FILES * files, void * complexCol, int suffix ) //TODO: Looks like this switches between 'schema.h' and a non-generic name. What is that name, //and how do we fully enable this feature (i.e. how to write the file with different name)? #ifdef SCHEMA_HANDLING - sprintf( np, "h" ); + snprintf( np, remaining, "h" ); fprintf( libfile, "#include <%s.h> \n", sufnm ); #else fprintf( libfile, "#include \"schema.h\"\n" ); #endif - fprintf( libfile, "#include \"sc_memmgr.h\"\n" ); fprintf( libfile, "\n#ifdef SC_LOGGING \n" @@ -499,8 +496,7 @@ void SCHEMAprint( Schema schema, FILES * files, void * complexCol, int suffix ) "#include \"schema.h\"\n" "#endif\n" ); #endif - fprintf( initfile, "#include \n#include \n" ); - fprintf( initfile, "#include \n" ); + fprintf( initfile, "#include \"clstepcore/Registry.h\"\n#include \n" ); fprintf( initfile, "\nvoid %sInit (Registry& reg) {\n", schnm ); @@ -628,7 +624,8 @@ void getMCPrint( Express express, FILE * schema_h, FILE * schema_cc ) { ** Status: 24-Feb-1992 new -kcm ******************************************************************/ void EXPRESSPrint( Express express, ComplexCollect & col, FILES * files ) { - char fnm [MAX_LEN], *np; + char fnm [MAX_LEN+1], *np; + size_t remaining; const char * schnm; /* schnm is really "express name" */ FILE * libfile; FILE * incfile; @@ -643,19 +640,20 @@ void EXPRESSPrint( Express express, ComplexCollect & col, FILES * files ) { /********** create files based on name of schema ***********/ /* return if failure */ /* 1. header file */ - sprintf( fnm, "%s.h", schnm = ClassName( EXPRESSget_basename( express ) ) ); + snprintf( fnm, sizeof(fnm), "%s.h", schnm = ClassName( EXPRESSget_basename( express ) ) ); if( !( incfile = ( files -> inc ) = FILEcreate( fnm ) ) ) { return; } fprintf( files->inc, "\n// in the exp2cxx source code, this file is generally referred to as files->inc or incfile\n" ); - fprintf( incfile, "#include \n" ); + fprintf( incfile, "#include \"core/sdai.h\" \n" ); np = fnm + strlen( fnm ) - 1; /* point to end of constant part of string */ + remaining = (size_t)(fnm + sizeof(fnm) - np); /* 1.9 init unity files (large translation units, faster compilation) */ initUnityFiles( schnm, files ); /* 2. class source file */ - sprintf( np, "cc" ); + snprintf( np, remaining, "cc" ); if( !( libfile = ( files -> lib ) = FILEcreate( fnm ) ) ) { return; } @@ -664,7 +662,7 @@ void EXPRESSPrint( Express express, ComplexCollect & col, FILES * files ) { fprintf( libfile, "#include \"%s.h\" n", schnm ); // 3. header for namespace to contain all formerly-global variables - sprintf( fnm, "%sNames.h", schnm ); + snprintf( fnm, sizeof(fnm), "%sNames.h", schnm ); if( !( files->names = FILEcreate( fnm ) ) ) { return; } @@ -676,7 +674,7 @@ void EXPRESSPrint( Express express, ComplexCollect & col, FILES * files ) { /* 4. source code to initialize entity registry */ /* prints header of file for input function */ - sprintf( np, "init.cc" ); + snprintf( np, remaining, "init.cc" ); if( !( initfile = ( files -> init ) = FILEcreate( fnm ) ) ) { return; } diff --git a/src/exp2cxx/collect.cc b/src/exp2cxx/collect.cc index d12db7346..a50b808be 100644 --- a/src/exp2cxx/collect.cc +++ b/src/exp2cxx/collect.cc @@ -12,7 +12,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include void ComplexCollect::insert( ComplexList * c ) /* diff --git a/src/exp2cxx/complexSupport.h b/src/exp2cxx/complexSupport.h index 8277a03fa..f285c506d 100644 --- a/src/exp2cxx/complexSupport.h +++ b/src/exp2cxx/complexSupport.h @@ -73,7 +73,7 @@ class EntNode { public: EntNode( const char * nm = "" ) : next( 0 ), mark( NOMARK ), multSupers( 0 ) { - strcpy( name, nm ); + strncpy( name, nm, BUFSIZ ); } EntNode( char *[] ); // given a list, create a linked list of EntNodes ~EntNode() { @@ -116,7 +116,7 @@ class EntNode { private: MarkType mark; - char name[BUFSIZ]; + char name[BUFSIZ+1]; int multSupers; // do I correspond to an entity with >1 supertype? }; @@ -225,7 +225,7 @@ class SimpleList : public EntList { void write( ostream & ); private: - char name[BUFSIZ]; // Name of entity we correspond to. + char name[BUFSIZ+1]; // Name of entity we correspond to. MarkType I_marked; // Did I mark, and with what type of mark. }; diff --git a/src/exp2cxx/complexlist.cc b/src/exp2cxx/complexlist.cc index 2a42c6d96..485f0609d 100644 --- a/src/exp2cxx/complexlist.cc +++ b/src/exp2cxx/complexlist.cc @@ -11,7 +11,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include ComplexList::~ComplexList() /* diff --git a/src/exp2cxx/entlist.cc b/src/exp2cxx/entlist.cc index e27114294..bd45be671 100644 --- a/src/exp2cxx/entlist.cc +++ b/src/exp2cxx/entlist.cc @@ -14,7 +14,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include int EntList::siblings() /* diff --git a/src/exp2cxx/entnode.cc b/src/exp2cxx/entnode.cc index 50f3a8659..569dcde87 100644 --- a/src/exp2cxx/entnode.cc +++ b/src/exp2cxx/entnode.cc @@ -12,7 +12,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include EntNode::EntNode( char * namelist[] ) /* diff --git a/src/exp2cxx/expressbuild.cc b/src/exp2cxx/expressbuild.cc index a1c665656..d55465eef 100644 --- a/src/exp2cxx/expressbuild.cc +++ b/src/exp2cxx/expressbuild.cc @@ -12,7 +12,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include // Local function prototypes: static void initEnts( Express ); @@ -286,7 +285,7 @@ void ComplexList::addImplicitSubs( Linked_List subs, ComplexCollect * col ) AndOrList * ao = 0; LISTdo( subs, subEnt, Entity ) - strcpy( node.name, ENTITYget_name( subEnt ) ); + strncpy( node.name, ENTITYget_name( subEnt ), BUFSIZ ); if( !contains( &node ) ) { // We've found an implicit subtype. #ifdef COMPLEX_INFO diff --git a/src/exp2cxx/fedex_main.c b/src/exp2cxx/fedex_main.c index 81c6f1515..b83976daf 100644 --- a/src/exp2cxx/fedex_main.c +++ b/src/exp2cxx/fedex_main.c @@ -72,13 +72,12 @@ * Added * to typedefs. Replaced warning kludges with ERRORoption. */ -#include #include #include #include "../express/express.h" #include "../express/resolve.h" -#include +#include "./trace_fprintf.h" extern void print_fedex_version( void ); diff --git a/src/exp2cxx/genCxxFilenames.c b/src/exp2cxx/genCxxFilenames.c index 47004e43d..14bee4295 100644 --- a/src/exp2cxx/genCxxFilenames.c +++ b/src/exp2cxx/genCxxFilenames.c @@ -1,11 +1,6 @@ #include "genCxxFilenames.h" #include "class_strings.h" -#if defined(_MSC_VER) && _MSC_VER < 1900 -# include "sc_stdio.h" -# define snprintf c99_snprintf -#endif - /** \file genCxxFilenames.c * functions shared by exp2cxx and the schema scanner. * The latter creates, at configuration time, a list @@ -17,8 +12,8 @@ */ /* these buffers are shared amongst (and potentially overwritten by) all functions in this file */ -char impl[ BUFSIZ ] = {0}; -char header[ BUFSIZ ] = {0}; +char impl[ BUFSIZ+1 ] = {0}; +char header[ BUFSIZ+1 ] = {0}; /* struct containing pointers to above buffers. pointers are 'const char *' */ filenames_t fnames = { impl, header }; diff --git a/src/exp2cxx/match-ors.cc b/src/exp2cxx/match-ors.cc index 1b86622e4..41d5af88c 100644 --- a/src/exp2cxx/match-ors.cc +++ b/src/exp2cxx/match-ors.cc @@ -14,7 +14,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include MatchType AndOrList::matchORs( EntNode * ents ) /* diff --git a/src/exp2cxx/multlist.cc b/src/exp2cxx/multlist.cc index fb74cf5d1..5d2cade84 100644 --- a/src/exp2cxx/multlist.cc +++ b/src/exp2cxx/multlist.cc @@ -13,7 +13,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include MultList::~MultList() /* diff --git a/src/exp2cxx/multpass.c b/src/exp2cxx/multpass.c index 51a210ecb..03e1eb885 100644 --- a/src/exp2cxx/multpass.c +++ b/src/exp2cxx/multpass.c @@ -31,11 +31,10 @@ * Date: 04/09/97 * *****************************************************************************/ -#include #include #include "classes.h" -#include +#include "./trace_fprintf.h" int isAggregateType( const Type t ); @@ -160,7 +159,7 @@ void print_schemas_separate( Express express, void * complexCol, FILES * files ) // which hasn't been closed yet. (That's done on 2nd line below.)) */ fprintf( files->initall, " reg.SetCompCollect( gencomplex() );\n" ); fprintf( files->initall, "}\n\n" ); - fprintf( files->incall, "\n#include \n" ); + fprintf( files->incall, "\n#include \"clstepcore/complexSupport.h\"\n" ); fprintf( files->incall, "ComplexCollect *gencomplex();\n" ); /* Function GetModelContents() is printed at the end of the schema.xx @@ -189,7 +188,7 @@ static void initializeMarks( Express express ) DICTdo_type_init( express->symbol_table, &de_sch, OBJ_SCHEMA ); while( ( schema = ( Scope )DICTdo( &de_sch ) ) != 0 ) { schema->search_id = UNPROCESSED; - schema->clientData = ( int * )sc_malloc( sizeof( int ) ); + schema->clientData = ( int * )malloc( sizeof( int ) ); *( int * )schema->clientData = 0; SCOPEdo_entities( schema, ent, de_ent ) ent->search_id = NOTKNOWN; @@ -207,7 +206,7 @@ static void cleanupMarks( Express express ) { DICTdo_type_init( express->symbol_table, &de_sch, OBJ_SCHEMA ); while( ( schema = ( Scope )DICTdo( &de_sch ) ) != 0 ) { if( schema->clientData ) { - sc_free( schema->clientData ); + free( schema->clientData ); schema->clientData = NULL; } } @@ -608,7 +607,7 @@ static int inSchema( Scope scope, Scope super ) static void addRenameTypedefs( Schema schema, FILE * classes ) { DictionaryEntry de; Type i; - char nm[BUFSIZ], basenm[BUFSIZ]; + char nm[BUFSIZ+1], basenm[BUFSIZ+1]; static bool firsttime = true; SCOPEdo_types( schema, t, de ) { @@ -654,7 +653,7 @@ static void addAggrTypedefs( Schema schema, FILE * classes ) { DictionaryEntry de; Type i; static bool firsttime = true; - char nm[BUFSIZ]; + char nm[BUFSIZ+1]; SCOPEdo_types( schema, t, de ) { if( TYPEis_aggregate( t ) ) { @@ -691,7 +690,7 @@ static void addUseRefNames( Schema schema, FILE * create ) { Dictionary useRefDict; DictionaryEntry de; Rename * rnm; - char * oldnm, schNm[BUFSIZ]; + char * oldnm, schNm[BUFSIZ+1]; static bool firsttime = true; if( ( useRefDict = schema->u.schema->usedict ) != NULL ) { diff --git a/src/exp2cxx/non-ors.cc b/src/exp2cxx/non-ors.cc index 2ef5dd803..6b05bb378 100644 --- a/src/exp2cxx/non-ors.cc +++ b/src/exp2cxx/non-ors.cc @@ -11,7 +11,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include MatchType SimpleList::matchNonORs( EntNode * ents ) /* diff --git a/src/exp2cxx/orlist.cc b/src/exp2cxx/orlist.cc index dd0c9db88..809804320 100644 --- a/src/exp2cxx/orlist.cc +++ b/src/exp2cxx/orlist.cc @@ -11,7 +11,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include int OrList::hit( const char * nm ) /* diff --git a/src/exp2cxx/print.cc b/src/exp2cxx/print.cc index 0b1398a6d..b338c5954 100644 --- a/src/exp2cxx/print.cc +++ b/src/exp2cxx/print.cc @@ -8,7 +8,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include // Local function prototypes: static char * joinText( JoinType, char * ); diff --git a/src/exp2cxx/selects.c b/src/exp2cxx/selects.c index afd490832..5d975cdde 100644 --- a/src/exp2cxx/selects.c +++ b/src/exp2cxx/selects.c @@ -16,13 +16,12 @@ N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. extern int multiple_inheritance; -#include #include #include "classes.h" #include "classes_type.h" #include "classes_attribute.h" -#include +#include "./trace_fprintf.h" #define BASE_SELECT "SDAI_Select" @@ -123,7 +122,7 @@ static int compareOrigTypes( Type a, Type b ) { compareOrigTypes() above). */ const char * utype_member( const Linked_List list, const Type check, int rename ) { - static char r [BUFSIZ]; + static char r [BUFSIZ+1]; bool checkIsEntity = TYPEis_entity( check ); LISTdo( list, t, Type ) { @@ -244,7 +243,7 @@ int unique_types( const Linked_List list ) { RETURNS 1 if true, else 0. */ int duplicate_utype_member( const Linked_List list, const Type check ) { - char b [BUFSIZ]; + char b [BUFSIZ+1]; if( TYPEis_entity( check ) ) { return FALSE; @@ -397,7 +396,7 @@ char * non_unique_types_string( const Type type ) { non_unique_types_vector( type, tvec ); /* build type string from vector */ - typestr = ( char * )sc_malloc( BUFSIZ ); + typestr = ( char * )malloc( BUFSIZ + 1 ); typestr[0] = '\0'; strcat( typestr, ( char * )"(" ); for( i = 0; i <= tnumber; i++ ) { @@ -450,8 +449,8 @@ char * non_unique_types_string( const Type type ) { * \returns the attribute 'check' if an attribute with the same name is on the list, 0 otherwise */ Variable ATTR_LISTmember( Linked_List l, Variable check ) { - char nm [BUFSIZ]; - char cur [BUFSIZ]; + char nm [BUFSIZ+1]; + char cur [BUFSIZ+1]; generate_attribute_name( check, nm ); LISTdo( l, a, Variable ) { @@ -494,9 +493,9 @@ Linked_List SEL_TYPEgetnew_attribute_list( const Type type ) { void TYPEselect_inc_print_vars( const Type type, FILE * f, Linked_List dups ) { int size, j; Linked_List data_members = SELgetnew_dmlist( type ); - char dmname [BUFSIZ], - classnm [BUFSIZ], - tdnm [BUFSIZ]; + char dmname [BUFSIZ+1], + classnm [BUFSIZ+1], + tdnm [BUFSIZ+1]; strncpy( classnm, SelectName( TYPEget_name( type ) ), BUFSIZ ); classnm[BUFSIZ-1] = '\0'; @@ -583,8 +582,8 @@ void TYPEselect_inc_print_vars( const Type type, FILE * f, Linked_List dups ) { * class. */ void TYPEselect_inc_print( const Type type, FILE * f ) { - char n[BUFSIZ]; /* class name */ - char tdnm [BUFSIZ]; /* TypeDescriptor name */ + char n[BUFSIZ+1]; /* class name */ + char tdnm [BUFSIZ+1]; /* TypeDescriptor name */ Linked_List dups; int dup_result; Linked_List attrs; @@ -708,8 +707,8 @@ void TYPEselect_inc_print( const Type type, FILE * f ) { void TYPEselect_lib_print_part_one( const Type type, FILE * f, Linked_List dups, char * n ) { #define schema_name SCHEMAget_name(schema) - char tdnm[BUFSIZ], - nm[BUFSIZ]; + char tdnm[BUFSIZ+1], + nm[BUFSIZ+1]; int size = strlen( n ) * 2 + 4, j; /* size - for formatting output */ strncpy( tdnm, TYPEtd_name( type ), BUFSIZ ); @@ -741,7 +740,11 @@ void TYPEselect_lib_print_part_one( const Type type, FILE * f, if( ( TYPEis_entity( t ) ) || ( !utype_member( dups, t, 1 ) ) ) { if( isAggregateType( t ) && ( t->u.type->body->base ) ) { fprintf( f, " _%s = new %s;\n", SEL_ITEMget_dmname( t ), TYPEget_utype( t ) ); - } + } else if (TYPEis_entity(t)) { + // Per TYPEget_utype, any TYPEis_entity is an + // SDAI_Application_instance_ptr - initialize it here. + fprintf(f, " _%s = NULL;\n", SEL_ITEMget_dmname(t)); + } } } LISTod fprintf( f, " nullify();\n" ); @@ -1049,10 +1052,10 @@ void TYPEselect_lib_part_three_getter( const Type type, const char * classnm, co void TYPEselect_lib_print_part_three( const Type type, FILE * f, char * classnm ) { #define ENTITYget_type(e) ((e)->u.entity->type) - char uent[BUFSIZ], /* name of underlying entity type */ - utype[BUFSIZ], /* underlying type name */ - attrnm [BUFSIZ], /* attribute name -> data member = _attrnm */ - funcnm[BUFSIZ]; /* access function name = Attrnm */ + char uent[BUFSIZ+1], /* name of underlying entity type */ + utype[BUFSIZ+1], /* underlying type name */ + attrnm [BUFSIZ+1], /* attribute name -> data member = _attrnm */ + funcnm[BUFSIZ+1]; /* access function name = Attrnm */ Linked_List items = SEL_TYPEget_items( type ); /* all the items in the select type */ Linked_List attrs = SEL_TYPEgetnew_attribute_list( type ); @@ -1151,7 +1154,7 @@ void TYPEselect_lib_print_part_three( const Type type, FILE * f, char * classnm * TYPEselect_lib_print_part_four prints part 4 of the SDAI document of a select class. */ void TYPEselect_lib_print_part_four( const Type type, FILE * f, Linked_List dups, char * n ) { - char x[BUFSIZ]; + char x[BUFSIZ+1]; fprintf( f, "\n // part 4\n" ); @@ -1280,7 +1283,7 @@ void TYPEselect_init_print( const Type type, FILE * f ) { } void TYPEselect_lib_part21( const Type type, FILE * f ) { - char n[BUFSIZ]; /* pointers to class name(s) */ + char n[BUFSIZ+1]; /* pointers to class name(s) */ const char * dm; /* data member name */ Linked_List data_members = SELgetnew_dmlist( type ); @@ -1554,7 +1557,7 @@ void TYPEselect_lib_part21( const Type type, FILE * f ) { void TYPEselect_lib_StrToVal( const Type type, FILE * f ) { - char n[BUFSIZ]; /* pointers to class name */ + char n[BUFSIZ+1]; /* pointers to class name */ Linked_List data_members = SELgetnew_dmlist( type ); int enum_cnt = 0; @@ -1713,7 +1716,7 @@ void SELlib_print_protected( const Type type, FILE * f ) { * TYPEselect_lib_print prints the member functions (definitions) of a select class. */ void TYPEselect_lib_print( const Type type, FILE * f ) { - char n[BUFSIZ], m[BUFSIZ]; + char n[BUFSIZ+1], m[BUFSIZ+1]; const char * z; /* pointers to class name(s) */ Linked_List dups; int dup_result; @@ -1850,7 +1853,7 @@ void TYPEselect_lib_print( const Type type, FILE * f ) { void TYPEselect_print( Type t, FILES * files, Schema schema ) { SelectTag tag, tmp; Type i, bt; /* type of elements in an aggregate */ - char nm[BUFSIZ], tdnm[BUFSIZ]; + char nm[BUFSIZ+1], tdnm[BUFSIZ+1]; FILE * inc = files->inc; /* if type is already marked, return */ @@ -1862,7 +1865,7 @@ void TYPEselect_print( Type t, FILES * files, Schema schema ) { } /* mark the type as being processed */ - tag = ( SelectTag ) sc_malloc( sizeof( struct SelectTag_ ) ); + tag = ( SelectTag ) malloc( sizeof( struct SelectTag_ ) ); tag -> started = 1; tag -> complete = 0; TYPEput_clientData( t, ( ClientData ) tag ); @@ -1934,7 +1937,7 @@ void TYPEselect_print( Type t, FILES * files, Schema schema ) { DAR - moved to TYPEprint_init() - to keep init info together. */ tag -> complete = 1; - sc_free( tag ); + free( tag ); } #undef BASE_SELECT diff --git a/src/base/sc_trace_fprintf.c b/src/exp2cxx/trace_fprintf.c similarity index 92% rename from src/base/sc_trace_fprintf.c rename to src/exp2cxx/trace_fprintf.c index 95ca6b9c6..3a3838d67 100644 --- a/src/base/sc_trace_fprintf.c +++ b/src/exp2cxx/trace_fprintf.c @@ -1,8 +1,7 @@ - #include #include -#include "sc_trace_fprintf.h" +#include "trace_fprintf.h" void trace_fprintf( char const * sourcefile, int line, FILE * file, const char * format, ... ) { va_list args; diff --git a/src/base/sc_trace_fprintf.h b/src/exp2cxx/trace_fprintf.h similarity index 85% rename from src/base/sc_trace_fprintf.h rename to src/exp2cxx/trace_fprintf.h index b7aa05fa2..9e5c2f073 100644 --- a/src/base/sc_trace_fprintf.h +++ b/src/exp2cxx/trace_fprintf.h @@ -1,7 +1,7 @@ #ifndef SC_TRACE_FPRINTF_H #define SC_TRACE_FPRINTF_H -/** \file sc_trace_fprintf.h +/** \file trace_fprintf.h * Used to track the source file and line where generated code is printed from * When enabled, comments are printed into the generated files for every 'fprintf': * / * source: scl/src/exp2cxx/selects.c:1375 * / @@ -20,7 +20,7 @@ extern "C" { /** Used to find where generated c++ originates from in exp2cxx. * To enable, configure with 'cmake .. -DSC_TRACE_FPRINTF=ON' */ - SC_BASE_EXPORT void trace_fprintf( char const * sourcefile, int line, FILE * file, const char * format, ... ); + void trace_fprintf( char const * sourcefile, int line, FILE * file, const char * format, ... ); #ifdef __cplusplus } #endif diff --git a/src/exp2cxx/trynext.cc b/src/exp2cxx/trynext.cc index 97cacc8a3..e2c0a0edf 100644 --- a/src/exp2cxx/trynext.cc +++ b/src/exp2cxx/trynext.cc @@ -12,7 +12,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include // Local function prototypes: static EntList * firstCandidate( EntList * ); diff --git a/src/exp2cxx/write.cc b/src/exp2cxx/write.cc index 964aca652..da1ecb747 100644 --- a/src/exp2cxx/write.cc +++ b/src/exp2cxx/write.cc @@ -11,7 +11,6 @@ *****************************************************************************/ #include "complexSupport.h" -#include // Local function prototypes: static void writeheader( ostream &, int ); @@ -117,7 +116,7 @@ static void writeheader( ostream & os, int noLists ) << " * file, however, there are no complex entities, so this\n" << " * function is a stub.\n" << " */" << endl << endl; - os << "#include \"complexSupport.h\"\n#include \"sc_memmgr.h\"\n\n"; + os << "#include \"clstepcore/complexSupport.h\"\n\n"; os << "ComplexCollect *gencomplex()" << endl; os << "{" << endl; return; @@ -129,7 +128,7 @@ static void writeheader( ostream & os, int noLists ) << " * support structures. The structures will be used in the SCL to\n" << " * validate user requests to instantiate complex entities.\n" << " */" << endl << endl; - os << "#include \"complexSupport.h\"\n#include \"sc_memmgr.h\"\n\n"; + os << "#include \"clstepcore/complexSupport.h\"\n\n"; os << "ComplexCollect *gencomplex()" << endl; os << " /*" << endl << " * This function contains instantiation statements for all the\n" diff --git a/src/exp2python/CMakeLists.txt b/src/exp2python/CMakeLists.txt index a9feb39d2..1395e75a6 100644 --- a/src/exp2python/CMakeLists.txt +++ b/src/exp2python/CMakeLists.txt @@ -3,7 +3,6 @@ if(SC_PYTHON_GENERATOR) include_directories( ${SC_SOURCE_DIR}/include ${SC_SOURCE_DIR}/include/express - ${SC_SOURCE_DIR}/src/base ) add_definitions(-DHAVE_CONFIG_H) @@ -29,7 +28,11 @@ if(SC_PYTHON_GENERATOR) ../exp2cxx/write.cc ../exp2cxx/print.cc ) - SC_ADDEXEC(exp2python SOURCES ${exp2python_SOURCES} LINK_LIBRARIES express base) + if(BUILD_SHARED_LIBS) + SC_ADDEXEC(exp2python SOURCES ${exp2python_SOURCES} LINK_LIBRARIES express) + else() + SC_ADDEXEC(exp2python SOURCES ${exp2python_SOURCES} LINK_LIBRARIES express-static) + endif() endif(SC_PYTHON_GENERATOR) diff --git a/src/exp2python/examples/unitary_schemas/gcc_incomplete_type.py b/src/exp2python/examples/unitary_schemas/gcc_incomplete_type.py deleted file mode 100644 index 75448145b..000000000 --- a/src/exp2python/examples/unitary_schemas/gcc_incomplete_type.py +++ /dev/null @@ -1,28 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'gcc_incomplete_type' - -schema_scope = sys.modules[__name__] - -# Defined datatype maths_number -class maths_number(NUMBER): - def __init__(self,*kargs): - pass - -# SELECT TYPE atom_based_value -atom_based_value = SELECT( - 'maths_number', - 'atom_based_tuple', - scope = schema_scope) -atom_based_tuple = LIST(0,None,'atom_based_value', scope = schema_scope) diff --git a/src/exp2python/examples/unitary_schemas/generate_schemas_modules.py b/src/exp2python/examples/unitary_schemas/generate_schemas_modules.py deleted file mode 100644 index bc61a1a01..000000000 --- a/src/exp2python/examples/unitary_schemas/generate_schemas_modules.py +++ /dev/null @@ -1,13 +0,0 @@ -__doc__= ''' This script runs exp2python over each EXPRESS schema in the test/unitary_schemas folder''' - -unitary_schemas_path = '../../../../test/unitary_schemas' -exp2python_path = '../../../../cmake-build/bin/exp2python' - -import subprocess -import glob -import os - -unitary_schemas = glob.glob(os.path.join(unitary_schemas_path,'*.exp')) - -for unitary_schema in unitary_schemas: - subprocess.call([exp2python_path,unitary_schema]) \ No newline at end of file diff --git a/src/exp2python/examples/unitary_schemas/index_attribute.py b/src/exp2python/examples/unitary_schemas/index_attribute.py deleted file mode 100644 index 32fffaeab..000000000 --- a/src/exp2python/examples/unitary_schemas/index_attribute.py +++ /dev/null @@ -1,140 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'index_attribute' - -schema_scope = sys.modules[__name__] - -common_datum_list = LIST(1,None,'datum_reference_element', scope = schema_scope) -# Defined datatype label -class label(STRING): - def __init__(self,*kargs): - pass - -# SELECT TYPE datum_or_common_datum -datum_or_common_datum = SELECT( - 'common_datum_list', - 'datum', - scope = schema_scope) - -#################### - # ENTITY shape_aspect # -#################### -class shape_aspect(BaseEntityClass): - '''Entity shape_aspect definition. - - :param name - :type name:label - - :param of_shape - :type of_shape:product_definition_shape - ''' - def __init__( self , name,of_shape, ): - self.name = name - self.of_shape = of_shape - - @apply - def name(): - def fget( self ): - return self._name - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument name is mandatory and can not be set to None') - if not check_type(value,label): - self._name = label(value) - else: - self._name = value - return property(**locals()) - - @apply - def of_shape(): - def fget( self ): - return self._of_shape - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument of_shape is mandatory and can not be set to None') - if not check_type(value,product_definition_shape): - self._of_shape = product_definition_shape(value) - else: - self._of_shape = value - return property(**locals()) - def wr1(self): - eval_wr1_wr = (SIZEOF(USEDIN(self,'INDEX_ATTRIBUTE.' + 'ID_ATTRIBUTE.IDENTIFIED_ITEM')) <= 1) - if not eval_wr1_wr: - raise AssertionError('Rule wr1 violated') - else: - return eval_wr1_wr - - -#################### - # ENTITY general_datum_reference # -#################### -class general_datum_reference(shape_aspect): - '''Entity general_datum_reference definition. - - :param base - :type base:datum_or_common_datum - ''' - def __init__( self , inherited0__name , inherited1__of_shape , base, ): - shape_aspect.__init__(self , inherited0__name , inherited1__of_shape , ) - self.base = base - - @apply - def base(): - def fget( self ): - return self._base - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument base is mandatory and can not be set to None') - if not check_type(value,datum_or_common_datum): - self._base = datum_or_common_datum(value) - else: - self._base = value - return property(**locals()) - def wr1(self): - eval_wr1_wr = (( not ('INDEX_ATTRIBUTE.COMMON_DATUM_LIST' == TYPEOF(self.base))) or (self.self.shape_aspect.self.of_shape == self.base[1].self.shape_aspect.self.of_shape)) - if not eval_wr1_wr: - raise AssertionError('Rule wr1 violated') - else: - return eval_wr1_wr - - -#################### - # ENTITY product_definition_shape # -#################### -class product_definition_shape(BaseEntityClass): - '''Entity product_definition_shape definition. - ''' - # This class does not define any attribute. - pass - -#################### - # ENTITY datum_reference_element # -#################### -class datum_reference_element(general_datum_reference): - '''Entity datum_reference_element definition. - ''' - def __init__( self , inherited0__name , inherited1__of_shape , inherited2__base , ): - general_datum_reference.__init__(self , inherited0__name , inherited1__of_shape , inherited2__base , ) - -#################### - # ENTITY datum # -#################### -class datum(shape_aspect): - '''Entity datum definition. - ''' - def __init__( self , inherited0__name , inherited1__of_shape , ): - shape_aspect.__init__(self , inherited0__name , inherited1__of_shape , ) diff --git a/src/exp2python/examples/unitary_schemas/multiple_rep.py b/src/exp2python/examples/unitary_schemas/multiple_rep.py deleted file mode 100644 index 3805349fc..000000000 --- a/src/exp2python/examples/unitary_schemas/multiple_rep.py +++ /dev/null @@ -1,353 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'multiple_rep' - -schema_scope = sys.modules[__name__] - -# Defined datatype text -class text(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype representation_context -class representation_context(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype identifier -class identifier(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype shape_definition -class shape_definition(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype transformation -class transformation(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype representation_item -class representation_item(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype characterized_product_definition -class characterized_product_definition(STRING): - def __init__(self,*kargs): - pass - -# SELECT TYPE characterized_definition -characterized_definition = SELECT( - 'characterized_object', - 'characterized_product_definition', - 'shape_definition', - scope = schema_scope) -# Defined datatype label -class label(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype characterized_object -class characterized_object(STRING): - def __init__(self,*kargs): - pass - - -#################### - # ENTITY representation_relationship # -#################### -class representation_relationship(BaseEntityClass): - '''Entity representation_relationship definition. - - :param name - :type name:label - - :param rep_1 - :type rep_1:representation - - :param rep_2 - :type rep_2:representation - ''' - def __init__( self , name,rep_1,rep_2, ): - self.name = name - self.rep_1 = rep_1 - self.rep_2 = rep_2 - - @apply - def name(): - def fget( self ): - return self._name - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument name is mandatory and can not be set to None') - if not check_type(value,label): - self._name = label(value) - else: - self._name = value - return property(**locals()) - - @apply - def rep_1(): - def fget( self ): - return self._rep_1 - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument rep_1 is mandatory and can not be set to None') - if not check_type(value,representation): - self._rep_1 = representation(value) - else: - self._rep_1 = value - return property(**locals()) - - @apply - def rep_2(): - def fget( self ): - return self._rep_2 - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument rep_2 is mandatory and can not be set to None') - if not check_type(value,representation): - self._rep_2 = representation(value) - else: - self._rep_2 = value - return property(**locals()) - -#################### - # ENTITY shape_representation_relationship # -#################### -class shape_representation_relationship(representation_relationship): - '''Entity shape_representation_relationship definition. - ''' - def __init__( self , inherited0__name , inherited1__rep_1 , inherited2__rep_2 , ): - representation_relationship.__init__(self , inherited0__name , inherited1__rep_1 , inherited2__rep_2 , ) - def wr1(self): - eval_wr1_wr = ('MULTIPLE_REP.SHAPE_REPRESENTATION' == (TYPEOF(self.self.representation_relationship.self.rep_1) + TYPEOF(self.self.representation_relationship.self.rep_2))) - if not eval_wr1_wr: - raise AssertionError('Rule wr1 violated') - else: - return eval_wr1_wr - - -#################### - # ENTITY representation # -#################### -class representation(BaseEntityClass): - '''Entity representation definition. - - :param name - :type name:label - - :param items - :type items:SET(1,None,'STRING', scope = schema_scope) - - :param context_of_items - :type context_of_items:representation_context - ''' - def __init__( self , name,items,context_of_items, ): - self.name = name - self.items = items - self.context_of_items = context_of_items - - @apply - def name(): - def fget( self ): - return self._name - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument name is mandatory and can not be set to None') - if not check_type(value,label): - self._name = label(value) - else: - self._name = value - return property(**locals()) - - @apply - def items(): - def fget( self ): - return self._items - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument items is mandatory and can not be set to None') - if not check_type(value,SET(1,None,'STRING', scope = schema_scope)): - self._items = SET(value) - else: - self._items = value - return property(**locals()) - - @apply - def context_of_items(): - def fget( self ): - return self._context_of_items - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument context_of_items is mandatory and can not be set to None') - if not check_type(value,representation_context): - self._context_of_items = representation_context(value) - else: - self._context_of_items = value - return property(**locals()) - def wr1(self): - eval_wr1_wr = (SIZEOF(USEDIN(self,'MULTIPLE_REP.' + 'ID_ATTRIBUTE.IDENTIFIED_ITEM')) <= 1) - if not eval_wr1_wr: - raise AssertionError('Rule wr1 violated') - else: - return eval_wr1_wr - - def wr2(self): - eval_wr2_wr = (SIZEOF(USEDIN(self,'MULTIPLE_REP.' + 'DESCRIPTION_ATTRIBUTE.DESCRIBED_ITEM')) <= 1) - if not eval_wr2_wr: - raise AssertionError('Rule wr2 violated') - else: - return eval_wr2_wr - - -#################### - # ENTITY property_definition # -#################### -class property_definition(BaseEntityClass): - '''Entity property_definition definition. - - :param name - :type name:label - - :param definition - :type definition:characterized_definition - ''' - def __init__( self , name,definition, ): - self.name = name - self.definition = definition - - @apply - def name(): - def fget( self ): - return self._name - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument name is mandatory and can not be set to None') - if not check_type(value,label): - self._name = label(value) - else: - self._name = value - return property(**locals()) - - @apply - def definition(): - def fget( self ): - return self._definition - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument definition is mandatory and can not be set to None') - if not check_type(value,characterized_definition): - self._definition = characterized_definition(value) - else: - self._definition = value - return property(**locals()) - def wr1(self): - eval_wr1_wr = (SIZEOF(USEDIN(self,'MULTIPLE_REP.' + 'ID_ATTRIBUTE.IDENTIFIED_ITEM')) <= 1) - if not eval_wr1_wr: - raise AssertionError('Rule wr1 violated') - else: - return eval_wr1_wr - - -#################### - # ENTITY context_dependent_shape_representation # -#################### -class context_dependent_shape_representation(BaseEntityClass): - '''Entity context_dependent_shape_representation definition. - - :param representation_relation - :type representation_relation:shape_representation_relationship - ''' - def __init__( self , representation_relation, ): - self.representation_relation = representation_relation - - @apply - def representation_relation(): - def fget( self ): - return self._representation_relation - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument representation_relation is mandatory and can not be set to None') - if not check_type(value,shape_representation_relationship): - self._representation_relation = shape_representation_relationship(value) - else: - self._representation_relation = value - return property(**locals()) - def wr2(self): - eval_wr2_wr = (SIZEOF(USEDIN(self,'MULTIPLE_REP.' + 'DESCRIPTION_ATTRIBUTE.DESCRIBED_ITEM')) <= 1) - if not eval_wr2_wr: - raise AssertionError('Rule wr2 violated') - else: - return eval_wr2_wr - - def wr3(self): - eval_wr3_wr = (SIZEOF(USEDIN(self,'MULTIPLE_REP.' + 'NAME_ATTRIBUTE.NAMED_ITEM')) <= 1) - if not eval_wr3_wr: - raise AssertionError('Rule wr3 violated') - else: - return eval_wr3_wr - - -#################### - # ENTITY definitional_representation_relationship # -#################### -class definitional_representation_relationship(representation_relationship): - '''Entity definitional_representation_relationship definition. - ''' - def __init__( self , inherited0__name , inherited1__rep_1 , inherited2__rep_2 , ): - representation_relationship.__init__(self , inherited0__name , inherited1__rep_1 , inherited2__rep_2 , ) - -#################### - # ENTITY component_2d_location # -#################### -class component_2d_location(context_dependent_shape_representation,shape_representation_relationship,definitional_representation_relationship): - '''Entity component_2d_location definition. - - :param context_dependent_shape_representation_representation_relation - :type context_dependent_shape_representation_representation_relation:component_2d_location - ''' - def __init__( self , inherited0__representation_relation , inherited1__name , inherited2__rep_1 , inherited3__rep_2 , inherited4__name , inherited5__rep_1 , inherited6__rep_2 , ): - context_dependent_shape_representation.__init__(self , inherited0__representation_relation , ) - shape_representation_relationship.__init__(self , inherited1__name , inherited2__rep_1 , inherited3__rep_2 , ) - definitional_representation_relationship.__init__(self , inherited4__name , inherited5__rep_1 , inherited6__rep_2 , ) - - @apply - def context_dependent_shape_representation_representation_relation(): - def fget( self ): - attribute_eval = self - return attribute_eval - def fset( self, value ): - # DERIVED argument - raise AssertionError('Argument context_dependent_shape_representation_representation_relation is DERIVED. It is computed and can not be set to any value') - return property(**locals()) - def wr1(self): - eval_wr1_wr = (self.self.representation_relationship.self.name == 'component 2d location') - if not eval_wr1_wr: - raise AssertionError('Rule wr1 violated') - else: - return eval_wr1_wr - diff --git a/src/exp2python/examples/unitary_schemas/test_array.py b/src/exp2python/examples/unitary_schemas/test_array.py deleted file mode 100644 index 7f4fb6259..000000000 --- a/src/exp2python/examples/unitary_schemas/test_array.py +++ /dev/null @@ -1,43 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_array' - -schema_scope = sys.modules[__name__] - - -#################### - # ENTITY point # -#################### -class point(BaseEntityClass): - '''Entity point definition. - - :param coords - :type coords:ARRAY(1,3,'REAL', scope = schema_scope) - ''' - def __init__( self , coords, ): - self.coords = coords - - @apply - def coords(): - def fget( self ): - return self._coords - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument coords is mandatory and can not be set to None') - if not check_type(value,ARRAY(1,3,'REAL', scope = schema_scope)): - self._coords = ARRAY(value) - else: - self._coords = value - return property(**locals()) diff --git a/src/exp2python/examples/unitary_schemas/test_array_of_array_of_simple_types.py b/src/exp2python/examples/unitary_schemas/test_array_of_array_of_simple_types.py deleted file mode 100644 index 3ea8a8c15..000000000 --- a/src/exp2python/examples/unitary_schemas/test_array_of_array_of_simple_types.py +++ /dev/null @@ -1,43 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_array_of_array_of_simple_types' - -schema_scope = sys.modules[__name__] - - -#################### - # ENTITY transformation # -#################### -class transformation(BaseEntityClass): - '''Entity transformation definition. - - :param rotation - :type rotation:ARRAY(1,3,ARRAY(1,3,'REAL', scope = schema_scope)) - ''' - def __init__( self , rotation, ): - self.rotation = rotation - - @apply - def rotation(): - def fget( self ): - return self._rotation - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument rotation is mandatory and can not be set to None') - if not check_type(value,ARRAY(1,3,ARRAY(1,3,'REAL', scope = schema_scope))): - self._rotation = ARRAY(value) - else: - self._rotation = value - return property(**locals()) diff --git a/src/exp2python/examples/unitary_schemas/test_array_of_simple_types.py b/src/exp2python/examples/unitary_schemas/test_array_of_simple_types.py deleted file mode 100644 index 4c3d6f5df..000000000 --- a/src/exp2python/examples/unitary_schemas/test_array_of_simple_types.py +++ /dev/null @@ -1,79 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_array_of_simple_types' - -schema_scope = sys.modules[__name__] - - -#################### - # ENTITY point # -#################### -class point(BaseEntityClass): - '''Entity point definition. - - :param arr_real - :type arr_real:ARRAY(1,3,'REAL', scope = schema_scope) - - :param arr_string - :type arr_string:ARRAY(1,3,'STRING', scope = schema_scope) - - :param arr_integer - :type arr_integer:ARRAY(1,None,'INTEGER', scope = schema_scope) - ''' - def __init__( self , arr_real,arr_string,arr_integer, ): - self.arr_real = arr_real - self.arr_string = arr_string - self.arr_integer = arr_integer - - @apply - def arr_real(): - def fget( self ): - return self._arr_real - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument arr_real is mandatory and can not be set to None') - if not check_type(value,ARRAY(1,3,'REAL', scope = schema_scope)): - self._arr_real = ARRAY(value) - else: - self._arr_real = value - return property(**locals()) - - @apply - def arr_string(): - def fget( self ): - return self._arr_string - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument arr_string is mandatory and can not be set to None') - if not check_type(value,ARRAY(1,3,'STRING', scope = schema_scope)): - self._arr_string = ARRAY(value) - else: - self._arr_string = value - return property(**locals()) - - @apply - def arr_integer(): - def fget( self ): - return self._arr_integer - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument arr_integer is mandatory and can not be set to None') - if not check_type(value,ARRAY(1,None,'INTEGER', scope = schema_scope)): - self._arr_integer = ARRAY(value) - else: - self._arr_integer = value - return property(**locals()) diff --git a/src/exp2python/examples/unitary_schemas/test_derived_attribute.py b/src/exp2python/examples/unitary_schemas/test_derived_attribute.py deleted file mode 100644 index bdd4b82ee..000000000 --- a/src/exp2python/examples/unitary_schemas/test_derived_attribute.py +++ /dev/null @@ -1,123 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_derived_attribute' - -schema_scope = sys.modules[__name__] - - -#################### - # ENTITY vector # -#################### -class vector(BaseEntityClass): - '''Entity vector definition. - ''' - # This class does not define any attribute. - pass - -#################### - # ENTITY circle # -#################### -class circle(BaseEntityClass): - '''Entity circle definition. - - :param centre - :type centre:point - - :param radius - :type radius:REAL - - :param axis - :type axis:vector - - :param area - :type area:REAL - - :param perimeter - :type perimeter:REAL - ''' - def __init__( self , centre,radius,axis, ): - self.centre = centre - self.radius = radius - self.axis = axis - - @apply - def centre(): - def fget( self ): - return self._centre - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument centre is mandatory and can not be set to None') - if not check_type(value,point): - self._centre = point(value) - else: - self._centre = value - return property(**locals()) - - @apply - def radius(): - def fget( self ): - return self._radius - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument radius is mandatory and can not be set to None') - if not check_type(value,REAL): - self._radius = REAL(value) - else: - self._radius = value - return property(**locals()) - - @apply - def axis(): - def fget( self ): - return self._axis - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument axis is mandatory and can not be set to None') - if not check_type(value,vector): - self._axis = vector(value) - else: - self._axis = value - return property(**locals()) - - @apply - def area(): - def fget( self ): - attribute_eval = ( PI * (self.radius ** 2)) - return attribute_eval - def fset( self, value ): - # DERIVED argument - raise AssertionError('Argument area is DERIVED. It is computed and can not be set to any value') - return property(**locals()) - - @apply - def perimeter(): - def fget( self ): - attribute_eval = ((2 * PI ) * self.radius) - return attribute_eval - def fset( self, value ): - # DERIVED argument - raise AssertionError('Argument perimeter is DERIVED. It is computed and can not be set to any value') - return property(**locals()) - -#################### - # ENTITY point # -#################### -class point(BaseEntityClass): - '''Entity point definition. - ''' - # This class does not define any attribute. - pass diff --git a/src/exp2python/examples/unitary_schemas/test_entity_where_rule.py b/src/exp2python/examples/unitary_schemas/test_entity_where_rule.py deleted file mode 100644 index 84c56c78b..000000000 --- a/src/exp2python/examples/unitary_schemas/test_entity_where_rule.py +++ /dev/null @@ -1,322 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_entity_where_rule' - -schema_scope = sys.modules[__name__] - -# Defined datatype label -class label(STRING): - def __init__(self,*kargs): - pass - - -#################### - # ENTITY unit_vector # -#################### -class unit_vector(BaseEntityClass): - '''Entity unit_vector definition. - - :param a - :type a:REAL - - :param b - :type b:REAL - - :param c - :type c:REAL - ''' - def __init__( self , a,b,c, ): - self.a = a - self.b = b - self.c = c - - @apply - def a(): - def fget( self ): - return self._a - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument a is mandatory and can not be set to None') - if not check_type(value,REAL): - self._a = REAL(value) - else: - self._a = value - return property(**locals()) - - @apply - def b(): - def fget( self ): - return self._b - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument b is mandatory and can not be set to None') - if not check_type(value,REAL): - self._b = REAL(value) - else: - self._b = value - return property(**locals()) - - @apply - def c(): - def fget( self ): - return self._c - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument c is mandatory and can not be set to None') - if not check_type(value,REAL): - self._c = REAL(value) - else: - self._c = value - return property(**locals()) - def length_1(self): - eval_length_1_wr = ((((self.a ** 2) + (self.b ** 2)) + (self.c ** 2)) == 1) - if not eval_length_1_wr: - raise AssertionError('Rule length_1 violated') - else: - return eval_length_1_wr - - -#################### - # ENTITY address # -#################### -class address(BaseEntityClass): - '''Entity address definition. - - :param internal_location - :type internal_location:label - - :param street_number - :type street_number:label - - :param street - :type street:label - - :param postal_box - :type postal_box:label - - :param town - :type town:label - - :param region - :type region:label - - :param postal_code - :type postal_code:label - - :param country - :type country:label - - :param facsimile_number - :type facsimile_number:label - - :param telephone_number - :type telephone_number:label - - :param electronic_mail_address - :type electronic_mail_address:label - - :param telex_number - :type telex_number:label - ''' - def __init__( self , internal_location,street_number,street,postal_box,town,region,postal_code,country,facsimile_number,telephone_number,electronic_mail_address,telex_number, ): - self.internal_location = internal_location - self.street_number = street_number - self.street = street - self.postal_box = postal_box - self.town = town - self.region = region - self.postal_code = postal_code - self.country = country - self.facsimile_number = facsimile_number - self.telephone_number = telephone_number - self.electronic_mail_address = electronic_mail_address - self.telex_number = telex_number - - @apply - def internal_location(): - def fget( self ): - return self._internal_location - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._internal_location = label(value) - else: - self._internal_location = value - else: - self._internal_location = value - return property(**locals()) - - @apply - def street_number(): - def fget( self ): - return self._street_number - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._street_number = label(value) - else: - self._street_number = value - else: - self._street_number = value - return property(**locals()) - - @apply - def street(): - def fget( self ): - return self._street - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._street = label(value) - else: - self._street = value - else: - self._street = value - return property(**locals()) - - @apply - def postal_box(): - def fget( self ): - return self._postal_box - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._postal_box = label(value) - else: - self._postal_box = value - else: - self._postal_box = value - return property(**locals()) - - @apply - def town(): - def fget( self ): - return self._town - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._town = label(value) - else: - self._town = value - else: - self._town = value - return property(**locals()) - - @apply - def region(): - def fget( self ): - return self._region - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._region = label(value) - else: - self._region = value - else: - self._region = value - return property(**locals()) - - @apply - def postal_code(): - def fget( self ): - return self._postal_code - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._postal_code = label(value) - else: - self._postal_code = value - else: - self._postal_code = value - return property(**locals()) - - @apply - def country(): - def fget( self ): - return self._country - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._country = label(value) - else: - self._country = value - else: - self._country = value - return property(**locals()) - - @apply - def facsimile_number(): - def fget( self ): - return self._facsimile_number - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._facsimile_number = label(value) - else: - self._facsimile_number = value - else: - self._facsimile_number = value - return property(**locals()) - - @apply - def telephone_number(): - def fget( self ): - return self._telephone_number - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._telephone_number = label(value) - else: - self._telephone_number = value - else: - self._telephone_number = value - return property(**locals()) - - @apply - def electronic_mail_address(): - def fget( self ): - return self._electronic_mail_address - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._electronic_mail_address = label(value) - else: - self._electronic_mail_address = value - else: - self._electronic_mail_address = value - return property(**locals()) - - @apply - def telex_number(): - def fget( self ): - return self._telex_number - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._telex_number = label(value) - else: - self._telex_number = value - else: - self._telex_number = value - return property(**locals()) - def wr1(self): - eval_wr1_wr = (((((((((((EXISTS(self.internal_location) or EXISTS(self.street_number)) or EXISTS(self.street)) or EXISTS(self.postal_box)) or EXISTS(self.town)) or EXISTS(self.region)) or EXISTS(self.postal_code)) or EXISTS(self.country)) or EXISTS(self.facsimile_number)) or EXISTS(self.telephone_number)) or EXISTS(self.electronic_mail_address)) or EXISTS(self.telex_number)) - if not eval_wr1_wr: - raise AssertionError('Rule wr1 violated') - else: - return eval_wr1_wr - diff --git a/src/exp2python/examples/unitary_schemas/test_enum_entity_name.py b/src/exp2python/examples/unitary_schemas/test_enum_entity_name.py deleted file mode 100644 index 5285ef88b..000000000 --- a/src/exp2python/examples/unitary_schemas/test_enum_entity_name.py +++ /dev/null @@ -1,32 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_enum_entity_name' - -schema_scope = sys.modules[__name__] - - -# ENUMERATION TYPE simple_datum_reference_modifier -simple_datum_reference_modifier = ENUMERATION( - 'line', - 'translation', - scope = schema_scope) - -#################### - # ENTITY line # -#################### -class line(BaseEntityClass): - '''Entity line definition. - ''' - # This class does not define any attribute. - pass diff --git a/src/exp2python/examples/unitary_schemas/test_enums_same_name.py b/src/exp2python/examples/unitary_schemas/test_enums_same_name.py deleted file mode 100644 index 4a446be99..000000000 --- a/src/exp2python/examples/unitary_schemas/test_enums_same_name.py +++ /dev/null @@ -1,29 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_enums_same_name' - -schema_scope = sys.modules[__name__] - - -# ENUMERATION TYPE hair_color -hair_color = ENUMERATION( - 'bald', - 'red', - scope = schema_scope) - -# ENUMERATION TYPE favorite_color -favorite_color = ENUMERATION( - 'clear', - 'red', - scope = schema_scope) diff --git a/src/exp2python/examples/unitary_schemas/test_function.py b/src/exp2python/examples/unitary_schemas/test_function.py deleted file mode 100644 index 72a90c1e4..000000000 --- a/src/exp2python/examples/unitary_schemas/test_function.py +++ /dev/null @@ -1,80 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_function' - -schema_scope = sys.modules[__name__] - - -#################### - # ENTITY dummy # -#################### -class dummy(BaseEntityClass): - '''Entity dummy definition. - ''' - # This class does not define any attribute. - pass - -#################### - # FUNCTION add # -#################### -def add(r1,r2,): - ''' - :param r1 - :type r1:REAL - :param r2 - :type r2:REAL - ''' - result = r1 + r2 - return result - -#################### - # FUNCTION pow_n # -#################### -def pow_n(r1,n,): - ''' - :param r1 - :type r1:REAL - :param n - :type n:INTEGER - ''' - if (n == 0): - return 1 - else: - result = r1 - for i in range(1,n,1): - result = result * r1 - return result - -#################### - # FUNCTION case_1 # -#################### -def case_1(a,): - ''' - :param a - :type a:INTEGER - ''' - case_selector = a - if case_selector == 1: - x = SIN(a) - elif case_selector == 2: - x = EXP(a) - elif case_selector == 3: - x = SQRT(a) - elif case_selector == 4: - x = LOG(a) - elif case_selector == 5: - x = LOG(a) - else: - x = 0 - return x diff --git a/src/exp2python/examples/unitary_schemas/test_multiple_inheritance.py b/src/exp2python/examples/unitary_schemas/test_multiple_inheritance.py deleted file mode 100644 index ce4e42d52..000000000 --- a/src/exp2python/examples/unitary_schemas/test_multiple_inheritance.py +++ /dev/null @@ -1,582 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_multiple_inheritance' - -schema_scope = sys.modules[__name__] - -# SELECT TYPE classification_item -classification_item = SELECT( - 'person_and_organization_address', - 'address', - scope = schema_scope) -# Defined datatype text -class text(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype identifier -class identifier(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype label -class label(STRING): - def __init__(self,*kargs): - pass - - -#################### - # ENTITY address # -#################### -class address(BaseEntityClass): - '''Entity address definition. - - :param internal_location - :type internal_location:label - - :param street_number - :type street_number:label - - :param street - :type street:label - - :param postal_box - :type postal_box:label - - :param town - :type town:label - - :param region - :type region:label - - :param postal_code - :type postal_code:label - - :param country - :type country:label - - :param facsimile_number - :type facsimile_number:label - - :param telephone_number - :type telephone_number:label - - :param electronic_mail_address - :type electronic_mail_address:label - - :param telex_number - :type telex_number:label - ''' - def __init__( self , internal_location,street_number,street,postal_box,town,region,postal_code,country,facsimile_number,telephone_number,electronic_mail_address,telex_number, ): - self.internal_location = internal_location - self.street_number = street_number - self.street = street - self.postal_box = postal_box - self.town = town - self.region = region - self.postal_code = postal_code - self.country = country - self.facsimile_number = facsimile_number - self.telephone_number = telephone_number - self.electronic_mail_address = electronic_mail_address - self.telex_number = telex_number - - @apply - def internal_location(): - def fget( self ): - return self._internal_location - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._internal_location = label(value) - else: - self._internal_location = value - else: - self._internal_location = value - return property(**locals()) - - @apply - def street_number(): - def fget( self ): - return self._street_number - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._street_number = label(value) - else: - self._street_number = value - else: - self._street_number = value - return property(**locals()) - - @apply - def street(): - def fget( self ): - return self._street - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._street = label(value) - else: - self._street = value - else: - self._street = value - return property(**locals()) - - @apply - def postal_box(): - def fget( self ): - return self._postal_box - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._postal_box = label(value) - else: - self._postal_box = value - else: - self._postal_box = value - return property(**locals()) - - @apply - def town(): - def fget( self ): - return self._town - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._town = label(value) - else: - self._town = value - else: - self._town = value - return property(**locals()) - - @apply - def region(): - def fget( self ): - return self._region - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._region = label(value) - else: - self._region = value - else: - self._region = value - return property(**locals()) - - @apply - def postal_code(): - def fget( self ): - return self._postal_code - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._postal_code = label(value) - else: - self._postal_code = value - else: - self._postal_code = value - return property(**locals()) - - @apply - def country(): - def fget( self ): - return self._country - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._country = label(value) - else: - self._country = value - else: - self._country = value - return property(**locals()) - - @apply - def facsimile_number(): - def fget( self ): - return self._facsimile_number - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._facsimile_number = label(value) - else: - self._facsimile_number = value - else: - self._facsimile_number = value - return property(**locals()) - - @apply - def telephone_number(): - def fget( self ): - return self._telephone_number - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._telephone_number = label(value) - else: - self._telephone_number = value - else: - self._telephone_number = value - return property(**locals()) - - @apply - def electronic_mail_address(): - def fget( self ): - return self._electronic_mail_address - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._electronic_mail_address = label(value) - else: - self._electronic_mail_address = value - else: - self._electronic_mail_address = value - return property(**locals()) - - @apply - def telex_number(): - def fget( self ): - return self._telex_number - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._telex_number = label(value) - else: - self._telex_number = value - else: - self._telex_number = value - return property(**locals()) - -#################### - # ENTITY personal_address # -#################### -class personal_address(address): - '''Entity personal_address definition. - - :param people - :type people:SET(1,None,'person', scope = schema_scope) - - :param description - :type description:text - ''' - def __init__( self , inherited0__internal_location , inherited1__street_number , inherited2__street , inherited3__postal_box , inherited4__town , inherited5__region , inherited6__postal_code , inherited7__country , inherited8__facsimile_number , inherited9__telephone_number , inherited10__electronic_mail_address , inherited11__telex_number , people,description, ): - address.__init__(self , inherited0__internal_location , inherited1__street_number , inherited2__street , inherited3__postal_box , inherited4__town , inherited5__region , inherited6__postal_code , inherited7__country , inherited8__facsimile_number , inherited9__telephone_number , inherited10__electronic_mail_address , inherited11__telex_number , ) - self.people = people - self.description = description - - @apply - def people(): - def fget( self ): - return self._people - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument people is mandatory and can not be set to None') - if not check_type(value,SET(1,None,'person', scope = schema_scope)): - self._people = SET(value) - else: - self._people = value - return property(**locals()) - - @apply - def description(): - def fget( self ): - return self._description - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,text): - self._description = text(value) - else: - self._description = value - else: - self._description = value - return property(**locals()) - -#################### - # ENTITY organizational_address # -#################### -class organizational_address(address): - '''Entity organizational_address definition. - - :param organizations - :type organizations:SET(1,None,'organization', scope = schema_scope) - - :param description - :type description:text - ''' - def __init__( self , inherited0__internal_location , inherited1__street_number , inherited2__street , inherited3__postal_box , inherited4__town , inherited5__region , inherited6__postal_code , inherited7__country , inherited8__facsimile_number , inherited9__telephone_number , inherited10__electronic_mail_address , inherited11__telex_number , organizations,description, ): - address.__init__(self , inherited0__internal_location , inherited1__street_number , inherited2__street , inherited3__postal_box , inherited4__town , inherited5__region , inherited6__postal_code , inherited7__country , inherited8__facsimile_number , inherited9__telephone_number , inherited10__electronic_mail_address , inherited11__telex_number , ) - self.organizations = organizations - self.description = description - - @apply - def organizations(): - def fget( self ): - return self._organizations - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument organizations is mandatory and can not be set to None') - if not check_type(value,SET(1,None,'organization', scope = schema_scope)): - self._organizations = SET(value) - else: - self._organizations = value - return property(**locals()) - - @apply - def description(): - def fget( self ): - return self._description - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,text): - self._description = text(value) - else: - self._description = value - else: - self._description = value - return property(**locals()) - -#################### - # ENTITY person # -#################### -class person(BaseEntityClass): - '''Entity person definition. - - :param id - :type id:identifier - - :param last_name - :type last_name:label - - :param first_name - :type first_name:label - - :param middle_names - :type middle_names:LIST(1,None,'STRING', scope = schema_scope) - - :param prefix_titles - :type prefix_titles:LIST(1,None,'STRING', scope = schema_scope) - - :param suffix_titles - :type suffix_titles:LIST(1,None,'STRING', scope = schema_scope) - ''' - def __init__( self , id,last_name,first_name,middle_names,prefix_titles,suffix_titles, ): - self.id = id - self.last_name = last_name - self.first_name = first_name - self.middle_names = middle_names - self.prefix_titles = prefix_titles - self.suffix_titles = suffix_titles - - @apply - def id(): - def fget( self ): - return self._id - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument id is mandatory and can not be set to None') - if not check_type(value,identifier): - self._id = identifier(value) - else: - self._id = value - return property(**locals()) - - @apply - def last_name(): - def fget( self ): - return self._last_name - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._last_name = label(value) - else: - self._last_name = value - else: - self._last_name = value - return property(**locals()) - - @apply - def first_name(): - def fget( self ): - return self._first_name - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,label): - self._first_name = label(value) - else: - self._first_name = value - else: - self._first_name = value - return property(**locals()) - - @apply - def middle_names(): - def fget( self ): - return self._middle_names - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,LIST(1,None,'STRING', scope = schema_scope)): - self._middle_names = LIST(value) - else: - self._middle_names = value - else: - self._middle_names = value - return property(**locals()) - - @apply - def prefix_titles(): - def fget( self ): - return self._prefix_titles - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,LIST(1,None,'STRING', scope = schema_scope)): - self._prefix_titles = LIST(value) - else: - self._prefix_titles = value - else: - self._prefix_titles = value - return property(**locals()) - - @apply - def suffix_titles(): - def fget( self ): - return self._suffix_titles - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,LIST(1,None,'STRING', scope = schema_scope)): - self._suffix_titles = LIST(value) - else: - self._suffix_titles = value - else: - self._suffix_titles = value - return property(**locals()) - def wr1(self): - eval_wr1_wr = (EXISTS(self.last_name) or EXISTS(self.first_name)) - if not eval_wr1_wr: - raise AssertionError('Rule wr1 violated') - else: - return eval_wr1_wr - - -#################### - # ENTITY organization # -#################### -class organization(BaseEntityClass): - '''Entity organization definition. - - :param id - :type id:identifier - - :param name - :type name:label - - :param description - :type description:text - ''' - def __init__( self , id,name,description, ): - self.id = id - self.name = name - self.description = description - - @apply - def id(): - def fget( self ): - return self._id - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,identifier): - self._id = identifier(value) - else: - self._id = value - else: - self._id = value - return property(**locals()) - - @apply - def name(): - def fget( self ): - return self._name - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument name is mandatory and can not be set to None') - if not check_type(value,label): - self._name = label(value) - else: - self._name = value - return property(**locals()) - - @apply - def description(): - def fget( self ): - return self._description - def fset( self, value ): - if value != None: # OPTIONAL attribute - if not check_type(value,text): - self._description = text(value) - else: - self._description = value - else: - self._description = value - return property(**locals()) - -#################### - # ENTITY person_and_organization_address # -#################### -class person_and_organization_address(organizational_address,personal_address): - '''Entity person_and_organization_address definition. - - :param organizational_address_organizations - :type organizational_address_organizations:SET(1,1,'organization', scope = schema_scope) - - :param personal_address_people - :type personal_address_people:SET(1,1,'person', scope = schema_scope) - ''' - def __init__( self , inherited0__internal_location , inherited1__street_number , inherited2__street , inherited3__postal_box , inherited4__town , inherited5__region , inherited6__postal_code , inherited7__country , inherited8__facsimile_number , inherited9__telephone_number , inherited10__electronic_mail_address , inherited11__telex_number , inherited12__organizations , inherited13__description , inherited14__internal_location , inherited15__street_number , inherited16__street , inherited17__postal_box , inherited18__town , inherited19__region , inherited20__postal_code , inherited21__country , inherited22__facsimile_number , inherited23__telephone_number , inherited24__electronic_mail_address , inherited25__telex_number , inherited26__people , inherited27__description , organizational_address_organizations,personal_address_people, ): - organizational_address.__init__(self , inherited0__internal_location , inherited1__street_number , inherited2__street , inherited3__postal_box , inherited4__town , inherited5__region , inherited6__postal_code , inherited7__country , inherited8__facsimile_number , inherited9__telephone_number , inherited10__electronic_mail_address , inherited11__telex_number , inherited12__organizations , inherited13__description , ) - personal_address.__init__(self , inherited14__internal_location , inherited15__street_number , inherited16__street , inherited17__postal_box , inherited18__town , inherited19__region , inherited20__postal_code , inherited21__country , inherited22__facsimile_number , inherited23__telephone_number , inherited24__electronic_mail_address , inherited25__telex_number , inherited26__people , inherited27__description , ) - self.organizational_address_organizations = organizational_address_organizations - self.personal_address_people = personal_address_people - - @apply - def organizational_address_organizations(): - def fget( self ): - return self._organizational_address_organizations - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument organizational_address_organizations is mandatory and can not be set to None') - if not check_type(value,SET(1,1,'organization', scope = schema_scope)): - self._organizational_address_organizations = SET(value) - else: - self._organizational_address_organizations = value - return property(**locals()) - - @apply - def personal_address_people(): - def fget( self ): - return self._personal_address_people - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument personal_address_people is mandatory and can not be set to None') - if not check_type(value,SET(1,1,'person', scope = schema_scope)): - self._personal_address_people = SET(value) - else: - self._personal_address_people = value - return property(**locals()) diff --git a/src/exp2python/examples/unitary_schemas/test_named_type.py b/src/exp2python/examples/unitary_schemas/test_named_type.py deleted file mode 100644 index 8ba93647f..000000000 --- a/src/exp2python/examples/unitary_schemas/test_named_type.py +++ /dev/null @@ -1,94 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_named_type' - -schema_scope = sys.modules[__name__] - -# Defined datatype measure -class measure(REAL): - def __init__(self,*kargs): - pass - -# Defined datatype type2 -class type2(INTEGER): - def __init__(self,*kargs): - pass - -# Defined datatype type3 -class type3(type2): - def __init__(self,*kargs): - pass - - -#################### - # ENTITY line # -#################### -class line(BaseEntityClass): - '''Entity line definition. - - :param line_length - :type line_length:measure - - :param other_param - :type other_param:type3 - - :param and_another - :type and_another:REAL - ''' - def __init__( self , line_length,other_param,and_another, ): - self.line_length = line_length - self.other_param = other_param - self.and_another = and_another - - @apply - def line_length(): - def fget( self ): - return self._line_length - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument line_length is mandatory and can not be set to None') - if not check_type(value,measure): - self._line_length = measure(value) - else: - self._line_length = value - return property(**locals()) - - @apply - def other_param(): - def fget( self ): - return self._other_param - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument other_param is mandatory and can not be set to None') - if not check_type(value,type3): - self._other_param = type3(value) - else: - self._other_param = value - return property(**locals()) - - @apply - def and_another(): - def fget( self ): - return self._and_another - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument and_another is mandatory and can not be set to None') - if not check_type(value,REAL): - self._and_another = REAL(value) - else: - self._and_another = value - return property(**locals()) diff --git a/src/exp2python/examples/unitary_schemas/test_select_data_type.py b/src/exp2python/examples/unitary_schemas/test_select_data_type.py deleted file mode 100644 index d4c3b53c3..000000000 --- a/src/exp2python/examples/unitary_schemas/test_select_data_type.py +++ /dev/null @@ -1,252 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_select_data_type' - -schema_scope = sys.modules[__name__] - -# SELECT TYPE permanent_attachment -permanent_attachment = SELECT( - 'glue', - 'weld', - scope = schema_scope) -# SELECT TYPE temporary_attachment -temporary_attachment = SELECT( - 'nail', - 'screw', - scope = schema_scope) -# SELECT TYPE attachment_method -attachment_method = SELECT( - 'permanent_attachment', - 'temporary_attachment', - scope = schema_scope) - -#################### - # ENTITY weld # -#################### -class weld(BaseEntityClass): - '''Entity weld definition. - - :param composition - :type composition:STRING - ''' - def __init__( self , composition, ): - self.composition = composition - - @apply - def composition(): - def fget( self ): - return self._composition - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument composition is mandatory and can not be set to None') - if not check_type(value,STRING): - self._composition = STRING(value) - else: - self._composition = value - return property(**locals()) - -#################### - # ENTITY glue # -#################### -class glue(BaseEntityClass): - '''Entity glue definition. - - :param composition - :type composition:STRING - - :param solvent - :type solvent:STRING - ''' - def __init__( self , composition,solvent, ): - self.composition = composition - self.solvent = solvent - - @apply - def composition(): - def fget( self ): - return self._composition - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument composition is mandatory and can not be set to None') - if not check_type(value,STRING): - self._composition = STRING(value) - else: - self._composition = value - return property(**locals()) - - @apply - def solvent(): - def fget( self ): - return self._solvent - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument solvent is mandatory and can not be set to None') - if not check_type(value,STRING): - self._solvent = STRING(value) - else: - self._solvent = value - return property(**locals()) - -#################### - # ENTITY wall_mounting # -#################### -class wall_mounting(BaseEntityClass): - '''Entity wall_mounting definition. - - :param mounting - :type mounting:STRING - - :param on - :type on:STRING - - :param using - :type using:attachment_method - ''' - def __init__( self , mounting,on,using, ): - self.mounting = mounting - self.on = on - self.using = using - - @apply - def mounting(): - def fget( self ): - return self._mounting - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument mounting is mandatory and can not be set to None') - if not check_type(value,STRING): - self._mounting = STRING(value) - else: - self._mounting = value - return property(**locals()) - - @apply - def on(): - def fget( self ): - return self._on - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument on is mandatory and can not be set to None') - if not check_type(value,STRING): - self._on = STRING(value) - else: - self._on = value - return property(**locals()) - - @apply - def using(): - def fget( self ): - return self._using - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument using is mandatory and can not be set to None') - if not check_type(value,attachment_method): - self._using = attachment_method(value) - else: - self._using = value - return property(**locals()) - -#################### - # ENTITY screw # -#################### -class screw(BaseEntityClass): - '''Entity screw definition. - - :param body_length - :type body_length:REAL - - :param pitch - :type pitch:REAL - ''' - def __init__( self , body_length,pitch, ): - self.body_length = body_length - self.pitch = pitch - - @apply - def body_length(): - def fget( self ): - return self._body_length - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument body_length is mandatory and can not be set to None') - if not check_type(value,REAL): - self._body_length = REAL(value) - else: - self._body_length = value - return property(**locals()) - - @apply - def pitch(): - def fget( self ): - return self._pitch - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument pitch is mandatory and can not be set to None') - if not check_type(value,REAL): - self._pitch = REAL(value) - else: - self._pitch = value - return property(**locals()) - -#################### - # ENTITY nail # -#################### -class nail(BaseEntityClass): - '''Entity nail definition. - - :param body_length - :type body_length:REAL - - :param head_area - :type head_area:REAL - ''' - def __init__( self , body_length,head_area, ): - self.body_length = body_length - self.head_area = head_area - - @apply - def body_length(): - def fget( self ): - return self._body_length - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument body_length is mandatory and can not be set to None') - if not check_type(value,REAL): - self._body_length = REAL(value) - else: - self._body_length = value - return property(**locals()) - - @apply - def head_area(): - def fget( self ): - return self._head_area - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument head_area is mandatory and can not be set to None') - if not check_type(value,REAL): - self._head_area = REAL(value) - else: - self._head_area = value - return property(**locals()) diff --git a/src/exp2python/examples/unitary_schemas/test_single_inheritance.py b/src/exp2python/examples/unitary_schemas/test_single_inheritance.py deleted file mode 100644 index bd67d1a8b..000000000 --- a/src/exp2python/examples/unitary_schemas/test_single_inheritance.py +++ /dev/null @@ -1,121 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_single_inheritance' - -schema_scope = sys.modules[__name__] - -# Defined datatype length_measure -class length_measure(REAL): - def __init__(self,*kargs): - pass - -# Defined datatype label -class label(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype point -class point(REAL): - def __init__(self,*kargs): - pass - - -#################### - # ENTITY shape # -#################### -class shape(BaseEntityClass): - '''Entity shape definition. - - :param item_name - :type item_name:label - - :param number_of_sides - :type number_of_sides:INTEGER - ''' - def __init__( self , item_name,number_of_sides, ): - self.item_name = item_name - self.number_of_sides = number_of_sides - - @apply - def item_name(): - def fget( self ): - return self._item_name - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument item_name is mandatory and can not be set to None') - if not check_type(value,label): - self._item_name = label(value) - else: - self._item_name = value - return property(**locals()) - - @apply - def number_of_sides(): - def fget( self ): - return self._number_of_sides - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument number_of_sides is mandatory and can not be set to None') - if not check_type(value,INTEGER): - self._number_of_sides = INTEGER(value) - else: - self._number_of_sides = value - return property(**locals()) - -#################### - # ENTITY rectangle # -#################### -class rectangle(shape): - '''Entity rectangle definition. - - :param height - :type height:length_measure - - :param width - :type width:length_measure - ''' - def __init__( self , inherited0__item_name , inherited1__number_of_sides , height,width, ): - shape.__init__(self , inherited0__item_name , inherited1__number_of_sides , ) - self.height = height - self.width = width - - @apply - def height(): - def fget( self ): - return self._height - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument height is mandatory and can not be set to None') - if not check_type(value,length_measure): - self._height = length_measure(value) - else: - self._height = value - return property(**locals()) - - @apply - def width(): - def fget( self ): - return self._width - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument width is mandatory and can not be set to None') - if not check_type(value,length_measure): - self._width = length_measure(value) - else: - self._width = value - return property(**locals()) diff --git a/src/exp2python/examples/unitary_schemas/test_single_inheritance_multi_level.py b/src/exp2python/examples/unitary_schemas/test_single_inheritance_multi_level.py deleted file mode 100644 index b15846391..000000000 --- a/src/exp2python/examples/unitary_schemas/test_single_inheritance_multi_level.py +++ /dev/null @@ -1,130 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_single_inheritance_multi_level' - -schema_scope = sys.modules[__name__] - -# Defined datatype length_measure -class length_measure(REAL): - def __init__(self,*kargs): - pass - -# Defined datatype label -class label(STRING): - def __init__(self,*kargs): - pass - -# Defined datatype point -class point(REAL): - def __init__(self,*kargs): - pass - - -#################### - # ENTITY shape # -#################### -class shape(BaseEntityClass): - '''Entity shape definition. - - :param item_name - :type item_name:label - - :param number_of_sides - :type number_of_sides:INTEGER - ''' - def __init__( self , item_name,number_of_sides, ): - self.item_name = item_name - self.number_of_sides = number_of_sides - - @apply - def item_name(): - def fget( self ): - return self._item_name - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument item_name is mandatory and can not be set to None') - if not check_type(value,label): - self._item_name = label(value) - else: - self._item_name = value - return property(**locals()) - - @apply - def number_of_sides(): - def fget( self ): - return self._number_of_sides - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument number_of_sides is mandatory and can not be set to None') - if not check_type(value,INTEGER): - self._number_of_sides = INTEGER(value) - else: - self._number_of_sides = value - return property(**locals()) - -#################### - # ENTITY subshape # -#################### -class subshape(shape): - '''Entity subshape definition. - ''' - def __init__( self , inherited0__item_name , inherited1__number_of_sides , ): - shape.__init__(self , inherited0__item_name , inherited1__number_of_sides , ) - -#################### - # ENTITY rectangle # -#################### -class rectangle(subshape): - '''Entity rectangle definition. - - :param height - :type height:length_measure - - :param width - :type width:length_measure - ''' - def __init__( self , inherited0__item_name , inherited1__number_of_sides , height,width, ): - subshape.__init__(self , inherited0__item_name , inherited1__number_of_sides , ) - self.height = height - self.width = width - - @apply - def height(): - def fget( self ): - return self._height - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument height is mandatory and can not be set to None') - if not check_type(value,length_measure): - self._height = length_measure(value) - else: - self._height = value - return property(**locals()) - - @apply - def width(): - def fget( self ): - return self._width - def fset( self, value ): - # Mandatory argument - if value==None: - raise AssertionError('Argument width is mandatory and can not be set to None') - if not check_type(value,length_measure): - self._width = length_measure(value) - else: - self._width = value - return property(**locals()) diff --git a/src/exp2python/examples/unitary_schemas/test_where_rule.py b/src/exp2python/examples/unitary_schemas/test_where_rule.py deleted file mode 100644 index 99bb2f146..000000000 --- a/src/exp2python/examples/unitary_schemas/test_where_rule.py +++ /dev/null @@ -1,51 +0,0 @@ -# This file was generated by exp2python. You probably don't want to edit -# it since your modifications will be lost if exp2python is used to -# regenerate it. -import sys - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Builtin import * -from SCL.Rules import * - -schema_name = 'test_where_rule' - -schema_scope = sys.modules[__name__] - -# Defined datatype month -class month(INTEGER): - def __init__(self,*kargs): - pass - self.unnamed_wr_0() - self.unnamed_wr_1() - - def unnamed_wr_0(self): - eval_unnamed_wr_0 = (self <= 12) - if not eval_unnamed_wr_0: - raise AssertionError('Rule unnamed_wr_0 violated') - else: - return eval_unnamed_wr_0 - - def unnamed_wr_1(self): - eval_unnamed_wr_1 = (self >= 1) - if not eval_unnamed_wr_1: - raise AssertionError('Rule unnamed_wr_1 violated') - else: - return eval_unnamed_wr_1 - -# Defined datatype positive -class positive(INTEGER): - def __init__(self,*kargs): - pass - self.notnegative() - - def notnegative(self): - eval_notnegative_wr = (self > 0) - if not eval_notnegative_wr: - raise AssertionError('Rule notnegative violated') - else: - return eval_notnegative_wr - diff --git a/src/exp2python/python/setup.py b/src/exp2python/python/LICENSE similarity index 81% rename from src/exp2python/python/setup.py rename to src/exp2python/python/LICENSE index bda974879..6e4fe3b3b 100644 --- a/src/exp2python/python/setup.py +++ b/src/exp2python/python/LICENSE @@ -1,9 +1,10 @@ -#!/usr/bin/env python - # Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# Copyright (c) 2014, Christopher HORLER (cshorler@googlemail.com) +# Copyright (c) 2021, Devon Sparks (devonsparks.com) + # All rights reserved. -# This file is part StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -29,15 +30,4 @@ # 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. - -from distutils.core import setup - -setup(name='SCL', - version='0.5', - description='Python STEP Class Library', - author='Thomas Paviot', - author_email='tpaviot@gmail.com', - url='https://github.com/mpictor/StepClassLibrary', - packages=['SCL'], - ) \ No newline at end of file +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/src/exp2python/python/README.md b/src/exp2python/python/README.md new file mode 100644 index 000000000..20278a512 --- /dev/null +++ b/src/exp2python/python/README.md @@ -0,0 +1,22 @@ +# stepcode - A Python3 STEP Library + +STEPCODE Python is a Python3-based library for parsing and manipulating ISO 10303 Part 21 ("STEP") files. + +# Use + +To parse a ISO 10303 Part 21 file, use the `Parser` class of `stepcode.Part21`. On a successful parse, the result will be a Part 21 parse tree and associated STEP instances. + +See [test_parser](tests/test_parser.py) for use of the `stepcode.Part21` parser with a sample STEP file. + + +# Building + +The stepcode Python package can be built directly using [PyPA's build module](https://github.com/pypa/build). Run `python3 -m build` from this directory. + +# Testing + +STEPCODE Python comes with a small test suite (additions welcome!) From this directory, `python3 -m unittest discover`. + +# License + +See [LICENSE](LICENSE) \ No newline at end of file diff --git a/src/exp2python/python/pyproject.toml b/src/exp2python/python/pyproject.toml new file mode 100644 index 000000000..8d4a680fe --- /dev/null +++ b/src/exp2python/python/pyproject.toml @@ -0,0 +1,6 @@ +[build-system] +requires = [ + "setuptools>=40", + "wheel" +] +build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/src/exp2python/python/setup.cfg b/src/exp2python/python/setup.cfg new file mode 100644 index 000000000..3a05fbf27 --- /dev/null +++ b/src/exp2python/python/setup.cfg @@ -0,0 +1,22 @@ +[metadata] +name = stepcode +version = 0.7.0 +author = Thomas Paviot , Christopher HORLER (cshorler@googlemail.com), Devon Sparks (devonsparks.com) +description = stepcode is a Python3-based library for parsing and manipulating ISO 10303 Part 21 ("STEP") files. +long_description = file: README.md +long_description_content_type = text/markdown + +url = https://github.com/stepcode/stepcode +project_urls = + Bug Tracker = https://github.com/stepcode/stepcode/issues +classifiers = + Programming Language :: Python :: 3 + +[options] +package_dir = + =. +packages = stepcode +python_requires = >=3.6 +install_requires = + ply + diff --git a/src/exp2python/python/SCL/AggregationDataTypes.py b/src/exp2python/python/stepcode/AggregationDataTypes.py similarity index 99% rename from src/exp2python/python/SCL/AggregationDataTypes.py rename to src/exp2python/python/stepcode/AggregationDataTypes.py index 09c4892b1..9dfd1b1a0 100644 --- a/src/exp2python/python/SCL/AggregationDataTypes.py +++ b/src/exp2python/python/stepcode/AggregationDataTypes.py @@ -1,7 +1,7 @@ # Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) # All rights reserved. -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -29,11 +29,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from SimpleDataTypes import * -from TypeChecker import check_type -import BaseType +from .SimpleDataTypes import * +from .TypeChecker import check_type +from . import BaseType -class BaseAggregate(object): +class BaseAggregate: """ A class that define common properties to ARRAY, LIST, SET and BAG. """ def __init__( self , bound1 , bound2 , base_type ): diff --git a/src/exp2python/python/SCL/BaseType.py b/src/exp2python/python/stepcode/BaseType.py similarity index 96% rename from src/exp2python/python/SCL/BaseType.py rename to src/exp2python/python/stepcode/BaseType.py index a92fc39fa..64bf779f2 100644 --- a/src/exp2python/python/SCL/BaseType.py +++ b/src/exp2python/python/stepcode/BaseType.py @@ -1,8 +1,7 @@ -from __future__ import print_function # Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) # All rights reserved. -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -30,7 +29,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -class Type(object): +class Type: ''' A type can be defined from its name and scope Looking into the scope dict returns the python type class. diff --git a/src/exp2python/python/SCL/Builtin.py b/src/exp2python/python/stepcode/Builtin.py similarity index 99% rename from src/exp2python/python/SCL/Builtin.py rename to src/exp2python/python/stepcode/Builtin.py index 54b7eb167..0d71466a1 100644 --- a/src/exp2python/python/SCL/Builtin.py +++ b/src/exp2python/python/stepcode/Builtin.py @@ -1,7 +1,7 @@ # Copyright (c) 2011-2012, Thomas Paviot (tpaviot@gmail.com) # All rights reserved. -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -32,9 +32,9 @@ __doc__ = "This module defines EXPRESS built in constants and functions" import math -from SimpleDataTypes import * -from BaseType import Aggregate -from AggregationDataTypes import * +from .SimpleDataTypes import * +from .BaseType import Aggregate +from .AggregationDataTypes import * SCL_float_epsilon = 1e-7 # Builtin constants @@ -713,4 +713,4 @@ def VALUE_UNIQUE(V): raise TypeError("VALUE_UNIQUE method takes an aggregate as first parameter") return V.get_value_unique() - \ No newline at end of file + diff --git a/src/exp2python/python/SCL/ConstructedDataTypes.py b/src/exp2python/python/stepcode/ConstructedDataTypes.py similarity index 97% rename from src/exp2python/python/SCL/ConstructedDataTypes.py rename to src/exp2python/python/stepcode/ConstructedDataTypes.py index f272994ef..9b9d8bc5e 100644 --- a/src/exp2python/python/SCL/ConstructedDataTypes.py +++ b/src/exp2python/python/stepcode/ConstructedDataTypes.py @@ -1,7 +1,7 @@ # Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) # All rights reserved. -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -29,9 +29,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import sys from enum import Enum -import BaseType +from . import BaseType class ENUMERATION(Enum): """ @@ -59,7 +58,7 @@ class ENUMERATION(Enum): """ pass -class SELECT(object): +class SELECT: """ A select data type has as its domain the union of the domains of the named data types in its select list. The select data type is a generalization of each of the named data types in its select list. diff --git a/src/exp2python/python/SCL/Model.py b/src/exp2python/python/stepcode/Model.py similarity index 95% rename from src/exp2python/python/SCL/Model.py rename to src/exp2python/python/stepcode/Model.py index c697dfa66..0a2d20aca 100644 --- a/src/exp2python/python/SCL/Model.py +++ b/src/exp2python/python/stepcode/Model.py @@ -1,8 +1,7 @@ -from __future__ import print_function # Copyright (c) 2011-2012, Thomas Paviot (tpaviot@gmail.com) # All rights reserved. -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -30,7 +29,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -class Model(object): +class Model: """ The container for entity instances """ def __init_(self): diff --git a/src/exp2python/python/SCL/Part21.py b/src/exp2python/python/stepcode/Part21.py similarity index 71% rename from src/exp2python/python/SCL/Part21.py rename to src/exp2python/python/stepcode/Part21.py index 3490b55bf..8c8be8fef 100644 --- a/src/exp2python/python/SCL/Part21.py +++ b/src/exp2python/python/stepcode/Part21.py @@ -6,7 +6,7 @@ # # All rights reserved. # -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -41,19 +41,6 @@ from ply.lex import LexError logger = logging.getLogger(__name__) - -# ensure Python 2.6 compatibility -if not hasattr(logging, 'NullHandler'): - class NullHandler(logging.Handler): - def handle(self, record): - pass - def emit(self, record): - pass - def createLock(self): - self.lock = None - - setattr(logging, 'NullHandler', NullHandler) - logger.addHandler(logging.NullHandler()) #################################################################################################### @@ -66,19 +53,19 @@ def createLock(self): #################################################################################################### # Lexer #################################################################################################### -class Lexer(object): +class Lexer: tokens = list(base_tokens) states = (('slurp', 'exclusive'),) - def __init__(self, debug=0, optimize=0, compatibility_mode=False, header_limit=4096): + def __init__(self, debug=False, optimize=False, compatibility_mode=False, header_limit=4096): self.base_tokens = list(base_tokens) self.schema_dict = {} self.active_schema = {} self.input_length = 0 self.compatibility_mode = compatibility_mode self.header_limit = header_limit - self.lexer = lex.lex(module=self, debug=debug, debuglog=logger, optimize=optimize, - errorlog=logger) + self.lexer = lex.lex(module=self, debug=debug, optimize=optimize, lextab='l21tab', + debuglog=logger, errorlog=logger) self.reset() def __getattr__(self, name): @@ -98,10 +85,7 @@ def reset(self): self.lexer.begin('slurp') def token(self): - try: - return next(self.lexer) - except StopIteration: - return None + return self.lexer.token() def activate_schema(self, schema_name): if schema_name in self.schema_dict: @@ -138,6 +122,9 @@ def t_slurp_error(self, t): t.lexer.lineno += t.value[0:offset].count('\n') t.lexer.skip(offset) + def t_error(self, t): + raise LexError("Scanning error, invalid input", "{0}...".format(t.value[0:20])) + # Comment (ignored) def t_COMMENT(self, t): r'/\*(.|\n)*?\*/' @@ -206,8 +193,8 @@ def t_BINARY(self, t): # Punctuation literals = '()=;,*$' - t_ANY_ignore = ' \t' - + t_ANY_ignore = ' \t\r' + #################################################################################################### # Simple Model @@ -225,24 +212,24 @@ def __init__(self, file_description, file_name, file_schema): self.extra_headers = [] class HeaderEntity: - def __init__(self, type_name, *params): + def __init__(self, type_name, params): self.type_name = type_name - self.params = list(params) if params else [] + self.params = params class Section: def __init__(self, entities): self.entities = entities class SimpleEntity: - def __init__(self, ref, type_name, *params): + def __init__(self, ref, type_name, params): self.ref = ref self.type_name = type_name - self.params = list(params) if params else [] + self.params = params class ComplexEntity: - def __init__(self, ref, *params): + def __init__(self, ref, params): self.ref = ref - self.params = list(params) if params else [] + self.params = params class TypedParameter: def __init__(self, type_name, *params): @@ -252,17 +239,23 @@ def __init__(self, type_name, *params): #################################################################################################### # Parser #################################################################################################### -class Parser(object): +class Parser: tokens = list(base_tokens) - start = 'exchange_file' - def __init__(self, lexer=None, debug=0): - self.lexer = lexer if lexer else Lexer() - + def __init__(self, lexer=None, debug=False, tabmodule=None, start=None, optimize=False): + # defaults + start_tabs = {'exchange_file': 'p21tab', 'extract_header': 'p21hdrtab'} + if start and tabmodule: start_tabs[start] = tabmodule + if not start: start = 'exchange_file' + if start not in start_tabs: raise ValueError('please pass (dedicated) tabmodule') + + # lexer may provide a more specialised set of tokens for use in (subclassed) parser try: self.tokens = lexer.tokens except AttributeError: pass - self.parser = yacc.yacc(module=self, debug=debug, debuglog=logger, errorlog=logger) + self.lexer = lexer if lexer else Lexer() + self.parser = yacc.yacc(debug=debug, module=self, tabmodule=start_tabs[start], start=start, + optimize=optimize, debuglog=logger, errorlog=logger) self.reset() def parse(self, p21_data, **kwargs): @@ -272,7 +265,7 @@ def parse(self, p21_data, **kwargs): if 'debug' in kwargs: result = self.parser.parse(lexer=self.lexer, debug=logger, - ** dict((k, v) for k, v in kwargs.iteritems() if k != 'debug')) + ** dict((k, v) for k, v in kwargs.items() if k != 'debug')) else: result = self.parser.parse(lexer=self.lexer, **kwargs) return result @@ -284,6 +277,12 @@ def reset(self): def p_exchange_file(self, p): """exchange_file : check_p21_start_token header_section data_section_list check_p21_end_token""" p[0] = P21File(p[2], p[3]) + + def p_extract_header(self, p): + """extract_header : check_p21_start_token header_section DATA""" + p[0] = P21File(p[2], []) + # clear input to avoid trailing context errors + p.lexer.input('') def p_check_start_token(self, p): """check_p21_start_token : PART21_START""" @@ -323,9 +322,8 @@ def p_simple_entity_instance(self, p): p[0] = SimpleEntity(p[1], *p[3]) def p_entity_instance_error(self, p): - """simple_entity_instance : error '=' simple_record ';' - complex_entity_instance : error '=' subsuper_record ';'""" - pass + """entity_instance : check_entity_instance_name '=' error ';'""" + logger.error('resyncing parser, check input between lineno %d and %d', p.lineno(2), p.lineno(4)) def p_complex_entity_instance(self, p): """complex_entity_instance : check_entity_instance_name '=' subsuper_record ';'""" @@ -333,25 +331,34 @@ def p_complex_entity_instance(self, p): def p_subsuper_record(self, p): """subsuper_record : '(' simple_record_list ')'""" - p[0] = [TypedParameter(*x) for x in p[2]] + p[0] = [SimpleEntity(None, *x) for x in p[2]] + def p_data_section_list_init(self, p): + """data_section_list : data_section""" + p[0] = [p[1],] + def p_data_section_list(self, p): - """data_section_list : data_section_list data_section - | data_section""" - try: p[0] = p[1] + [p[2],] - except IndexError: p[0] = [p[1],] + """data_section_list : data_section_list data_section""" + p[0] = p[1] + p[0].append(p[2]) + def p_header_entity_list_init(self, p): + """header_entity_list : header_entity""" + p[0] = [p[1],] + def p_header_entity_list(self, p): - """header_entity_list : header_entity_list header_entity - | header_entity""" - try: p[0] = p[1] + [p[2],] - except IndexError: p[0] = [p[1],] + """header_entity_list : header_entity_list header_entity""" + p[0] = p[1] + p[0].append(p[2]) + def p_parameter_list_init(self, p): + """parameter_list : parameter""" + p[0] = [p[1],] + def p_parameter_list(self, p): - """parameter_list : parameter_list ',' parameter - | parameter""" - try: p[0] = p[1] + [p[3],] - except IndexError: p[0] = [p[1],] + """parameter_list : parameter_list ',' parameter""" + p[0] = p[1] + p[0].append(p[3]) def p_keyword(self, p): """keyword : USER_DEFINED_KEYWORD @@ -385,7 +392,7 @@ def p_parameter_empty_list(self, p): def p_data_start(self, p): """data_start : DATA '(' parameter_list ')' ';'""" - pass + pass # TODO: do something with the parameters def p_data_start_empty(self, p): """data_start : DATA '(' ')' ';' @@ -396,11 +403,14 @@ def p_data_section(self, p): """data_section : data_start entity_instance_list ENDSEC""" p[0] = Section(p[2]) + def p_entity_instance_list_init(self, p): + """entity_instance_list : entity_instance""" + p[0] = [p[1],] + def p_entity_instance_list(self, p): - """entity_instance_list : entity_instance_list entity_instance - | entity_instance""" - try: p[0] = p[1] + [p[2],] - except IndexError: p[0] = [p[1],] + """entity_instance_list : entity_instance_list entity_instance""" + p[0] = p[1] + p[0].append(p[2]) def p_entity_instance_list_empty(self, p): """entity_instance_list : empty""" @@ -420,18 +430,41 @@ def p_simple_record_with_params(self, p): """simple_record : keyword '(' parameter_list ')'""" p[0] = (p[1], p[3]) + def p_simple_record_list_init(self, p): + """simple_record_list : simple_record""" + p[0] = [p[1],] + def p_simple_record_list(self, p): - """simple_record_list : simple_record_list simple_record - | simple_record""" - try: p[0] = p[1] + [p[2],] - except IndexError: p[0] = [p[1],] + """simple_record_list : simple_record_list simple_record""" + p[0] = p[1] + p[0].append(p[2]) def p_empty(self, p): """empty :""" pass -def test_debug(): - import os.path + +def debug_lexer(): + import codecs + from os.path import normpath, expanduser + + logging.basicConfig() + logger.setLevel(logging.DEBUG) + + lexer = Lexer(debug=True) + + p = normpath(expanduser('~/projects/src/stepcode/data/ap209/ATS7-out.stp')) + with codecs.open(p, 'r', encoding='iso-8859-1') as f: + s = f.read() + lexer.input(s) + while True: + tok = lexer.token() + if not tok: break + print(tok) + +def debug_parser(): + import codecs + from os.path import normpath, expanduser logging.basicConfig() logger.setLevel(logging.DEBUG) @@ -440,36 +473,73 @@ def test_debug(): parser.reset() logger.info("***** parser debug *****") - p = os.path.expanduser('~/projects/src/stepcode/data/ap214e3/s1-c5-214/s1-c5-214.stp') - with open(p, 'rU') as f: + p = normpath(expanduser('~/projects/src/stepcode/data/ap214e3/s1-c5-214/s1-c5-214.stp')) + with codecs.open(p, 'r', encoding='iso-8859-1') as f: s = f.read() - try: - parser.parse(s, debug=1) - except SystemExit: - pass + parser.parse(s, debug=1) logger.info("***** finished *****") def test(): - import os, os.path, itertools, codecs + import os, codecs + from os.path import normpath, expanduser logging.basicConfig() logger.setLevel(logging.INFO) + + lexer = Lexer(optimize=True) + parser = Parser(lexer=lexer, optimize=True) + compat_list = [] - parser = Parser() + def parse_check(p): + logger.info("processing {0}".format(p)) + parser.reset() + with codecs.open(p, 'r', encoding='iso-8859-1') as f: + s = f.read() + parser.parse(s) + + logger.info("***** standard test *****") + stepcode_dir = normpath(os.path.expanduser('~/projects/src/stepcode')) + for d, _, files in os.walk(stepcode_dir): + for f in filter(lambda x: x.endswith('.stp'), files): + p = os.path.join(d, f) + try: + parse_check(p) + except LexError: + logger.exception('Lexer issue, adding {0} to compatibility test list'.format(os.path.basename(p))) + compat_list.append(p) + + lexer = Lexer(optimize=True, compatibility_mode=True) + parser = Parser(lexer=lexer, optimize=True) + + logger.info("***** compatibility test *****") + for p in compat_list: + parse_check(p) + + logger.info("***** finished *****") + +def test_header_only(): + import os, codecs + from os.path import normpath, expanduser + + logging.basicConfig() + logger.setLevel(logging.INFO) + + lexer = Lexer(optimize=True) + parser = Parser(start='extract_header', optimize=True) compat_list = [] def parse_check(p): logger.info("processing {0}".format(p)) parser.reset() - with open(p, 'rU') as f: - iso_wrapper = codecs.EncodedFile(f, 'iso-8859-1') - s = iso_wrapper.read() + with codecs.open(p, 'r', encoding='iso-8859-1') as f: + s = f.read() parser.parse(s) logger.info("***** standard test *****") - for d, _, files in os.walk(os.path.expanduser('~/projects/src/stepcode')): - for f in itertools.ifilter(lambda x: x.endswith('.stp'), files): + stepcode_dir = normpath(os.path.expanduser('~/projects/src/stepcode')) + for d, _, files in os.walk(stepcode_dir): + for f in filter(lambda x: x.endswith('.stp'), files): p = os.path.join(d, f) try: parse_check(p) @@ -477,8 +547,8 @@ def parse_check(p): logger.exception('Lexer issue, adding {0} to compatibility test list'.format(os.path.basename(p))) compat_list.append(p) - lexer = Lexer(compatibility_mode=True) - parser = Parser(lexer=lexer) + lexer = Lexer(optimize=True, compatibility_mode=True) + parser = Parser(lexer=lexer, start='extract_header', optimize=True) logger.info("***** compatibility test *****") for p in compat_list: @@ -487,4 +557,7 @@ def parse_check(p): logger.info("***** finished *****") if __name__ == '__main__': + #debug_lexer() + #debug_parser() test() + #test_header_only() diff --git a/src/exp2python/python/SCL/Rules.py b/src/exp2python/python/stepcode/Rules.py similarity index 95% rename from src/exp2python/python/SCL/Rules.py rename to src/exp2python/python/stepcode/Rules.py index 1267a99d6..4c01e15a0 100644 --- a/src/exp2python/python/SCL/Rules.py +++ b/src/exp2python/python/stepcode/Rules.py @@ -1,7 +1,7 @@ # Copyright (c) 2011-2012, Thomas Paviot (tpaviot@gmail.com) # All rights reserved. -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -31,7 +31,7 @@ __doc__ = "This module defines EXPRESS rules" -class Rule(object): +class Rule: ''' This class describes a RULE @TODO: to be implemented diff --git a/src/exp2python/python/SCL/SCLBase.py b/src/exp2python/python/stepcode/SCLBase.py similarity index 91% rename from src/exp2python/python/SCL/SCLBase.py rename to src/exp2python/python/stepcode/SCLBase.py index 617c816ad..aebc880f3 100644 --- a/src/exp2python/python/SCL/SCLBase.py +++ b/src/exp2python/python/stepcode/SCLBase.py @@ -1,7 +1,8 @@ # Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# Copyright (c) 2022, Chris Horler (cshorler@googlemail.com) # All rights reserved. -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -29,7 +30,12 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -class BaseEntityClass(object): +__all__ = ['BaseEntityClass'] + +def raise_(exc): + raise exc + +class BaseEntityClass: """ A class that allows advanced __repr__ features for entity instances """ def __repr__(self): diff --git a/src/exp2python/python/SCL/SimpleDataTypes.py b/src/exp2python/python/stepcode/SimpleDataTypes.py similarity index 99% rename from src/exp2python/python/SCL/SimpleDataTypes.py rename to src/exp2python/python/stepcode/SimpleDataTypes.py index d1a99f259..4e1d0a508 100644 --- a/src/exp2python/python/SCL/SimpleDataTypes.py +++ b/src/exp2python/python/stepcode/SimpleDataTypes.py @@ -1,7 +1,7 @@ # Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) # All rights reserved. -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -32,7 +32,6 @@ """ Docstrings are courtesy of ISO 10303-11:1994(E) """ -from __future__ import print_function class NUMBER: """ diff --git a/src/exp2python/python/SCL/TypeChecker.py b/src/exp2python/python/stepcode/TypeChecker.py similarity index 97% rename from src/exp2python/python/SCL/TypeChecker.py rename to src/exp2python/python/stepcode/TypeChecker.py index d46b00aad..c97d7c11f 100644 --- a/src/exp2python/python/SCL/TypeChecker.py +++ b/src/exp2python/python/stepcode/TypeChecker.py @@ -1,8 +1,7 @@ -from __future__ import print_function # Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) # All rights reserved. -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -30,8 +29,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from ConstructedDataTypes import ENUMERATION, SELECT -import BaseType +from .ConstructedDataTypes import ENUMERATION, SELECT +from . import BaseType RAISE_EXCEPTION_IF_TYPE_DOES_NOT_MATCH = True DEBUG = False diff --git a/src/exp2python/python/SCL/Utils.py b/src/exp2python/python/stepcode/Utils.py similarity index 88% rename from src/exp2python/python/SCL/Utils.py rename to src/exp2python/python/stepcode/Utils.py index 4ba119349..76e352fc3 100644 --- a/src/exp2python/python/SCL/Utils.py +++ b/src/exp2python/python/stepcode/Utils.py @@ -1,7 +1,9 @@ # Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# Copyright (c) 2021, Devon Sparks (devonsparks.com) + # All rights reserved. -# This file is part of the StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -30,7 +32,6 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ''' This module provide string utils''' -from __future__ import print_function def process_nested_parent_str(attr_str,idx=0): ''' @@ -62,10 +63,10 @@ def process_nested_parent_str(attr_str,idx=0): return params,k if __name__=="__main__": - print(process_nested_parent_str2("'A'")[0]) - print(process_nested_parent_str2("30.0,0.0,5.0")[0]) - print(process_nested_parent_str2("1,2,(3,4,5),6,7,8")[0]) - print(process_nested_parent_str2("(#9149,#9166),#9142,.T.")[0]) + print(process_nested_parent_str("'A'")[0]) + print(process_nested_parent_str("30.0,0.0,5.0")[0]) + print(process_nested_parent_str("1,2,(3,4,5),6,7,8")[0]) + print(process_nested_parent_str("(#9149,#9166),#9142,.T.")[0]) diff --git a/src/exp2python/python/SCL/__init__.py b/src/exp2python/python/stepcode/__init__.py similarity index 55% rename from src/exp2python/python/SCL/__init__.py rename to src/exp2python/python/stepcode/__init__.py index ebced4874..0bb38afaa 100644 --- a/src/exp2python/python/SCL/__init__.py +++ b/src/exp2python/python/stepcode/__init__.py @@ -1 +1 @@ -__all__ = ['SCLBase','SimpleDataTypes','AggregationDataTypes','TypeChecker','ConstructedDataTypes','Expr','Part21'] +__all__ = ['SCLBase','SimpleDataTypes','AggregationDataTypes','TypeChecker','ConstructedDataTypes','Part21'] diff --git a/src/exp2python/python/stepcode/_cPart21.c b/src/exp2python/python/stepcode/_cPart21.c new file mode 100644 index 000000000..2b93ac7ca --- /dev/null +++ b/src/exp2python/python/stepcode/_cPart21.c @@ -0,0 +1,4694 @@ +/* Generated by re2c 1.2.1 on Mon May 18 17:14:55 2020 */ +/* + * STEP Part 21 Parser + * + * Copyright (c) 2020, Christopher HORLER (cshorler@googlemail.com) + * + * All rights reserved. + * + * This file is part of the STEPCODE project. + * + * 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 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 HOLDER 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#define YYCTYPE unsigned char +#define YYCURSOR in->cur +#define YYLIMIT in->lim +#define YYMARKER in->mrk +#define YYCTXMARKER in->ctxmrk +#define YYFILL(n) do { \ + if (fill(in, n) != 0) { \ + fprintf(stderr, "lexer fill(...) failed, exiting\n"); \ + exit(1); \ + } \ + } while (0) + +#define YYMAXFILL 17 + +#define INIT_BUF_SZ 4096 +#define INIT_STACK_SZ 64 + +/* reserved literals '(' ')' ';' '=' */ +#define T_P21_START 'S' +#define T_P21_END 'X' +#define T_HEADER 'H' +#define T_DATA 'D' +#define T_ENDSEC 'E' +#define T_EID 'I' +#define T_KEYWORD 'K' +#define T_VARIANT 'V' +#define T_EOF '\x00' +#define T_ERROR '\x01' + +#define V_REAL 'r' +#define V_INTEGER 'i' +#define V_STRING 's' +#define V_BINARY 'b' +#define V_ENUMERATION 'e' +#define V_EID T_EID +#define V_DERIVED '*' +#define V_EMPTY '$' + +#define P_FILE 'f' +#define P_HEADERSECTION 'h' +#define P_DATASECTION 'd' +#define P_HEADERENTITY 'x' +#define P_SIMPLEENTITY 's' +#define P_COMPLEXENTITY 'c' +#define P_SIMPLERECORD 'u' +#define P_LIST 'l' +#define P_PARAMETER 'p' + +int debug = 1; +#define dprintf(fmt, ...) \ + do { if (debug) fprintf(stderr, "%s:%3d " fmt, __FILE__, __LINE__, ##__VA_ARGS__); } while (0) + +/* ppfu https://stackoverflow.com/a/11763277/1162349 */ +#define GET_MACRO(_1, _2, _3, _4, NAME, ...) NAME +#define _EXPAND(x) x + +/* for lookahead */ +#define PUSH_SYMBOL(...) _EXPAND(GET_MACRO(__VA_ARGS__, _4, _3, _PUSH_SYMBOL2, _PUSH_SYMBOL1)(__VA_ARGS__)) +#define _PUSH_SYMBOL1(token) in->sym[in->nsym++] = (Symbol){(token), 0, n, in->lineno, in->sp - in->basemrk} +#define _PUSH_SYMBOL2(token, vtype) in->sym[in->nsym++] = (Symbol){(token), (vtype), n, in->lineno, in->sp - in->basemrk} + +/* for parse stack */ +#define PUSH_TERMINAL(stack, sym) do { \ + Symbol it = (sym); \ + push((stack), it); \ + if (it.token == T_ERROR) goto err; \ + } while (0) + +#define PUSH_TERMINAL_EXT(cxt, stack, sym) do { \ + Symbol it = (sym); \ + push((stack), it); \ + if (it.token == T_ERROR) goto err; \ + else if (it.token == '(') (cxt) = (stack)->idx_top - 1; \ + else if (it.token == ')') (stack)->items[(cxt)].n = (stack)->idx_top - (cxt) - 1; \ + } while (0) + +/* test for one in a set of 1 to 4 e.g. {t0, t1, t2, t3} */ +#define LOOKAHEAD(x, ...) _EXPAND(GET_MACRO(__VA_ARGS__, _LOOKAHEAD4, _LOOKAHEAD3, _LOOKAHEAD2, _LOOKAHEAD1)(x, __VA_ARGS__)) +#define _LOOKAHEAD1(x, t0) ((t0) == (x).token) +#define _LOOKAHEAD2(x, t0, t1) ((t0) == (x).token || (t1) == (x).token) +#define _LOOKAHEAD3(x, t0, t1, t2) (_LOOKAHEAD2(x, t0, t1) || (t2) == (x).token) +#define _LOOKAHEAD4(x, t0, t1, t2, t3) (_LOOKAHEAD2(x, t0, t1) || _LOOKAHEAD2(x, t2, t3)) + + + + + +/* lexeme */ +typedef struct { + uint8_t token; + union { + uint8_t vtype; + uint8_t errtoken; + }; + uint16_t n; + uint32_t lineno; + union { + ptrdiff_t offset; /* from basemrk */ + void *data; /* production allocation if applicable */ + }; +} Symbol; + +typedef struct SimpleRecord_ { + Symbol *kw; /* 'KEYWORD' */ + Symbol *args;/* '(' */ +} SimpleRecord; + +typedef struct SimpleRecord_ HeaderEntity; + +typedef struct { + Symbol *eid; /* '#' */ + Symbol *eq; /* '=' */ + Symbol *kw; /* 'KEYWORD' */ + Symbol *args;/* '(' */ +} SimpleEntity; + +typedef struct { + Symbol *eid; /* '#' */ + Symbol *eq; /* '=' */ + Symbol *subsupers;/* '(' */ +} ComplexEntity; + + +typedef struct { + FILE *file; + size_t bufsz; + unsigned char *cur, *mrk, *ctxmrk, *lim; + unsigned char *sp, *basemrk; + int eof; + uint32_t lineno; + int nsym; + Symbol sym[3]; + unsigned char *buf; +} Input; + +typedef struct { + int idx_top; + int idx_lim; + Symbol *items; +} Stack; + +/* LL(3) parser */ +typedef struct { + bool error; + bool hold; + Input *in; + Stack *stack; +} P21Parser; + +typedef void (p21_action_cb_t) (P21Parser *, int, void *); +typedef void (p21_error_cb_t) (P21Parser *, int, uint8_t); +typedef void (p21_ud_cb_t) (void *); + +typedef struct { + void *userdata; + p21_error_cb_t *error_cb; + p21_ud_cb_t *ud_init_cb; + p21_ud_cb_t *ud_exit_cb; + p21_action_cb_t *exchange_file_cb; + p21_action_cb_t *header_start_cb; + p21_action_cb_t *header_entity_list_cb; + p21_action_cb_t *data_section_list_cb; + p21_action_cb_t *data_start_cb; + p21_action_cb_t *header_entity_cb; + p21_action_cb_t *simple_entity_instance_cb; + p21_action_cb_t *complex_entity_instance_cb; + p21_action_cb_t *parameter_list_cb; + p21_action_cb_t *parameter_cb; + p21_action_cb_t *entity_instance_list_cb; + p21_action_cb_t *entity_instance_cb; + p21_action_cb_t *simple_record_list_cb; + p21_action_cb_t *simple_record_cb; +} P21ParserActions; + + +void report_error(P21Parser *, const char *); +void _recover(Input *, uint8_t, uint8_t, uint8_t); +Symbol lpop(Input *, uint8_t); + +void p21_parse(P21Parser *, P21ParserActions *); +void p21_exchange_file(P21Parser *, P21ParserActions *); +void p21_header_section(P21Parser *, P21ParserActions *); +void p21_header_entity_list(P21Parser *, P21ParserActions *); +void p21_header_entity(P21Parser *, P21ParserActions *); +void p21_data_section_list(P21Parser *, P21ParserActions *); +void p21_data_section(P21Parser *, P21ParserActions *); +void p21_entity_instance(P21Parser *, P21ParserActions *); +void p21_simple_entity_instance(P21Parser *, P21ParserActions *); +void p21_complex_entity_instance(P21Parser *, P21ParserActions *); +void p21_entity_instance_list(P21Parser *, P21ParserActions *); +void p21_parameter(P21Parser *, P21ParserActions *); +void p21_parameter_list(P21Parser *, P21ParserActions *); +void p21_simple_record(P21Parser *, P21ParserActions *); +void p21_simple_record_list(P21Parser *, P21ParserActions *); + + +void push(Stack *stack, Symbol it) { + if (stack->idx_top == stack->idx_lim) { + Symbol *nitems = realloc(stack->items, 2 * stack->idx_lim * sizeof stack->items[0]); + if (!nitems) { + fprintf(stderr, "failed to grow parser stack, memory exhausted\n"); + exit(1); + } + stack->items = nitems; + stack->idx_lim *= 2; + } + + stack->items[stack->idx_top++] = it; +} + +/* mock implementations */ +void drop(Stack *stack, uint32_t n) { + assert(stack->idx_top >= n); + stack->idx_top -= n; +} + +void unwind(Stack *stack, int bsp) { + stack->idx_top = bsp; +} + +Symbol *pop(Stack *stack) { + assert(stack->idx_top >= 1); + stack->idx_top--; + return stack->items + stack->idx_top; +} + +Symbol *peek(Stack *stack) { + assert(stack->idx_top >= 1); + return stack->items + stack->idx_top - 1; +} + +Symbol lpop(Input *in, uint8_t token) { + Symbol *stack = in->sym; + Symbol sym = stack[0]; + + /* missing input or unexpected lookahead token */ + if (in->nsym == 0) + return (Symbol){T_ERROR, token, 0, in->lineno}; + else if (sym.token != token) + return (Symbol){T_ERROR, token, 0, sym.lineno}; + + if (!--in->nsym) { + memset(&in->sym[0], 0, sizeof in->sym[0]); + } else { + memmove(&in->sym[0], &in->sym[1], in->nsym * sizeof in->sym[0]); + memset(&in->sym[in->nsym], 0, sizeof in->sym[0]); + } + + return sym; +} + +static int fill(Input *in, size_t need) +{ + size_t free; + unsigned char *newbuf; + + if (in->eof) { + return 1; + } + free = in->basemrk - in->buf; + if (free < need) { + newbuf = realloc(in->buf, 2 * in->bufsz + YYMAXFILL); + if (!newbuf) { + fprintf(stderr, "fatal - buffer memory exhausted, exiting\n"); + return 2; + } + in->bufsz *= 2; + in->lim = newbuf + (in->lim - in->buf); + in->cur = newbuf + (in->cur - in->buf); + in->mrk = newbuf + (in->mrk - in->buf); + in->ctxmrk = newbuf + (in->ctxmrk - in->buf); + in->basemrk = newbuf + (in->basemrk - in->buf); + in->sp = newbuf + (in->sp - in->buf); + in->buf = newbuf; + + /* don't memmove() here! */ + free = (in->buf + in->bufsz) - in->lim; + } else { + memmove(in->buf, in->basemrk, in->lim - in->basemrk); + in->lim -= free; + in->cur -= free; + in->mrk -= free; + in->ctxmrk -= free; + in->basemrk -= free; + in->sp -= free; + } + + in->lim += fread(in->lim, 1, free, in->file); + if (in->lim < in->buf + in->bufsz) { + in->eof = 1; + memset(in->lim, 0, YYMAXFILL); + in->lim += YYMAXFILL; + } + return 0; +} + +static void p21_init(P21Parser *p, FILE *file) +{ + Stack *stack; + Input *in; + + in = malloc(sizeof *in); + if (!in) + goto err; + memset(in, 0, sizeof *in); + in->bufsz = INIT_BUF_SZ; + in->buf = malloc(INIT_BUF_SZ + YYMAXFILL); + if (!in->buf) + goto err; + in->file = file; + in->cur = in->basemrk = in->sp = in->lim = in->buf + INIT_BUF_SZ; + in->lineno = 1; + fill(in, 1); + + stack = malloc(sizeof *stack); + if (!stack) + goto err; + memset(stack, 0, sizeof *stack); + stack->idx_lim = 16; + stack->idx_top = 0; + stack->items = malloc(stack->idx_lim * sizeof stack->items[0]); + if (!stack->items) + goto err; + + p->in = in; + p->stack = stack; + p->error = false; + + return; + +err: + fprintf(stderr, "failed to initialise parser\n"); + exit(1); +} + +/* noop error handler */ +void default_error_handler(P21Parser *p, int bsp, uint8_t t) { + Symbol *sym = peek(p->stack); + if (sym->token == T_ERROR) + pop(p->stack); + push(p->stack, (Symbol){t}); +} + +/* TODO: this needs to be reworked */ +void report_error(P21Parser *p, const char *cxt) { + Input *in = p->in; + Symbol *it = peek(p->stack); + int lineno; + unsigned char *cur; + + fprintf(stderr, cxt); + + if (it->token == T_ERROR) { + fprintf(stderr, " syntax error - line: %d\n", it->lineno); + fprintf(stderr, " expected '%c' (token type) ", it->errtoken); + } else { + cur = in->cur; + lineno = in->lineno; + while (1) { + if (*(cur - 2) == '\r' && *(cur - 1) == '\n') { cur -= 2; --lineno; } + else if (*(cur - 1) == '\n') { --cur; --lineno; } + else { break; } + } + fprintf(stderr, " syntax error - line: %d\n", lineno); + } + + if (!in->nsym) { + cur = in->cur; + lineno = in->lineno; + while (1) { + if (*cur == '\r' && *(cur + 1) == '\n') { cur -= 2; --lineno; } + else if (*cur == '\n') { --cur; --lineno; } + else { break; } + } + fprintf(stderr, " unexpected character '%c' (line: %d)\n", *cur, lineno); + } else { + fprintf(stderr, " got '%c' (token type)\n", in->sym[0].token); + } +} + + +void lex_comment(Input *in) { + size_t n; + int comment_lvl = 1; + + while (1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= '*') { + if (yych <= '\r') { + if (yych == '\n') goto yy4; + if (yych >= '\r') goto yy6; + } else { + if (yych <= 0x001F) goto yy2; + if (yych <= ' ') goto yy7; + if (yych <= ')') goto yy10; + goto yy13; + } + } else { + if (yych <= '[') { + if (yych == '/') goto yy16; + if (yych <= 'Z') goto yy10; + } else { + if (yych == ']') goto yy2; + if (yych <= '~') goto yy10; + } + } +yy2: + ++YYCURSOR; +yy3: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy4: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy6: + yych = *++YYCURSOR; + if (yych == '\n') goto yy4; + goto yy3; +yy7: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') { + if (yych <= ')') { + if (yych <= 0x001F) goto yy9; + if (yych <= ' ') goto yy7; + goto yy10; + } else { + if (yych <= '*') goto yy9; + if (yych <= '.') goto yy10; + } + } else { + if (yych <= '\\') { + if (yych != '[') goto yy10; + } else { + if (yych <= ']') goto yy9; + if (yych <= '~') goto yy10; + } + } +yy9: + { n = in->cur - in->sp; } + { continue; } +yy10: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') { + if (yych <= ')') { + if (yych >= ' ') goto yy10; + } else { + if (yych <= '*') goto yy12; + if (yych <= '.') goto yy10; + } + } else { + if (yych <= '\\') { + if (yych != '[') goto yy10; + } else { + if (yych <= ']') goto yy12; + if (yych <= '~') goto yy10; + } + } +yy12: + { n = in->cur - in->sp; } + { continue; } +yy13: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '*') goto yy13; + if (yych == '/') goto yy18; + { n = in->cur - in->sp; } + { continue; } +yy16: + yych = *++YYCURSOR; + if (yych == '*') goto yy20; + { n = in->cur - in->sp; } + { continue; } +yy18: + ++YYCURSOR; + { n = in->cur - in->sp; } + { + if (!--comment_lvl) { break; } + else { continue; } + } +yy20: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + + return; + +err: + fprintf(stderr, "invalid character in comment, exiting\n"); + exit(1); +} + +#define recover(in, ...) GET_MACRO(__VA_ARGS__, _4, _RECOVER3, _RECOVER2, _RECOVER1)(in, __VA_ARGS__) +#define _RECOVER1(in, u0) _recover((in), (u0), 0U, 0U) +#define _RECOVER2(in, u0, u1) _recover((in), (u0), (u1), 0U) +#define _RECOVER3(in, u0, u1, u2) _recover((in), (u0), (u1), (u2)) + +void _recover(Input *in, uint8_t u0, uint8_t u1, uint8_t u2) { + size_t n; + Symbol sym; + + while (in->nsym) { + if (LOOKAHEAD(in->sym[0], u0, u1, u2, T_EOF)) + break; + --in->nsym; + memmove(&in->sym[0], &in->sym[1], in->nsym * sizeof in->sym[0]); + memset(&in->sym[in->nsym], 0, sizeof in->sym[0]); + } + + if (in->nsym) + return; + + while (1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + unsigned int yyaccept = 0; + if ((YYLIMIT - YYCURSOR) < 17) YYFILL(17); + yych = *YYCURSOR; + if (yych <= '-') { + if (yych <= '"') { + if (yych <= '\r') { + if (yych == '\n') goto yy26; + if (yych >= '\r') goto yy28; + } else { + if (yych <= 0x001F) goto yy24; + if (yych <= ' ') goto yy29; + if (yych <= '!') goto yy32; + goto yy33; + } + } else { + if (yych <= '\'') { + if (yych <= '#') goto yy34; + if (yych <= '$') goto yy35; + if (yych >= '\'') goto yy37; + } else { + if (yych <= '*') { + if (yych <= ')') goto yy38; + goto yy40; + } else { + if (yych != ',') goto yy42; + } + } + } + } else { + if (yych <= 'E') { + if (yych <= ':') { + if (yych <= '.') goto yy43; + if (yych <= '/') goto yy44; + if (yych <= '9') goto yy45; + } else { + if (yych <= '@') { + if (yych <= ';') goto yy38; + } else { + if (yych <= 'C') goto yy48; + if (yych <= 'D') goto yy51; + goto yy52; + } + } + } else { + if (yych <= 'Z') { + if (yych <= 'G') goto yy48; + if (yych <= 'H') goto yy53; + if (yych <= 'I') goto yy54; + goto yy48; + } else { + if (yych <= '_') { + if (yych >= '_') goto yy48; + } else { + if (yych <= '`') goto yy24; + if (yych <= 'z') goto yy48; + } + } + } + } +yy24: + ++YYCURSOR; +yy25: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy26: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy28: + yych = *++YYCURSOR; + if (yych == '\n') goto yy26; + goto yy25; +yy29: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy29; + { n = in->cur - in->sp; } + { continue; } +yy32: + yych = *++YYCURSOR; + if (yych <= '^') { + if (yych <= '@') goto yy25; + if (yych <= 'Z') goto yy48; + goto yy25; + } else { + if (yych == '`') goto yy25; + if (yych <= 'z') goto yy48; + goto yy25; + } +yy33: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '/') goto yy25; + if (yych <= '3') goto yy55; + goto yy25; +yy34: + yych = *++YYCURSOR; + if (yych <= '/') goto yy25; + if (yych <= '9') goto yy58; + goto yy25; +yy35: + ++YYCURSOR; + { n = in->cur - in->sp; } + { sym = (Symbol){T_VARIANT, V_EMPTY}; goto check; } +yy37: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '[') { + if (yych <= 0x001F) goto yy25; + if (yych <= 'Z') goto yy62; + goto yy25; + } else { + if (yych == ']') goto yy25; + if (yych <= '~') goto yy62; + goto yy25; + } +yy38: + ++YYCURSOR; + { n = in->cur - in->sp; } + { sym = (Symbol){*in->sp}; goto check; } +yy40: + ++YYCURSOR; + { n = in->cur - in->sp; } + { sym = (Symbol){T_VARIANT, V_DERIVED}; goto check; } +yy42: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= ',') { + if (yych == '+') goto yy66; + goto yy25; + } else { + if (yych <= '-') goto yy66; + if (yych <= '/') goto yy25; + if (yych <= '9') goto yy45; + goto yy25; + } +yy43: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '@') goto yy25; + if (yych <= 'Z') goto yy68; + if (yych == '_') goto yy68; + goto yy25; +yy44: + yych = *++YYCURSOR; + if (yych == '*') goto yy70; + goto yy25; +yy45: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '.') goto yy72; + if (yych <= '/') goto yy47; + if (yych <= '9') goto yy45; +yy47: + { n = in->cur - in->sp; } + { sym = (Symbol){T_VARIANT, V_INTEGER}; goto check; } +yy48: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy49: + if (yych <= 'Z') { + if (yych <= '/') goto yy50; + if (yych <= '9') goto yy48; + if (yych >= 'A') goto yy48; + } else { + if (yych <= '_') { + if (yych >= '_') goto yy48; + } else { + if (yych <= '`') goto yy50; + if (yych <= 'z') goto yy48; + } + } +yy50: + { n = in->cur - in->sp; } + { sym = (Symbol){T_KEYWORD}; goto check; } +yy51: + yych = *++YYCURSOR; + if (yych == 'A') goto yy75; + goto yy49; +yy52: + yych = *++YYCURSOR; + if (yych == 'N') goto yy76; + goto yy49; +yy53: + yych = *++YYCURSOR; + if (yych == 'E') goto yy77; + goto yy49; +yy54: + yych = *++YYCURSOR; + if (yych == 'S') goto yy78; + goto yy49; +yy55: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') { + if (yych == '"') goto yy79; + } else { + if (yych <= '9') goto yy55; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy55; + } +yy57: + YYCURSOR = YYMARKER; + if (yyaccept <= 1) { + if (yyaccept == 0) { + goto yy25; + } else { + goto yy64; + } + } else { + if (yyaccept == 2) { + goto yy74; + } else { + goto yy50; + } + } +yy58: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy60; + if (yych <= '9') goto yy58; +yy60: + { n = in->cur - in->sp; } + { sym = (Symbol){T_EID}; goto check; } +yy61: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy62: + if (yych <= 'Z') { + if (yych <= 0x001F) goto yy57; + if (yych != '\'') goto yy61; + } else { + if (yych <= '\\') { + if (yych <= '[') goto yy57; + goto yy65; + } else { + if (yych <= ']') goto yy57; + if (yych <= '~') goto yy61; + goto yy57; + } + } + yyaccept = 1; + YYMARKER = ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\'') goto yy61; +yy64: + { n = in->cur - in->sp; } + { sym = (Symbol){T_VARIANT, V_STRING}; goto check; } +yy65: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 'S') { + if (yych <= '@') goto yy57; + if (yych <= 'I') goto yy81; + if (yych <= 'R') goto yy57; + goto yy82; + } else { + if (yych <= 'X') { + if (yych <= 'W') goto yy57; + goto yy83; + } else { + if (yych == '\\') goto yy61; + goto yy57; + } + } +yy66: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= ',') { + if (yych == '+') goto yy66; + goto yy57; + } else { + if (yych <= '-') goto yy66; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy45; + goto yy57; + } +yy68: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '9') { + if (yych == '.') goto yy84; + if (yych <= '/') goto yy57; + goto yy68; + } else { + if (yych <= 'Z') { + if (yych <= '@') goto yy57; + goto yy68; + } else { + if (yych == '_') goto yy68; + goto yy57; + } + } +yy70: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +yy72: + yyaccept = 2; + YYMARKER = ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy74; + if (yych <= '9') goto yy72; + if (yych == 'E') goto yy86; +yy74: + { n = in->cur - in->sp; } + { sym = (Symbol){T_VARIANT, V_REAL}; goto check; } +yy75: + yych = *++YYCURSOR; + if (yych == 'T') goto yy88; + goto yy49; +yy76: + yych = *++YYCURSOR; + if (yych == 'D') goto yy89; + goto yy49; +yy77: + yych = *++YYCURSOR; + if (yych == 'A') goto yy90; + goto yy49; +yy78: + yych = *++YYCURSOR; + if (yych == 'O') goto yy91; + goto yy49; +yy79: + ++YYCURSOR; + { n = in->cur - in->sp; } + { sym = (Symbol){T_VARIANT, V_BINARY}; goto check; } +yy81: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yy61; + goto yy57; +yy82: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yy92; + goto yy57; +yy83: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '3') { + if (yych == '2') goto yy93; + goto yy57; + } else { + if (yych <= '4') goto yy94; + if (yych == '\\') goto yy95; + goto yy57; + } +yy84: + ++YYCURSOR; + { n = in->cur - in->sp; } + { sym = (Symbol){T_VARIANT, V_ENUMERATION}; goto check; } +yy86: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= ',') { + if (yych == '+') goto yy86; + goto yy57; + } else { + if (yych <= '-') goto yy86; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy96; + goto yy57; + } +yy88: + yych = *++YYCURSOR; + if (yych == 'A') goto yy98; + goto yy49; +yy89: + yyaccept = 3; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == '-') goto yy99; + if (yych == 'S') goto yy100; + goto yy49; +yy90: + yych = *++YYCURSOR; + if (yych == 'D') goto yy101; + goto yy49; +yy91: + yyaccept = 3; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == '-') goto yy102; + goto yy49; +yy92: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '[') { + if (yych <= 0x001F) goto yy57; + if (yych <= 'Z') goto yy61; + goto yy57; + } else { + if (yych == ']') goto yy57; + if (yych <= '~') goto yy61; + goto yy57; + } +yy93: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yy103; + goto yy57; +yy94: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yy104; + goto yy57; +yy95: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy105; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy105; + goto yy57; +yy96: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy74; + if (yych <= '9') goto yy96; + goto yy74; +yy98: + yych = *++YYCURSOR; + if (yych <= ')') { + if (yych == ' ') goto yy106; + if (yych <= '\'') goto yy49; + goto yy106; + } else { + if (yych <= '/') { + if (yych <= '.') goto yy49; + goto yy106; + } else { + if (yych == ';') goto yy106; + goto yy49; + } + } +yy99: + yych = *++YYCURSOR; + if (yych == 'I') goto yy108; + goto yy57; +yy100: + yych = *++YYCURSOR; + if (yych == 'E') goto yy109; + goto yy49; +yy101: + yych = *++YYCURSOR; + if (yych == 'E') goto yy110; + goto yy49; +yy102: + yych = *++YYCURSOR; + if (yych == '1') goto yy111; + goto yy57; +yy103: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy112; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy112; + goto yy57; +yy104: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy113; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy113; + goto yy57; +yy105: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy61; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy61; + goto yy57; +yy106: + ++YYCURSOR; + YYCURSOR -= 1; + { n = in->cur - in->sp; } + { sym = (Symbol){T_DATA}; goto check; } +yy108: + yych = *++YYCURSOR; + if (yych == 'S') goto yy114; + goto yy57; +yy109: + yych = *++YYCURSOR; + if (yych == 'C') goto yy115; + goto yy49; +yy110: + yych = *++YYCURSOR; + if (yych == 'R') goto yy116; + goto yy49; +yy111: + yych = *++YYCURSOR; + if (yych == '0') goto yy117; + goto yy57; +yy112: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy118; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy118; + goto yy57; +yy113: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy119; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy119; + goto yy57; +yy114: + yych = *++YYCURSOR; + if (yych == 'O') goto yy120; + goto yy57; +yy115: + yych = *++YYCURSOR; + if (yych == ';') goto yy121; + goto yy49; +yy116: + yych = *++YYCURSOR; + if (yych == ';') goto yy123; + goto yy49; +yy117: + yych = *++YYCURSOR; + if (yych == '3') goto yy125; + goto yy57; +yy118: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy126; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy126; + goto yy57; +yy119: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy127; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy127; + goto yy57; +yy120: + yych = *++YYCURSOR; + if (yych == '-') goto yy128; + goto yy57; +yy121: + ++YYCURSOR; + { n = in->cur - in->sp; } + { sym = (Symbol){T_ENDSEC}; goto check; } +yy123: + ++YYCURSOR; + { n = in->cur - in->sp; } + { sym = (Symbol){T_HEADER}; goto check; } +yy125: + yych = *++YYCURSOR; + if (yych == '0') goto yy129; + goto yy57; +yy126: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy130; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy130; + goto yy57; +yy127: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy131; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy131; + goto yy57; +yy128: + yych = *++YYCURSOR; + if (yych == '1') goto yy132; + goto yy57; +yy129: + yych = *++YYCURSOR; + if (yych == '3') goto yy133; + goto yy57; +yy130: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '@') { + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy112; + goto yy57; + } else { + if (yych <= 'F') goto yy112; + if (yych == '\\') goto yy134; + goto yy57; + } +yy131: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy135; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy135; + goto yy57; +yy132: + yych = *++YYCURSOR; + if (yych == '0') goto yy136; + goto yy57; +yy133: + yych = *++YYCURSOR; + if (yych == '-') goto yy137; + goto yy57; +yy134: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == 'X') goto yy138; + goto yy57; +yy135: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy139; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy139; + goto yy57; +yy136: + yych = *++YYCURSOR; + if (yych == '3') goto yy140; + goto yy57; +yy137: + yych = *++YYCURSOR; + if (yych == '2') goto yy141; + goto yy57; +yy138: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '0') goto yy81; + goto yy57; +yy139: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy142; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy142; + goto yy57; +yy140: + yych = *++YYCURSOR; + if (yych == '0') goto yy143; + goto yy57; +yy141: + yych = *++YYCURSOR; + if (yych == '1') goto yy144; + goto yy57; +yy142: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy145; + if (yych <= '@') goto yy57; + if (yych <= 'F') goto yy145; + goto yy57; +yy143: + yych = *++YYCURSOR; + if (yych == '3') goto yy146; + goto yy57; +yy144: + yych = *++YYCURSOR; + if (yych == ';') goto yy147; + goto yy57; +yy145: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '@') { + if (yych <= '/') goto yy57; + if (yych <= '9') goto yy113; + goto yy57; + } else { + if (yych <= 'F') goto yy113; + if (yych == '\\') goto yy134; + goto yy57; + } +yy146: + yych = *++YYCURSOR; + if (yych == '-') goto yy149; + goto yy57; +yy147: + ++YYCURSOR; + { n = in->cur - in->sp; } + { sym = (Symbol){T_P21_START}; goto check; } +yy149: + yych = *++YYCURSOR; + if (yych != '2') goto yy57; + yych = *++YYCURSOR; + if (yych != '1') goto yy57; + yych = *++YYCURSOR; + if (yych != ';') goto yy57; + ++YYCURSOR; + { n = in->cur - in->sp; } + { sym = (Symbol){T_P21_END}; goto check; } +} + +check: + if (LOOKAHEAD(sym, u0, u1, u2, T_EOF)) { + PUSH_SYMBOL(sym.token, sym.vtype); + break; + } + } + + return; + +err: + fprintf(stderr, "fatal, failed to resolve follow set (%c, %c, %c)\n", u0, u1, u2); + exit(1); +} + + +/* + * P21Parser + */ +void p21_parse(P21Parser *p, P21ParserActions *act) { + if (act->ud_init_cb) + act->ud_init_cb(act->userdata); + + p21_exchange_file(p, act); + + if (act->ud_exit_cb) + act->ud_exit_cb(act->userdata); + + assert(p->stack->idx_top == 1); + return; + +err: + report_error(p, "exchange_file' << 0 >>\n"); +} + +void p21_exchange_file(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 13) YYFILL(13); + yych = *YYCURSOR; + if (yych <= 0x001F) { + if (yych <= '\n') { + if (yych >= '\n') goto yy158; + } else { + if (yych == '\r') goto yy160; + } + } else { + if (yych <= '/') { + if (yych <= ' ') goto yy161; + if (yych >= '/') goto yy164; + } else { + if (yych == 'I') goto yy165; + } + } + ++YYCURSOR; +yy157: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy158: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy160: + yych = *++YYCURSOR; + if (yych == '\n') goto yy158; + goto yy157; +yy161: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy161; + { n = in->cur - in->sp; } + { continue; } +yy164: + yych = *++YYCURSOR; + if (yych == '*') goto yy166; + goto yy157; +yy165: + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'S') goto yy168; + goto yy157; +yy166: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +yy168: + yych = *++YYCURSOR; + if (yych == 'O') goto yy170; +yy169: + YYCURSOR = YYMARKER; + goto yy157; +yy170: + yych = *++YYCURSOR; + if (yych != '-') goto yy169; + yych = *++YYCURSOR; + if (yych != '1') goto yy169; + yych = *++YYCURSOR; + if (yych != '0') goto yy169; + yych = *++YYCURSOR; + if (yych != '3') goto yy169; + yych = *++YYCURSOR; + if (yych != '0') goto yy169; + yych = *++YYCURSOR; + if (yych != '3') goto yy169; + yych = *++YYCURSOR; + if (yych != '-') goto yy169; + yych = *++YYCURSOR; + if (yych != '2') goto yy169; + yych = *++YYCURSOR; + if (yych != '1') goto yy169; + yych = *++YYCURSOR; + if (yych != ';') goto yy169; + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_P21_START); continue;} +} + + } + PUSH_TERMINAL(p->stack, lpop(in, T_P21_START)); + + p21_header_section(p, act); + p21_data_section_list(p, act); + + PUSH_TERMINAL(p->stack, lpop(in, T_P21_END)); + + if (p->error) + goto err; + + /* user action */ + if (act->exchange_file_cb) + act->exchange_file_cb(p, bsp, act->userdata); + + /* default reduction */ + p->stack->items[bsp] = (Symbol){P_FILE}; + drop(p->stack, p->stack->idx_top - bsp - 1); + + return; + +err: + report_error(p, "exchange_file << 1 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_FILE); + else default_error_handler(p, bsp, P_FILE); + recover(in, T_EOF); +} + +void p21_header_section(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7); + yych = *YYCURSOR; + if (yych <= 0x001F) { + if (yych <= '\n') { + if (yych >= '\n') goto yya186; + } else { + if (yych == '\r') goto yya188; + } + } else { + if (yych <= '/') { + if (yych <= ' ') goto yya189; + if (yych >= '/') goto yya192; + } else { + if (yych == 'H') goto yya193; + } + } + ++YYCURSOR; +yya185: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yya186: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yya188: + yych = *++YYCURSOR; + if (yych == '\n') goto yya186; + goto yya185; +yya189: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yya189; + { n = in->cur - in->sp; } + { continue; } +yya192: + yych = *++YYCURSOR; + if (yych == '*') goto yya194; + goto yya185; +yya193: + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'E') goto yya196; + goto yya185; +yya194: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +yya196: + yych = *++YYCURSOR; + if (yych == 'A') goto yya198; +yya197: + YYCURSOR = YYMARKER; + goto yya185; +yya198: + yych = *++YYCURSOR; + if (yych != 'D') goto yya197; + yych = *++YYCURSOR; + if (yych != 'E') goto yya197; + yych = *++YYCURSOR; + if (yych != 'R') goto yya197; + yych = *++YYCURSOR; + if (yych != ';') goto yya197; + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_HEADER); continue; } +} + + } + PUSH_TERMINAL(p->stack, lpop(in, T_HEADER)); + + /* section callback */ + if (act->header_start_cb) + act->header_start_cb(p, bsp, act->userdata); + + /* mandatory headers */ + p21_header_entity(p, act); + p21_header_entity(p, act); + p21_header_entity(p, act); + + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7); + yych = *YYCURSOR; + if (yych <= '/') { + if (yych <= '\r') { + if (yych == '\n') goto yyb208; + if (yych >= '\r') goto yyb210; + } else { + if (yych <= ' ') { + if (yych >= ' ') goto yyb211; + } else { + if (yych <= '!') goto yyb214; + if (yych >= '/') goto yyb215; + } + } + } else { + if (yych <= 'Z') { + if (yych <= '@') goto yyb206; + if (yych == 'E') goto yyb219; + goto yyb216; + } else { + if (yych <= '_') { + if (yych >= '_') goto yyb216; + } else { + if (yych <= '`') goto yyb206; + if (yych <= 'z') goto yyb216; + } + } + } +yyb206: + ++YYCURSOR; +yyb207: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yyb208: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yyb210: + yych = *++YYCURSOR; + if (yych == '\n') goto yyb208; + goto yyb207; +yyb211: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yyb211; + { n = in->cur - in->sp; } + { continue; } +yyb214: + yych = *++YYCURSOR; + if (yych <= '^') { + if (yych <= '@') goto yyb207; + if (yych <= 'Z') goto yyb216; + goto yyb207; + } else { + if (yych == '`') goto yyb207; + if (yych <= 'z') goto yyb216; + goto yyb207; + } +yyb215: + yych = *++YYCURSOR; + if (yych == '*') goto yyb220; + goto yyb207; +yyb216: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yyb217: + if (yych <= 'Z') { + if (yych <= '/') goto yyb218; + if (yych <= '9') goto yyb216; + if (yych >= 'A') goto yyb216; + } else { + if (yych <= '_') { + if (yych >= '_') goto yyb216; + } else { + if (yych <= '`') goto yyb218; + if (yych <= 'z') goto yyb216; + } + } +yyb218: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_KEYWORD); continue; } +yyb219: + yych = *++YYCURSOR; + if (yych == 'N') goto yyb222; + goto yyb217; +yyb220: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +yyb222: + yych = *++YYCURSOR; + if (yych != 'D') goto yyb217; + yych = *++YYCURSOR; + if (yych != 'S') goto yyb217; + yych = *++YYCURSOR; + if (yych != 'E') goto yyb217; + yych = *++YYCURSOR; + if (yych != 'C') goto yyb217; + yych = *++YYCURSOR; + if (yych != ';') goto yyb217; + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_ENDSEC); continue; } +} + + } + + /* optional headers */ + if (LOOKAHEAD(in->sym[0], T_KEYWORD)) + p21_header_entity_list(p, act); + + PUSH_TERMINAL(p->stack, lpop(in, T_ENDSEC)); + + if (p->error) + goto err; + + /* default reduction */ + p->stack->items[bsp] = (Symbol){P_HEADERSECTION}; + drop(p->stack, p->stack->idx_top - bsp - 1); + + return; + +err: + report_error(p, "header_section << 2 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_HEADERSECTION); + else default_error_handler(p, bsp, P_HEADERSECTION); + recover(in, T_DATA); +} + +void p21_data_section_list(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + uint32_t len = 0; + Input *in = p->in; + + do { + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 17) YYFILL(17); + yych = *YYCURSOR; + if (yych <= ' ') { + if (yych <= '\f') { + if (yych == '\n') goto yy233; + } else { + if (yych <= '\r') goto yy235; + if (yych >= ' ') goto yy236; + } + } else { + if (yych <= 'C') { + if (yych == '/') goto yy239; + } else { + if (yych <= 'D') goto yy240; + if (yych <= 'E') goto yy241; + } + } + ++YYCURSOR; +yy232: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy233: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy235: + yych = *++YYCURSOR; + if (yych == '\n') goto yy233; + goto yy232; +yy236: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy236; + { n = in->cur - in->sp; } + { continue; } +yy239: + yych = *++YYCURSOR; + if (yych == '*') goto yy242; + goto yy232; +yy240: + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'A') goto yy244; + goto yy232; +yy241: + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'N') goto yy246; + goto yy232; +yy242: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +yy244: + yych = *++YYCURSOR; + if (yych == 'T') goto yy247; +yy245: + YYCURSOR = YYMARKER; + goto yy232; +yy246: + yych = *++YYCURSOR; + if (yych == 'D') goto yy248; + goto yy245; +yy247: + yych = *++YYCURSOR; + if (yych == 'A') goto yy249; + goto yy245; +yy248: + yych = *++YYCURSOR; + if (yych == '-') goto yy250; + goto yy245; +yy249: + yych = *++YYCURSOR; + if (yych <= ')') { + if (yych == ' ') goto yy251; + if (yych <= '\'') goto yy245; + goto yy251; + } else { + if (yych <= '/') { + if (yych <= '.') goto yy245; + goto yy251; + } else { + if (yych == ';') goto yy251; + goto yy245; + } + } +yy250: + yych = *++YYCURSOR; + if (yych == 'I') goto yy253; + goto yy245; +yy251: + ++YYCURSOR; + YYCURSOR -= 1; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_DATA); continue; } +yy253: + yych = *++YYCURSOR; + if (yych != 'S') goto yy245; + yych = *++YYCURSOR; + if (yych != 'O') goto yy245; + yych = *++YYCURSOR; + if (yych != '-') goto yy245; + yych = *++YYCURSOR; + if (yych != '1') goto yy245; + yych = *++YYCURSOR; + if (yych != '0') goto yy245; + yych = *++YYCURSOR; + if (yych != '3') goto yy245; + yych = *++YYCURSOR; + if (yych != '0') goto yy245; + yych = *++YYCURSOR; + if (yych != '3') goto yy245; + yych = *++YYCURSOR; + if (yych != '-') goto yy245; + yych = *++YYCURSOR; + if (yych != '2') goto yy245; + yych = *++YYCURSOR; + if (yych != '1') goto yy245; + yych = *++YYCURSOR; + if (yych != ';') goto yy245; + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_P21_END); continue; } +} + + } + if (!LOOKAHEAD(in->sym[0], T_DATA)) + break; + p21_data_section(p, act); + } while (++len); + + /* one or more */ + if (!len) { + push(p->stack, (Symbol){T_ERROR, T_DATA, 0, in->sym[0].lineno}); + p->error = true; + } + + if(p->error) + goto err; + + /* user action */ + if (act->data_section_list_cb) + act->data_section_list_cb(p, bsp, act->userdata); + + /* default reduction */ + p->stack->items[bsp] = (Symbol){P_LIST}; + drop(p->stack, p->stack->idx_top - bsp - 1); + + return; + +err: + report_error(p, "data_section_list << 3 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, T_P21_END); +} + +void p21_data_section(P21Parser *p, P21ParserActions *act) { + size_t n, cxt; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + while (in->nsym < 2) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= ' ') { + if (yych <= '\f') { + if (yych == '\n') goto yya271; + } else { + if (yych <= '\r') goto yya273; + if (yych >= ' ') goto yya274; + } + } else { + if (yych <= '.') { + if (yych == '(') goto yya277; + } else { + if (yych <= '/') goto yya279; + if (yych == ';') goto yya277; + } + } + ++YYCURSOR; +yya270: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yya271: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yya273: + yych = *++YYCURSOR; + if (yych == '\n') goto yya271; + goto yya270; +yya274: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yya274; + { n = in->cur - in->sp; } + { continue; } +yya277: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(*in->sp); continue; } +yya279: + yych = *++YYCURSOR; + if (yych != '*') goto yya270; + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + PUSH_TERMINAL(p->stack, lpop(in, T_DATA)); + + if (LOOKAHEAD(in->sym[0], '(')) { + PUSH_TERMINAL(p->stack, lpop(in, '(')); + + p21_parameter_list(p, act); + while (in->nsym < 2) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= 0x001F) { + if (yych <= '\n') { + if (yych >= '\n') goto yyb286; + } else { + if (yych == '\r') goto yyb288; + } + } else { + if (yych <= '/') { + if (yych <= ' ') goto yyb289; + if (yych >= '/') goto yyb292; + } else { + if (yych == ';') goto yyb293; + } + } + ++YYCURSOR; +yyb285: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yyb286: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yyb288: + yych = *++YYCURSOR; + if (yych == '\n') goto yyb286; + goto yyb285; +yyb289: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yyb289; + { n = in->cur - in->sp; } + { continue; } +yyb292: + yych = *++YYCURSOR; + if (yych == '*') goto yyb295; + goto yyb285; +yyb293: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(';'); continue; } +yyb295: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + + PUSH_TERMINAL(p->stack, lpop(in, ')')); + } + PUSH_TERMINAL(p->stack, lpop(in, ';')); + + if (act->data_start_cb) + act->data_start_cb(p, bsp, act->userdata); + + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7); + yych = *YYCURSOR; + if (yych <= ' ') { + if (yych <= '\f') { + if (yych == '\n') goto yyc301; + } else { + if (yych <= '\r') goto yyc303; + if (yych >= ' ') goto yyc304; + } + } else { + if (yych <= '.') { + if (yych == '#') goto yyc307; + } else { + if (yych <= '/') goto yyc308; + if (yych == 'E') goto yyc309; + } + } + ++YYCURSOR; +yyc300: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yyc301: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yyc303: + yych = *++YYCURSOR; + if (yych == '\n') goto yyc301; + goto yyc300; +yyc304: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yyc304; + { n = in->cur - in->sp; } + { continue; } +yyc307: + yych = *++YYCURSOR; + if (yych <= '/') goto yyc300; + if (yych <= '9') goto yyc310; + goto yyc300; +yyc308: + yych = *++YYCURSOR; + if (yych == '*') goto yyc313; + goto yyc300; +yyc309: + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'N') goto yyc315; + goto yyc300; +yyc310: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yyc312; + if (yych <= '9') goto yyc310; +yyc312: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_EID); continue; } +yyc313: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +yyc315: + yych = *++YYCURSOR; + if (yych == 'D') goto yyc317; +yyc316: + YYCURSOR = YYMARKER; + goto yyc300; +yyc317: + yych = *++YYCURSOR; + if (yych != 'S') goto yyc316; + yych = *++YYCURSOR; + if (yych != 'E') goto yyc316; + yych = *++YYCURSOR; + if (yych != 'C') goto yyc316; + yych = *++YYCURSOR; + if (yych != ';') goto yyc316; + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_ENDSEC); continue; } +} + + } + if (LOOKAHEAD(in->sym[0], T_EID)) + p21_entity_instance_list(p, act); + + PUSH_TERMINAL(p->stack, lpop(in, T_ENDSEC)); + + if (p->error) + goto err; + + /* default reduction */ + p->stack->items[bsp] = (Symbol){P_DATASECTION}; + drop(p->stack, p->stack->idx_top - bsp - 1); + + return; + +err: + report_error(p, "data_section << 4 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_DATASECTION); + else default_error_handler(p, bsp, P_DATASECTION); + recover(in, T_P21_END, T_DATA); +} + +void p21_header_entity(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + /* set KEYWORD as basemrk to prevent fill() recycling the buffer before user action */ + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= '.') { + if (yych <= '\r') { + if (yych == '\n') goto yy327; + if (yych >= '\r') goto yy329; + } else { + if (yych <= 0x001F) goto yy325; + if (yych <= ' ') goto yy330; + if (yych <= '!') goto yy333; + } + } else { + if (yych <= '^') { + if (yych <= '/') goto yy334; + if (yych <= '@') goto yy325; + if (yych <= 'Z') goto yy335; + } else { + if (yych == '`') goto yy325; + if (yych <= 'z') goto yy335; + } + } +yy325: + ++YYCURSOR; +yy326: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy327: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy329: + yych = *++YYCURSOR; + if (yych == '\n') goto yy327; + goto yy326; +yy330: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy330; + { n = in->cur - in->sp; } + { continue; } +yy333: + yych = *++YYCURSOR; + if (yych <= '^') { + if (yych <= '@') goto yy326; + if (yych <= 'Z') goto yy335; + goto yy326; + } else { + if (yych == '`') goto yy326; + if (yych <= 'z') goto yy335; + goto yy326; + } +yy334: + yych = *++YYCURSOR; + if (yych == '*') goto yy338; + goto yy326; +yy335: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 'Z') { + if (yych <= '/') goto yy337; + if (yych <= '9') goto yy335; + if (yych >= 'A') goto yy335; + } else { + if (yych <= '_') { + if (yych >= '_') goto yy335; + } else { + if (yych <= '`') goto yy337; + if (yych <= 'z') goto yy335; + } + } +yy337: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_KEYWORD); continue; } +yy338: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + + /* set KEYWORD as basemrk to prevent fill() recycling the buffer before user action */ + assert(in->nsym == 1); + in->basemrk += in->sym[0].offset; + in->sym[0].offset = 0; + + p21_simple_record(p, act); + + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= 0x001F) { + if (yych <= '\n') { + if (yych >= '\n') goto yy344; + } else { + if (yych == '\r') goto yy346; + } + } else { + if (yych <= '/') { + if (yych <= ' ') goto yy347; + if (yych >= '/') goto yy350; + } else { + if (yych == ';') goto yy351; + } + } + ++YYCURSOR; +yy343: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy344: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy346: + yych = *++YYCURSOR; + if (yych == '\n') goto yy344; + goto yy343; +yy347: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy347; + { n = in->cur - in->sp; } + { continue; } +yy350: + yych = *++YYCURSOR; + if (yych == '*') goto yy353; + goto yy343; +yy351: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(';'); continue; } +yy353: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + PUSH_TERMINAL(p->stack, lpop(in, ';')); + + if (p->error) + goto err; + + /* user action */ + if (act->header_entity_cb) + act->header_entity_cb(p, bsp, act->userdata); + + /* reduction */ + assert(!p->hold); + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_HEADERENTITY}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "header_entity << 5 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_HEADERENTITY); + else default_error_handler(p, bsp, P_HEADERENTITY); + recover(in, T_ENDSEC, T_KEYWORD); +} + +void p21_header_entity_list(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + p21_header_entity(p, act); + + do { + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7); + yych = *YYCURSOR; + if (yych <= '/') { + if (yych <= '\r') { + if (yych == '\n') goto yy359; + if (yych >= '\r') goto yy361; + } else { + if (yych <= ' ') { + if (yych >= ' ') goto yy362; + } else { + if (yych <= '!') goto yy365; + if (yych >= '/') goto yy366; + } + } + } else { + if (yych <= 'Z') { + if (yych <= '@') goto yy357; + if (yych == 'E') goto yy370; + goto yy367; + } else { + if (yych <= '_') { + if (yych >= '_') goto yy367; + } else { + if (yych <= '`') goto yy357; + if (yych <= 'z') goto yy367; + } + } + } +yy357: + ++YYCURSOR; +yy358: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy359: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy361: + yych = *++YYCURSOR; + if (yych == '\n') goto yy359; + goto yy358; +yy362: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy362; + { n = in->cur - in->sp; } + { continue; } +yy365: + yych = *++YYCURSOR; + if (yych <= '^') { + if (yych <= '@') goto yy358; + if (yych <= 'Z') goto yy367; + goto yy358; + } else { + if (yych == '`') goto yy358; + if (yych <= 'z') goto yy367; + goto yy358; + } +yy366: + yych = *++YYCURSOR; + if (yych == '*') goto yy371; + goto yy358; +yy367: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy368: + if (yych <= 'Z') { + if (yych <= '/') goto yy369; + if (yych <= '9') goto yy367; + if (yych >= 'A') goto yy367; + } else { + if (yych <= '_') { + if (yych >= '_') goto yy367; + } else { + if (yych <= '`') goto yy369; + if (yych <= 'z') goto yy367; + } + } +yy369: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_KEYWORD); continue; } +yy370: + yych = *++YYCURSOR; + if (yych == 'N') goto yy373; + goto yy368; +yy371: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +yy373: + yych = *++YYCURSOR; + if (yych != 'D') goto yy368; + yych = *++YYCURSOR; + if (yych != 'S') goto yy368; + yych = *++YYCURSOR; + if (yych != 'E') goto yy368; + yych = *++YYCURSOR; + if (yych != 'C') goto yy368; + yych = *++YYCURSOR; + if (yych != ';') goto yy368; + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_ENDSEC); continue; } +} + + } + if (!LOOKAHEAD(in->sym[0], T_KEYWORD)) + break; + p21_header_entity(p, act); + } while (1); + + if (p->error) + goto err; + + + /* user action */ + if (act->header_entity_list_cb) + act->header_entity_list_cb(p, bsp, act->userdata); + + /* reduction */ + assert(!p->hold); + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_LIST}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "header_entity_list << 6 >>"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, T_ENDSEC); +} + +void p21_entity_instance_list(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + p21_entity_instance(p, act); + + do { + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7); + yych = *YYCURSOR; + if (yych <= ' ') { + if (yych <= '\f') { + if (yych == '\n') goto yy384; + } else { + if (yych <= '\r') goto yy386; + if (yych >= ' ') goto yy387; + } + } else { + if (yych <= '.') { + if (yych == '#') goto yy390; + } else { + if (yych <= '/') goto yy391; + if (yych == 'E') goto yy392; + } + } + ++YYCURSOR; +yy383: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy384: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy386: + yych = *++YYCURSOR; + if (yych == '\n') goto yy384; + goto yy383; +yy387: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy387; + { n = in->cur - in->sp; } + { continue; } +yy390: + yych = *++YYCURSOR; + if (yych <= '/') goto yy383; + if (yych <= '9') goto yy393; + goto yy383; +yy391: + yych = *++YYCURSOR; + if (yych == '*') goto yy396; + goto yy383; +yy392: + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'N') goto yy398; + goto yy383; +yy393: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy395; + if (yych <= '9') goto yy393; +yy395: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_EID); continue; } +yy396: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +yy398: + yych = *++YYCURSOR; + if (yych == 'D') goto yy400; +yy399: + YYCURSOR = YYMARKER; + goto yy383; +yy400: + yych = *++YYCURSOR; + if (yych != 'S') goto yy399; + yych = *++YYCURSOR; + if (yych != 'E') goto yy399; + yych = *++YYCURSOR; + if (yych != 'C') goto yy399; + yych = *++YYCURSOR; + if (yych != ';') goto yy399; + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_ENDSEC); continue; } +} + + } + if (!LOOKAHEAD(in->sym[0], T_EID)) + break; + p21_entity_instance(p, act); + } while (1); + + if (p->error) + goto err; + + /* user action */ + if (act->entity_instance_list_cb) + act->entity_instance_list_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_LIST}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "entity_instance_list << 7 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, T_ENDSEC); +} + +void p21_parameter_list(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + p21_parameter(p, act); + + do { + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= ' ') { + if (yych <= '\f') { + if (yych == '\n') goto yy410; + } else { + if (yych <= '\r') goto yy412; + if (yych >= ' ') goto yy413; + } + } else { + if (yych <= '+') { + if (yych == ')') goto yy416; + } else { + if (yych <= ',') goto yy416; + if (yych == '/') goto yy418; + } + } + ++YYCURSOR; +yy409: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy410: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy412: + yych = *++YYCURSOR; + if (yych == '\n') goto yy410; + goto yy409; +yy413: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy413; + { n = in->cur - in->sp; } + { continue; } +yy416: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(*in->sp); continue; } +yy418: + yych = *++YYCURSOR; + if (yych != '*') goto yy409; + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + if (LOOKAHEAD(in->sym[0], ')')) + break; + + PUSH_TERMINAL(p->stack, lpop(in, ',')); + p21_parameter(p, act); + } while (1); + + if (p->error) + goto err; + + /* user action */ + if (act->parameter_list_cb) + act->parameter_list_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_LIST}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "parameter_list << 8 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, ')', ';'); +} + +void p21_entity_instance(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + /* set EID as basemrk to prevent fill() recycling the buffer before user action */ + assert(in->nsym == 1); + in->basemrk += in->sym[0].offset; + in->sym[0].offset = 0; + + while (in->nsym < 3) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= '.') { + if (yych <= 0x001F) { + if (yych <= '\n') { + if (yych >= '\n') goto yy425; + } else { + if (yych == '\r') goto yy427; + } + } else { + if (yych <= '!') { + if (yych <= ' ') goto yy428; + goto yy431; + } else { + if (yych == '(') goto yy432; + } + } + } else { + if (yych <= 'Z') { + if (yych <= '<') { + if (yych <= '/') goto yy434; + } else { + if (yych <= '=') goto yy432; + if (yych >= 'A') goto yy435; + } + } else { + if (yych <= '_') { + if (yych >= '_') goto yy435; + } else { + if (yych <= '`') goto yy423; + if (yych <= 'z') goto yy435; + } + } + } +yy423: + ++YYCURSOR; +yy424: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy425: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy427: + yych = *++YYCURSOR; + if (yych == '\n') goto yy425; + goto yy424; +yy428: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy428; + { n = in->cur - in->sp; } + { continue; } +yy431: + yych = *++YYCURSOR; + if (yych <= '^') { + if (yych <= '@') goto yy424; + if (yych <= 'Z') goto yy435; + goto yy424; + } else { + if (yych == '`') goto yy424; + if (yych <= 'z') goto yy435; + goto yy424; + } +yy432: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(*in->sp); continue; } +yy434: + yych = *++YYCURSOR; + if (yych == '*') goto yy438; + goto yy424; +yy435: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 'Z') { + if (yych <= '/') goto yy437; + if (yych <= '9') goto yy435; + if (yych >= 'A') goto yy435; + } else { + if (yych <= '_') { + if (yych >= '_') goto yy435; + } else { + if (yych <= '`') goto yy437; + if (yych <= 'z') goto yy435; + } + } +yy437: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_KEYWORD); continue; } +yy438: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + if (!LOOKAHEAD(in->sym[0], T_EID) || !LOOKAHEAD(in->sym[1], '=')) + goto err; + + if (LOOKAHEAD(in->sym[2], T_KEYWORD)) { + p21_simple_entity_instance(p, act); + } else if (LOOKAHEAD(in->sym[2], '(')) { + p21_complex_entity_instance(p, act); + } + + if (p->error) + goto err; + + /* user action */ + if (act->entity_instance_cb) + act->entity_instance_cb(p, bsp, act->userdata); + + /* no default reduction */ + + return; + +err: + report_error(p, "entity_instance << 9 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, T_ENDSEC, T_EID); +} + +void p21_simple_entity_instance(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + PUSH_TERMINAL(p->stack, lpop(in, T_EID)); + PUSH_TERMINAL(p->stack, lpop(in, '=')); + + p21_simple_record(p, act); + + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= 0x001F) { + if (yych <= '\n') { + if (yych >= '\n') goto yy444; + } else { + if (yych == '\r') goto yy446; + } + } else { + if (yych <= '/') { + if (yych <= ' ') goto yy447; + if (yych >= '/') goto yy450; + } else { + if (yych == ';') goto yy451; + } + } + ++YYCURSOR; +yy443: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy444: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy446: + yych = *++YYCURSOR; + if (yych == '\n') goto yy444; + goto yy443; +yy447: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy447; + { n = in->cur - in->sp; } + { continue; } +yy450: + yych = *++YYCURSOR; + if (yych == '*') goto yy453; + goto yy443; +yy451: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(';'); continue; } +yy453: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + PUSH_TERMINAL(p->stack, lpop(in, ';')); + + if (p->error) + goto err; + + /* user action */ + if (act->simple_entity_instance_cb) + act->simple_entity_instance_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_SIMPLEENTITY}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "simple_entity_instance << 10 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_SIMPLEENTITY); + else default_error_handler(p, bsp, P_SIMPLEENTITY); + recover(in, T_ENDSEC, T_EID); +} + + +void p21_complex_entity_instance(P21Parser *p, P21ParserActions *act) { + size_t n, c; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + PUSH_TERMINAL(p->stack, lpop(in, T_EID)); + PUSH_TERMINAL(p->stack, lpop(in, '=')); + PUSH_TERMINAL_EXT(c, p->stack, lpop(in, '(')); + + p21_simple_record_list(p, act); + + while (in->nsym < 2) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= 0x001F) { + if (yych <= '\n') { + if (yych >= '\n') goto yy459; + } else { + if (yych == '\r') goto yy461; + } + } else { + if (yych <= '/') { + if (yych <= ' ') goto yy462; + if (yych >= '/') goto yy465; + } else { + if (yych == ';') goto yy466; + } + } + ++YYCURSOR; +yy458: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy459: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy461: + yych = *++YYCURSOR; + if (yych == '\n') goto yy459; + goto yy458; +yy462: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy462; + { n = in->cur - in->sp; } + { continue; } +yy465: + yych = *++YYCURSOR; + if (yych == '*') goto yy468; + goto yy458; +yy466: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(';'); continue; } +yy468: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + + PUSH_TERMINAL_EXT(c, p->stack, lpop(in, ')')); + PUSH_TERMINAL(p->stack, lpop(in, ';')); + + if (p->error) + goto err; + + /* user action */ + if (act->complex_entity_instance_cb) + act->complex_entity_instance_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_COMPLEXENTITY}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "complex_entity_instance << 11 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_COMPLEXENTITY); + else default_error_handler(p, bsp, P_COMPLEXENTITY); + recover(in, T_ENDSEC, T_EID); +} + +void p21_simple_record(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + while (in->nsym < 3) { + in->sp = in->cur; + +{ + YYCTYPE yych; + unsigned int yyaccept = 0; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= ')') { + if (yych <= ' ') { + if (yych <= '\f') { + if (yych == '\n') goto yy474; + } else { + if (yych <= '\r') goto yy476; + if (yych >= ' ') goto yy477; + } + } else { + if (yych <= '#') { + if (yych <= '!') goto yy480; + if (yych <= '"') goto yy481; + goto yy482; + } else { + if (yych <= '$') goto yy483; + if (yych <= '&') goto yy472; + if (yych <= '\'') goto yy485; + goto yy486; + } + } + } else { + if (yych <= '9') { + if (yych <= ',') { + if (yych <= '*') goto yy488; + if (yych <= '+') goto yy490; + } else { + if (yych <= '-') goto yy490; + if (yych <= '.') goto yy491; + if (yych <= '/') goto yy492; + goto yy493; + } + } else { + if (yych <= '^') { + if (yych <= '@') goto yy472; + if (yych <= 'Z') goto yy496; + } else { + if (yych == '`') goto yy472; + if (yych <= 'z') goto yy496; + } + } + } +yy472: + ++YYCURSOR; +yy473: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy474: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy476: + yych = *++YYCURSOR; + if (yych == '\n') goto yy474; + goto yy473; +yy477: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy477; + { n = in->cur - in->sp; } + { continue; } +yy480: + yych = *++YYCURSOR; + if (yych <= '^') { + if (yych <= '@') goto yy473; + if (yych <= 'Z') goto yy496; + goto yy473; + } else { + if (yych == '`') goto yy473; + if (yych <= 'z') goto yy496; + goto yy473; + } +yy481: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '/') goto yy473; + if (yych <= '3') goto yy499; + goto yy473; +yy482: + yych = *++YYCURSOR; + if (yych <= '/') goto yy473; + if (yych <= '9') goto yy502; + goto yy473; +yy483: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_EMPTY); continue; } +yy485: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '[') { + if (yych <= 0x001F) goto yy473; + if (yych <= 'Z') goto yy506; + goto yy473; + } else { + if (yych == ']') goto yy473; + if (yych <= '~') goto yy506; + goto yy473; + } +yy486: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(*in->sp); continue; } +yy488: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_DERIVED); continue; } +yy490: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= ',') { + if (yych == '+') goto yy510; + goto yy473; + } else { + if (yych <= '-') goto yy510; + if (yych <= '/') goto yy473; + if (yych <= '9') goto yy493; + goto yy473; + } +yy491: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '@') goto yy473; + if (yych <= 'Z') goto yy512; + if (yych == '_') goto yy512; + goto yy473; +yy492: + yych = *++YYCURSOR; + if (yych == '*') goto yy514; + goto yy473; +yy493: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '.') goto yy516; + if (yych <= '/') goto yy495; + if (yych <= '9') goto yy493; +yy495: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_INTEGER); continue; } +yy496: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 'Z') { + if (yych <= '/') goto yy498; + if (yych <= '9') goto yy496; + if (yych >= 'A') goto yy496; + } else { + if (yych <= '_') { + if (yych >= '_') goto yy496; + } else { + if (yych <= '`') goto yy498; + if (yych <= 'z') goto yy496; + } + } +yy498: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_KEYWORD); continue; } +yy499: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') { + if (yych == '"') goto yy519; + } else { + if (yych <= '9') goto yy499; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy499; + } +yy501: + YYCURSOR = YYMARKER; + if (yyaccept <= 1) { + if (yyaccept == 0) { + goto yy473; + } else { + goto yy508; + } + } else { + goto yy518; + } +yy502: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy504; + if (yych <= '9') goto yy502; +yy504: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_EID); continue; } +yy505: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yy506: + if (yych <= 'Z') { + if (yych <= 0x001F) goto yy501; + if (yych != '\'') goto yy505; + } else { + if (yych <= '\\') { + if (yych <= '[') goto yy501; + goto yy509; + } else { + if (yych <= ']') goto yy501; + if (yych <= '~') goto yy505; + goto yy501; + } + } + yyaccept = 1; + YYMARKER = ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\'') goto yy505; +yy508: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_STRING); continue; } +yy509: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 'S') { + if (yych <= '@') goto yy501; + if (yych <= 'I') goto yy521; + if (yych <= 'R') goto yy501; + goto yy522; + } else { + if (yych <= 'X') { + if (yych <= 'W') goto yy501; + goto yy523; + } else { + if (yych == '\\') goto yy505; + goto yy501; + } + } +yy510: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= ',') { + if (yych == '+') goto yy510; + goto yy501; + } else { + if (yych <= '-') goto yy510; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy493; + goto yy501; + } +yy512: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '9') { + if (yych == '.') goto yy524; + if (yych <= '/') goto yy501; + goto yy512; + } else { + if (yych <= 'Z') { + if (yych <= '@') goto yy501; + goto yy512; + } else { + if (yych == '_') goto yy512; + goto yy501; + } + } +yy514: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +yy516: + yyaccept = 2; + YYMARKER = ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy518; + if (yych <= '9') goto yy516; + if (yych == 'E') goto yy526; +yy518: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_REAL); continue; } +yy519: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_BINARY); continue; } +yy521: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yy505; + goto yy501; +yy522: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yy528; + goto yy501; +yy523: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '3') { + if (yych == '2') goto yy529; + goto yy501; + } else { + if (yych <= '4') goto yy530; + if (yych == '\\') goto yy531; + goto yy501; + } +yy524: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_ENUMERATION); continue; } +yy526: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= ',') { + if (yych == '+') goto yy526; + goto yy501; + } else { + if (yych <= '-') goto yy526; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy532; + goto yy501; + } +yy528: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '[') { + if (yych <= 0x001F) goto yy501; + if (yych <= 'Z') goto yy505; + goto yy501; + } else { + if (yych == ']') goto yy501; + if (yych <= '~') goto yy505; + goto yy501; + } +yy529: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yy534; + goto yy501; +yy530: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yy535; + goto yy501; +yy531: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy536; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy536; + goto yy501; +yy532: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy518; + if (yych <= '9') goto yy532; + goto yy518; +yy534: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy537; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy537; + goto yy501; +yy535: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy538; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy538; + goto yy501; +yy536: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy505; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy505; + goto yy501; +yy537: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy539; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy539; + goto yy501; +yy538: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy540; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy540; + goto yy501; +yy539: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy541; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy541; + goto yy501; +yy540: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy542; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy542; + goto yy501; +yy541: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy543; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy543; + goto yy501; +yy542: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy544; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy544; + goto yy501; +yy543: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '@') { + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy537; + goto yy501; + } else { + if (yych <= 'F') goto yy537; + if (yych == '\\') goto yy545; + goto yy501; + } +yy544: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy546; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy546; + goto yy501; +yy545: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == 'X') goto yy547; + goto yy501; +yy546: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy548; + if (yych <= '@') goto yy501; + if (yych <= 'F') goto yy548; + goto yy501; +yy547: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '0') goto yy521; + goto yy501; +yy548: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy549; + if (yych <= '@') goto yy501; + if (yych >= 'G') goto yy501; +yy549: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy550; + if (yych <= '@') goto yy501; + if (yych >= 'G') goto yy501; +yy550: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '@') { + if (yych <= '/') goto yy501; + if (yych <= '9') goto yy538; + goto yy501; + } else { + if (yych <= 'F') goto yy538; + if (yych == '\\') goto yy545; + goto yy501; + } +} + + } + + PUSH_TERMINAL(p->stack, lpop(in, T_KEYWORD)); + PUSH_TERMINAL_EXT(n, p->stack, lpop(in, '(')); + + if (LOOKAHEAD(in->sym[0], '(', T_KEYWORD, T_VARIANT)) + p21_parameter_list(p, act); + + PUSH_TERMINAL_EXT(n, p->stack, lpop(in, ')')); + + if (p->error) + goto err; + + /* user action */ + if (act->simple_record_cb) + act->simple_record_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_SIMPLERECORD}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "simple_record << 12 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_SIMPLERECORD); + else default_error_handler(p, bsp, P_SIMPLERECORD); + recover(in, ';', ')', T_KEYWORD); +} + +void p21_simple_record_list(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + p21_simple_record(p, act); + + do { + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= ')') { + if (yych <= '\r') { + if (yych == '\n') goto yy555; + if (yych >= '\r') goto yy557; + } else { + if (yych <= ' ') { + if (yych >= ' ') goto yy558; + } else { + if (yych <= '!') goto yy561; + if (yych >= ')') goto yy562; + } + } + } else { + if (yych <= 'Z') { + if (yych == '/') goto yy564; + if (yych >= 'A') goto yy565; + } else { + if (yych <= '_') { + if (yych >= '_') goto yy565; + } else { + if (yych <= '`') goto yy553; + if (yych <= 'z') goto yy565; + } + } + } +yy553: + ++YYCURSOR; +yy554: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yy555: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yy557: + yych = *++YYCURSOR; + if (yych == '\n') goto yy555; + goto yy554; +yy558: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yy558; + { n = in->cur - in->sp; } + { continue; } +yy561: + yych = *++YYCURSOR; + if (yych <= '^') { + if (yych <= '@') goto yy554; + if (yych <= 'Z') goto yy565; + goto yy554; + } else { + if (yych == '`') goto yy554; + if (yych <= 'z') goto yy565; + goto yy554; + } +yy562: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(')'); continue; } +yy564: + yych = *++YYCURSOR; + if (yych == '*') goto yy568; + goto yy554; +yy565: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 'Z') { + if (yych <= '/') goto yy567; + if (yych <= '9') goto yy565; + if (yych >= 'A') goto yy565; + } else { + if (yych <= '_') { + if (yych >= '_') goto yy565; + } else { + if (yych <= '`') goto yy567; + if (yych <= 'z') goto yy565; + } + } +yy567: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_KEYWORD); continue; } +yy568: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + if (!LOOKAHEAD(in->sym[0], T_KEYWORD)) + break; + p21_simple_record(p, act); + } while (1); + + if (p->error) + goto err; + + /* user action */ + if (act->simple_record_list_cb) + act->simple_record_list_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_LIST}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "simple_record_list << 13 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, ')', ';'); +} + +void p21_parameter(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + while (in->nsym < 2) { + in->sp = in->cur; + +{ + YYCTYPE yych; + unsigned int yyaccept = 0; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= ')') { + if (yych <= ' ') { + if (yych <= '\f') { + if (yych == '\n') goto yya574; + } else { + if (yych <= '\r') goto yya576; + if (yych >= ' ') goto yya577; + } + } else { + if (yych <= '#') { + if (yych <= '!') goto yya580; + if (yych <= '"') goto yya581; + goto yya582; + } else { + if (yych <= '$') goto yya583; + if (yych <= '&') goto yya572; + if (yych <= '\'') goto yya585; + goto yya586; + } + } + } else { + if (yych <= '9') { + if (yych <= ',') { + if (yych <= '*') goto yya588; + if (yych <= '+') goto yya590; + goto yya586; + } else { + if (yych <= '-') goto yya590; + if (yych <= '.') goto yya591; + if (yych <= '/') goto yya592; + goto yya593; + } + } else { + if (yych <= '^') { + if (yych <= '@') goto yya572; + if (yych <= 'Z') goto yya596; + } else { + if (yych == '`') goto yya572; + if (yych <= 'z') goto yya596; + } + } + } +yya572: + ++YYCURSOR; +yya573: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yya574: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yya576: + yych = *++YYCURSOR; + if (yych == '\n') goto yya574; + goto yya573; +yya577: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yya577; + { n = in->cur - in->sp; } + { continue; } +yya580: + yych = *++YYCURSOR; + if (yych <= '^') { + if (yych <= '@') goto yya573; + if (yych <= 'Z') goto yya596; + goto yya573; + } else { + if (yych == '`') goto yya573; + if (yych <= 'z') goto yya596; + goto yya573; + } +yya581: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '/') goto yya573; + if (yych <= '3') goto yya599; + goto yya573; +yya582: + yych = *++YYCURSOR; + if (yych <= '/') goto yya573; + if (yych <= '9') goto yya602; + goto yya573; +yya583: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_EMPTY); continue; } +yya585: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '[') { + if (yych <= 0x001F) goto yya573; + if (yych <= 'Z') goto yya606; + goto yya573; + } else { + if (yych == ']') goto yya573; + if (yych <= '~') goto yya606; + goto yya573; + } +yya586: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(*in->sp); continue; } +yya588: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_DERIVED); continue; } +yya590: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= ',') { + if (yych == '+') goto yya610; + goto yya573; + } else { + if (yych <= '-') goto yya610; + if (yych <= '/') goto yya573; + if (yych <= '9') goto yya593; + goto yya573; + } +yya591: + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '@') goto yya573; + if (yych <= 'Z') goto yya612; + if (yych == '_') goto yya612; + goto yya573; +yya592: + yych = *++YYCURSOR; + if (yych == '*') goto yya614; + goto yya573; +yya593: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '.') goto yya616; + if (yych <= '/') goto yya595; + if (yych <= '9') goto yya593; +yya595: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_INTEGER); continue; } +yya596: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 'Z') { + if (yych <= '/') goto yya598; + if (yych <= '9') goto yya596; + if (yych >= 'A') goto yya596; + } else { + if (yych <= '_') { + if (yych >= '_') goto yya596; + } else { + if (yych <= '`') goto yya598; + if (yych <= 'z') goto yya596; + } + } +yya598: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_KEYWORD); continue; } +yya599: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') { + if (yych == '"') goto yya619; + } else { + if (yych <= '9') goto yya599; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya599; + } +yya601: + YYCURSOR = YYMARKER; + if (yyaccept <= 1) { + if (yyaccept == 0) { + goto yya573; + } else { + goto yya608; + } + } else { + goto yya618; + } +yya602: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya604; + if (yych <= '9') goto yya602; +yya604: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_EID); continue; } +yya605: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; +yya606: + if (yych <= 'Z') { + if (yych <= 0x001F) goto yya601; + if (yych != '\'') goto yya605; + } else { + if (yych <= '\\') { + if (yych <= '[') goto yya601; + goto yya609; + } else { + if (yych <= ']') goto yya601; + if (yych <= '~') goto yya605; + goto yya601; + } + } + yyaccept = 1; + YYMARKER = ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\'') goto yya605; +yya608: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_STRING); continue; } +yya609: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= 'S') { + if (yych <= '@') goto yya601; + if (yych <= 'I') goto yya621; + if (yych <= 'R') goto yya601; + goto yya622; + } else { + if (yych <= 'X') { + if (yych <= 'W') goto yya601; + goto yya623; + } else { + if (yych == '\\') goto yya605; + goto yya601; + } + } +yya610: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= ',') { + if (yych == '+') goto yya610; + goto yya601; + } else { + if (yych <= '-') goto yya610; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya593; + goto yya601; + } +yya612: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '9') { + if (yych == '.') goto yya624; + if (yych <= '/') goto yya601; + goto yya612; + } else { + if (yych <= 'Z') { + if (yych <= '@') goto yya601; + goto yya612; + } else { + if (yych == '_') goto yya612; + goto yya601; + } + } +yya614: + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +yya616: + yyaccept = 2; + YYMARKER = ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya618; + if (yych <= '9') goto yya616; + if (yych == 'E') goto yya626; +yya618: + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_REAL); continue; } +yya619: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_BINARY); continue; } +yya621: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yya605; + goto yya601; +yya622: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yya628; + goto yya601; +yya623: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '3') { + if (yych == '2') goto yya629; + goto yya601; + } else { + if (yych <= '4') goto yya630; + if (yych == '\\') goto yya631; + goto yya601; + } +yya624: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(T_VARIANT, V_ENUMERATION); continue; } +yya626: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= ',') { + if (yych == '+') goto yya626; + goto yya601; + } else { + if (yych <= '-') goto yya626; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya632; + goto yya601; + } +yya628: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '[') { + if (yych <= 0x001F) goto yya601; + if (yych <= 'Z') goto yya605; + goto yya601; + } else { + if (yych == ']') goto yya601; + if (yych <= '~') goto yya605; + goto yya601; + } +yya629: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yya634; + goto yya601; +yya630: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yya635; + goto yya601; +yya631: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya636; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya636; + goto yya601; +yya632: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya618; + if (yych <= '9') goto yya632; + goto yya618; +yya634: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya637; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya637; + goto yya601; +yya635: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya638; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya638; + goto yya601; +yya636: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya605; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya605; + goto yya601; +yya637: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya639; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya639; + goto yya601; +yya638: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya640; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya640; + goto yya601; +yya639: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya641; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya641; + goto yya601; +yya640: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya642; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya642; + goto yya601; +yya641: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya643; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya643; + goto yya601; +yya642: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya644; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya644; + goto yya601; +yya643: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '@') { + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya637; + goto yya601; + } else { + if (yych <= 'F') goto yya637; + if (yych == '\\') goto yya645; + goto yya601; + } +yya644: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya646; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya646; + goto yya601; +yya645: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == 'X') goto yya647; + goto yya601; +yya646: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya648; + if (yych <= '@') goto yya601; + if (yych <= 'F') goto yya648; + goto yya601; +yya647: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == '0') goto yya621; + goto yya601; +yya648: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya649; + if (yych <= '@') goto yya601; + if (yych >= 'G') goto yya601; +yya649: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya650; + if (yych <= '@') goto yya601; + if (yych >= 'G') goto yya601; +yya650: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych <= '@') { + if (yych <= '/') goto yya601; + if (yych <= '9') goto yya638; + goto yya601; + } else { + if (yych <= 'F') goto yya638; + if (yych == '\\') goto yya645; + goto yya601; + } +} + + } + + if (LOOKAHEAD(in->sym[0], T_VARIANT)) { + PUSH_TERMINAL(p->stack, lpop(in, T_VARIANT)); + } else { + if (LOOKAHEAD(in->sym[0], T_KEYWORD)) { + PUSH_TERMINAL(p->stack, lpop(in, T_KEYWORD)); + PUSH_TERMINAL(p->stack, lpop(in, '(')); + p21_parameter(p, act); + } else { + PUSH_TERMINAL(p->stack, lpop(in, '(')); + if (LOOKAHEAD(in->sym[0], '(', T_KEYWORD, T_VARIANT)) { + p21_parameter_list(p, act); + } + } + while (in->nsym < 1) { + in->sp = in->cur; + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + if (yych <= 0x001F) { + if (yych <= '\n') { + if (yych >= '\n') goto yyb655; + } else { + if (yych == '\r') goto yyb657; + } + } else { + if (yych <= ')') { + if (yych <= ' ') goto yyb658; + if (yych >= ')') goto yyb661; + } else { + if (yych == '/') goto yyb663; + } + } + ++YYCURSOR; +yyb654: + { n = in->cur - in->sp; } + { YYCURSOR--; break; } +yyb655: + ++YYCURSOR; + { n = in->cur - in->sp; } + { in->lineno++; continue; } +yyb657: + yych = *++YYCURSOR; + if (yych == '\n') goto yyb655; + goto yyb654; +yyb658: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + if (yych == ' ') goto yyb658; + { n = in->cur - in->sp; } + { continue; } +yyb661: + ++YYCURSOR; + { n = in->cur - in->sp; } + { PUSH_SYMBOL(')'); continue; } +yyb663: + yych = *++YYCURSOR; + if (yych != '*') goto yyb654; + ++YYCURSOR; + { n = in->cur - in->sp; } + { lex_comment(in); continue; } +} + + } + PUSH_TERMINAL(p->stack, lpop(in, ')')); + } + + if (p->error) + goto err; + + /* user action */ + if (act->parameter_cb) + act->parameter_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_PARAMETER}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "parameter << 14 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_PARAMETER); + else default_error_handler(p, bsp, P_PARAMETER); + recover(in, ')', ',', ';'); +} + +void mock_error(P21Parser *, int, uint8_t); +void mock_ud_init(void *); +void mock_ud_exit(void *); +void mock_exchange_file(P21Parser *, int, void *); +void mock_header_start(P21Parser *, int, void *); +void mock_header_entity_list(P21Parser *, int, void *); +void mock_data_section_list(P21Parser *, int, void *); +void mock_data_start(P21Parser *, int, void *); +void mock_header_entity(P21Parser *, int, void *); +void mock_simple_entity_instance(P21Parser *, int, void *); +void mock_complex_entity_instance(P21Parser *, int, void *); +void mock_parameter_list(P21Parser *, int, void *); +void mock_parameter(P21Parser *, int, void *); +void mock_entity_instance_list(P21Parser *, int, void *); +void mock_entity_instance(P21Parser *, int, void *); +void mock_simple_record_list(P21Parser *, int, void *); +void mock_simple_record(P21Parser *, int, void *); +void mock_noop(P21Parser *, int, void *); + +typedef struct { + sqlite3 *db; + sqlite3_stmt *sec_stmt; + sqlite3_stmt *sei_stmt; + sqlite3_stmt *cei_stmt; + sqlite3_stmt *hei_stmt; + int section_idx; +} P21UserData; + +P21UserData mockdata = {0}; + +P21ParserActions mockact = { + .userdata = &mockdata, + .error_cb = mock_error, + .ud_init_cb = mock_ud_init, + .ud_exit_cb = mock_ud_exit, + .header_start_cb = mock_header_start, + .data_start_cb = mock_data_start, + .exchange_file_cb = NULL, + .header_entity_list_cb = NULL, + .data_section_list_cb = NULL, + .header_entity_cb = mock_header_entity, + .simple_entity_instance_cb = mock_simple_entity_instance, + .complex_entity_instance_cb = mock_complex_entity_instance, + .parameter_list_cb = mock_noop, + .parameter_cb = mock_noop, + .entity_instance_list_cb = NULL, + .entity_instance_cb = NULL, + .simple_record_list_cb = mock_noop, + .simple_record_cb = mock_noop +}; + +void mock_error(P21Parser *p, int bsp, uint8_t cxt) { + switch (cxt) { + case P_SIMPLEENTITY: + case P_COMPLEXENTITY: + case P_HEADERENTITY: + dprintf("caught error: '%c'\n", cxt); + p->error = false; + drop(p->stack, p->stack->idx_top - bsp - 1); + break; + default: + p->error = true; + break; + } +} + + +void mock_ud_init(void *d) { + P21UserData *ud = d; + char ddl_sql[] = + "PRAGMA foreign_keys = ON;\n" + "CREATE TABLE entity_enum (type TEXT(1) PRIMARY KEY);\n" + "INSERT INTO entity_enum (type) VALUES ('S'), ('C');\n" + "CREATE TABLE section_enum (type TEXT(1) PRIMARY KEY);\n" + "INSERT INTO section_enum (type) VALUES ('D'), ('H');\n" + + "CREATE TABLE section_table (\n" + " id INTEGER PRIMARY KEY,\n" + " lineno INTEGER NOT NULL,\n" + " section_type TEXT(1) NOT NULL REFERENCES section_enum(type)\n" + ");\n" + + "CREATE TABLE section_headers (\n" + " id INTEGER PRIMARY KEY,\n" + " type_name TEXT COLLATE NOCASE,\n" + " raw_data TEXT NOT NULL,\n" + " lineno INTEGER NOT NULL,\n" + " fk_section INTEGER NOT NULL REFERENCES section_table(id)\n" + ");\n" + + "CREATE TABLE data_table (\n" + " id TEXT PRIMARY KEY,\n" + " type_name TEXT COLLATE NOCASE,\n" + " raw_data TEXT NOT NULL,\n" + " lineno INTEGER NOT NULL,\n" + " entity_type TEXT(1) NOT NULL REFERENCES entity_enum(type),\n" + " fk_section INTEGER NOT NULL REFERENCES section_table(id)\n" + ") WITHOUT ROWID;\n" + + "BEGIN DEFERRED TRANSACTION;"; + + char sei_sql[] = "INSERT INTO data_table VALUES (?,?,?,?,'S',?)"; + char cei_sql[] = "INSERT INTO data_table VALUES (?,NULL,?,?,'C',?)"; + char hei_sql[] = "INSERT INTO section_headers(type_name, raw_data, lineno, fk_section) VALUES (?, ?, ?, ?)"; + int rc; + + rc = sqlite3_open_v2(":memory:", &ud->db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); + + /* TODO: read ddl sql from external file */ + rc = sqlite3_exec(ud->db, ddl_sql, NULL, NULL, NULL); + + rc |= sqlite3_prepare_v3(ud->db, sei_sql, sizeof sei_sql, SQLITE_PREPARE_PERSISTENT, &ud->sei_stmt, NULL); + rc |= sqlite3_prepare_v3(ud->db, cei_sql, sizeof cei_sql, SQLITE_PREPARE_PERSISTENT, &ud->cei_stmt, NULL); + rc |= sqlite3_prepare_v3(ud->db, hei_sql, sizeof hei_sql, SQLITE_PREPARE_PERSISTENT, &ud->hei_stmt, NULL); + + if (rc != SQLITE_OK) + exit(1); + + ud->section_idx = 0; +} + +void mock_ud_exit(void *d) { + P21UserData *ud = d; + int rc; + char ddl_sql[] = + "CREATE INDEX ix_type_name ON data_table(type_name);\n" + "CREATE INDEX ix_entity_type ON data_table(entity_type);\n" + "CREATE INDEX ix_fk_section ON data_table(fk_section);"; + + rc = sqlite3_finalize(ud->sei_stmt); + rc |= sqlite3_finalize(ud->cei_stmt); + rc |= sqlite3_finalize(ud->hei_stmt); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_exec(ud->db, "COMMIT TRANSACTION", NULL, NULL, NULL); + if (rc != SQLITE_OK) goto err; + + /* TODO: benchmark index creation here vs on db init */ + rc = sqlite3_exec(ud->db, ddl_sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_close(ud->db); + if (rc != SQLITE_OK) goto err; + + return; +err: + dprintf("db error\n"); + exit(1); +} + +void mock_exchange_file(P21Parser *p, int bsp, void *d) { Stack *s = p->stack; } +void mock_header_start(P21Parser *p, int bsp, void *d) { + char sec_sql[] = "INSERT INTO section_table VALUES(?,?,'H')"; + Stack *s = p->stack; + P21UserData *ud = d; + Symbol *t = s->items + bsp; + sqlite3_stmt *stmt; + int rc; + + rc = sqlite3_prepare_v2(ud->db, sec_sql, sizeof sec_sql, &stmt, NULL); + if (rc != SQLITE_OK) goto err; + + rc |= sqlite3_bind_int(stmt, 1, ++ud->section_idx); + rc |= sqlite3_bind_int(stmt, 2, t->lineno); + if (rc != SQLITE_OK) goto err; + + rc |= sqlite3_step(stmt); + if (rc != SQLITE_DONE) goto err; + + sqlite3_finalize(stmt); + + /* + s->items[bsp] = (Symbol){P_HEADERSECTION}; + drop(s, s->idx_top - bsp - 1); + */ + + return; + +err: + dprintf("db error\n"); + exit(1); +} +void mock_header_entity_list(P21Parser *p, int bsp, void *d) { Stack *s = p->stack; } +void mock_data_section_list(P21Parser *p, int bsp, void *d) { Stack *s = p->stack; } +void mock_data_start(P21Parser *p, int bsp, void *d) { + char sec_sql[] = "INSERT INTO section_table VALUES(?,?,'D')"; + Stack *s = p->stack; + P21UserData *ud = d; + Symbol *t = s->items + bsp; + sqlite3_stmt *stmt; + int rc; + + rc = sqlite3_prepare_v2(ud->db, sec_sql, sizeof sec_sql, &stmt, NULL); + if (rc != SQLITE_OK) goto err; + + rc |= sqlite3_bind_int(stmt, 1, ++ud->section_idx); + rc |= sqlite3_bind_int(stmt, 2, t->lineno); + if (rc != SQLITE_OK) goto err; + + rc |= sqlite3_step(stmt); + if (rc!= SQLITE_DONE) goto err; + + sqlite3_finalize(stmt); + + return; + +err: + dprintf("db error\n"); + exit(1); +} + +void mock_header_entity(P21Parser *p, int bsp, void *d) { + Stack *s = p->stack; + P21UserData *ud = d; + HeaderEntity e = {s->items + bsp, s->items + bsp + 1}; + size_t i, nargs = e.args->n; + unsigned char *basemrk = p->in->basemrk; + ptrdiff_t ep; + int rc; + + /* rewrite (normalise) args member before bind */ + e.args->offset = (e.args + 1)->offset; + e.args->n = (e.args + 1)->n; + for (i = 2, ep = e.args->offset + 1; i < nargs; i++) { + Symbol *t = e.args + i; + if (t->token == '(') t->n = 1; + if (ep != t->offset) memmove(basemrk + ep, basemrk + t->offset, t->n); + ep += t->n; + } + e.args->n = ep - e.args->offset; + + rc = sqlite3_reset(ud->hei_stmt); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_bind_text(ud->hei_stmt, 1, basemrk + e.kw->offset, e.kw->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_text(ud->hei_stmt, 2, basemrk + e.args->offset, e.args->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_int(ud->hei_stmt, 3, e.kw->lineno); + rc |= sqlite3_bind_int(ud->hei_stmt, 4, ud->section_idx); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_step(ud->hei_stmt); + if (rc != SQLITE_DONE) goto err; + + p->hold = false; + return; + +err: + mock_error(p, bsp, P_HEADERENTITY); + dprintf("db error\n"); +} + +void mock_simple_entity_instance(P21Parser *p, int bsp, void *d) { + Stack *s = p->stack; + P21UserData *ud = d; + SimpleEntity e = {s->items + bsp, s->items + bsp + 1, s->items + bsp + 2, s->items + bsp + 3}; + size_t i, nargs = e.args->n; + unsigned char *basemrk = p->in->basemrk; + ptrdiff_t ep; + int rc; + + /* rewrite (normalise) args before bind */ + e.args->offset = (e.args + 1)->offset; + e.args->n = (e.args + 1)->n; + for (i = 2, ep = e.args->offset + e.args->n; i < nargs; i++) { + Symbol *t = e.args + i; + if (t->token == '(') t->n = 1; + if (ep != t->offset) memmove(basemrk + ep, basemrk + t->offset, t->n); + ep += t->n; + } + e.args->n = ep - e.args->offset; + + /* */ + rc = sqlite3_reset(ud->sei_stmt); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_bind_text(ud->sei_stmt, 1, basemrk + e.eid->offset, e.eid->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_text(ud->sei_stmt, 2, basemrk + e.kw->offset, e.kw->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_text(ud->sei_stmt, 3, basemrk + e.args->offset, e.args->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_int(ud->sei_stmt, 4, e.eid->lineno); + rc |= sqlite3_bind_int(ud->sei_stmt, 5, ud->section_idx); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_step(ud->sei_stmt); + if (rc != SQLITE_DONE) goto err; + + p->hold = false; + + return; + +err: + mock_error(p, bsp, P_SIMPLEENTITY); + dprintf("db error\n"); +} + + +void mock_complex_entity_instance(P21Parser *p, int bsp, void *d) { + Stack *s = p->stack; + P21UserData *ud = d; + ComplexEntity e = {s->items + bsp, s->items + bsp + 1, s->items + bsp + 2}; + size_t i, nsubsupers = e.subsupers->n; + unsigned char *basemrk = p->in->basemrk; + ptrdiff_t ep; + int rc; + + /* rewrite (normalise) list before bind */ + for (i = 1, ep = e.subsupers->offset + 1; i < nsubsupers; i++) { + Symbol *t = e.subsupers + i; + if (t->token == '(') t->n = 1; + if (ep != t->offset) memmove(basemrk + ep, basemrk + t->offset, t->n); + ep += t->n; + } + e.subsupers->n = ep - e.subsupers->offset; + + rc = sqlite3_reset(ud->cei_stmt); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_bind_text(ud->cei_stmt, 1, basemrk + e.eid->offset, e.eid->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_text(ud->cei_stmt, 2, basemrk + e.subsupers->offset, e.subsupers->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_int(ud->cei_stmt, 3, e.eid->lineno); + rc |= sqlite3_bind_int(ud->cei_stmt, 4, ud->section_idx); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_step(ud->cei_stmt); + if (rc != SQLITE_DONE) goto err; + + p->hold = false; + return; + +err: + mock_error(p, bsp, P_COMPLEXENTITY); + dprintf("db error \n"); +} + +void mock_parameter_list(P21Parser *p, int bsp, void *d) { } +void mock_parameter(P21Parser *p, int bsp, void *d) { } +void mock_entity_instance_list(P21Parser *p, int bsp, void *d) { } +void mock_entity_instance(P21Parser *p, int bsp, void *d) { } +void mock_simple_record_list(P21Parser *p, int bsp, void *d) { } +void mock_simple_record(P21Parser *p, int bsp, void *d) {} + +void mock_noop(P21Parser *p, int bsp, void *d) { + p->hold = true; +} + +int main(char *argv[], int argc) { + const char *paths[] = { + "/home/chorler/projects/src/stepcode/test/p21/test_array_bounds_FAIL1.p21", + "/home/chorler/projects/src/stepcode/test/p21/comments.p21", + "/home/chorler/projects/src/stepcode/test/p21/test_inverse_attr.p21", + "/home/chorler/projects/src/stepcode/test/p21/missing_and_required.p21", + "/home/chorler/projects/src/stepcode/test/p21/test_array_bounds.p21", + "/home/chorler/projects/src/stepcode/test/p21/test_inherit_inverse.p21", + "/home/chorler/projects/src/stepcode/data/ap214e3/as1-oc-214.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/dm1-id-214.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/MAINBODY.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/HEAD_BACK.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/HEAD_FRONT.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/TAIL.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/MAINBODY_FRONT.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/FOOT_BACK_000.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/FOOT_FRONT_000.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/s1-c5-214.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/MAINBODY_BACK.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/HEAD.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/TAIL_TURBINE.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/TAIL_MIDDLE_PART.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/FOOT.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/sg1-c5-214.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/io1-cm-214.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS7-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS1Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS2-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS1Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS3-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS10Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS2Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS8-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS3Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS4Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS7Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS4Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS10Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS3Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS8Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS4-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS7Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS2Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS8Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS10-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS1-out.stp" + }; + + P21Parser myp; + P21UserData mydata; + FILE *fp; + memset(&mydata, 0, sizeof mydata); + + for (unsigned int i = 0; i < (sizeof paths / sizeof paths[0]); i++) { + fp = fopen(paths[i], "rb"); + if (!fp) { fprintf(stderr, "failed to read input: %s\n", paths[i]); continue; } + else { fprintf(stderr, "processing: %s\n", paths[i]); } + p21_init(&myp, fp); + p21_parse(&myp, &mockact); + } +} diff --git a/src/exp2python/python/stepcode/_cPart21.l b/src/exp2python/python/stepcode/_cPart21.l new file mode 100644 index 000000000..2a8ded85a --- /dev/null +++ b/src/exp2python/python/stepcode/_cPart21.l @@ -0,0 +1,1602 @@ +/* + * STEP Part 21 Parser + * + * Copyright (c) 2020, Christopher HORLER (cshorler@googlemail.com) + * + * All rights reserved. + * + * This file is part of the STEPCODE project. + * + * 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 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 HOLDER 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#define YYCTYPE unsigned char +#define YYCURSOR in->cur +#define YYLIMIT in->lim +#define YYMARKER in->mrk +#define YYCTXMARKER in->ctxmrk +#define YYFILL(n) do { \ + if (fill(in, n) != 0) { \ + fprintf(stderr, "lexer fill(...) failed, exiting\n"); \ + exit(1); \ + } \ + } while (0) + +/*!max:re2c*/ +#define INIT_BUF_SZ 4096 +#define INIT_STACK_SZ 64 + +/* reserved literals '(' ')' ';' '=' */ +#define T_P21_START 'S' +#define T_P21_END 'X' +#define T_HEADER 'H' +#define T_DATA 'D' +#define T_ENDSEC 'E' +#define T_EID 'I' +#define T_KEYWORD 'K' +#define T_VARIANT 'V' +#define T_EOF '\x00' +#define T_ERROR '\x01' + +#define V_REAL 'r' +#define V_INTEGER 'i' +#define V_STRING 's' +#define V_BINARY 'b' +#define V_ENUMERATION 'e' +#define V_EID T_EID +#define V_DERIVED '*' +#define V_EMPTY '$' + +#define P_FILE 'f' +#define P_HEADERSECTION 'h' +#define P_DATASECTION 'd' +#define P_HEADERENTITY 'x' +#define P_SIMPLEENTITY 's' +#define P_COMPLEXENTITY 'c' +#define P_SIMPLERECORD 'u' +#define P_LIST 'l' +#define P_PARAMETER 'p' + +int debug = 1; +#define dprintf(fmt, ...) \ + do { if (debug) fprintf(stderr, "%s:%3d " fmt, __FILE__, __LINE__, ##__VA_ARGS__); } while (0) + +/* ppfu https://stackoverflow.com/a/11763277/1162349 */ +#define GET_MACRO(_1, _2, _3, _4, NAME, ...) NAME +#define _EXPAND(x) x + +/* for lookahead */ +#define PUSH_SYMBOL(...) _EXPAND(GET_MACRO(__VA_ARGS__, _4, _3, _PUSH_SYMBOL2, _PUSH_SYMBOL1)(__VA_ARGS__)) +#define _PUSH_SYMBOL1(token) in->sym[in->nsym++] = (Symbol){(token), 0, n, in->lineno, in->sp - in->basemrk} +#define _PUSH_SYMBOL2(token, vtype) in->sym[in->nsym++] = (Symbol){(token), (vtype), n, in->lineno, in->sp - in->basemrk} + +/* for parse stack */ +#define PUSH_TERMINAL(stack, sym) do { \ + Symbol it = (sym); \ + push((stack), it); \ + if (it.token == T_ERROR) goto err; \ + } while (0) + +#define PUSH_TERMINAL_EXT(cxt, stack, sym) do { \ + Symbol it = (sym); \ + push((stack), it); \ + if (it.token == T_ERROR) goto err; \ + else if (it.token == '(') (cxt) = (stack)->idx_top - 1; \ + else if (it.token == ')') (stack)->items[(cxt)].n = (stack)->idx_top - (cxt) - 1; \ + } while (0) + +/* test for one in a set of 1 to 4 e.g. {t0, t1, t2, t3} */ +#define LOOKAHEAD(x, ...) _EXPAND(GET_MACRO(__VA_ARGS__, _LOOKAHEAD4, _LOOKAHEAD3, _LOOKAHEAD2, _LOOKAHEAD1)(x, __VA_ARGS__)) +#define _LOOKAHEAD1(x, t0) ((t0) == (x).token) +#define _LOOKAHEAD2(x, t0, t1) ((t0) == (x).token || (t1) == (x).token) +#define _LOOKAHEAD3(x, t0, t1, t2) (_LOOKAHEAD2(x, t0, t1) || (t2) == (x).token) +#define _LOOKAHEAD4(x, t0, t1, t2, t3) (_LOOKAHEAD2(x, t0, t1) || _LOOKAHEAD2(x, t2, t3)) + + +/*!rules:re2c + ascii_encoding = [][!"*$%&.#+,\-()?/:;<=>@{}|^`~0-9a-zA-Z_ ] | "''" | "\\\\" ; + page_encoding = "\\" [A-I] "\\" | "\\S\\" [][!"'*$%&.#+,\-()?/:;<=>@{}|^`~0-9a-zA-Z_\\ ] ; + hex_encoding = "\\X2\\" ([0-9A-F]{4})+ "\\X0\\" | "\\X4\\" ([0-9A-F]{8})+ "\\X0\\" ; + byte_encoding = "\\X\\" [0-9A-F]{2} ; + + NL = ("\n" | "\r\n") ; + PUNCTUATION = [ ;()/] ; + + P21_START = "ISO-10303-21;" ; + P21_END = "END-ISO-10303-21;" ; + DATA = "DATA" ; + HEADER = "HEADER;" ; + ENDSEC = "ENDSEC;" ; + + WS = " " ; + KEYWORD = "!"? [A-Za-z_] [0-9A-Za-z_]* ; + REAL = [+-]* [0-9] [0-9]* "." [0-9]* ("E" [+-]* [0-9] [0-9]*)? ; + INTEGER = [+-]* [0-9] [0-9]* ; + STRING = "'" (ascii_encoding | page_encoding | hex_encoding | byte_encoding )* "'" ; + BINARY = '"' [0-3] [0-9A-F]* '"' ; + ENUMERATION = "." [A-Z_] [A-Z0-9_]* "." ; + EID = "#" [0-9]+ ; + + { n = in->cur - in->sp; } + WS+ { continue; } + NL { in->lineno++; continue; } + "/*" { lex_comment(in); continue; } + * { YYCURSOR--; break; } + + */ + + +/* lexeme */ +typedef struct { + uint8_t token; + union { + uint8_t vtype; + uint8_t errtoken; + }; + uint16_t n; + uint32_t lineno; + union { + ptrdiff_t offset; /* from basemrk */ + void *data; /* production allocation if applicable */ + }; +} Symbol; + +typedef struct SimpleRecord_ { + Symbol *kw; /* 'KEYWORD' */ + Symbol *args;/* '(' */ +} SimpleRecord; + +typedef struct SimpleRecord_ HeaderEntity; + +typedef struct { + Symbol *eid; /* '#' */ + Symbol *eq; /* '=' */ + Symbol *kw; /* 'KEYWORD' */ + Symbol *args;/* '(' */ +} SimpleEntity; + +typedef struct { + Symbol *eid; /* '#' */ + Symbol *eq; /* '=' */ + Symbol *subsupers;/* '(' */ +} ComplexEntity; + + +typedef struct { + FILE *file; + size_t bufsz; + unsigned char *cur, *mrk, *ctxmrk, *lim; + unsigned char *sp, *basemrk; + int eof; + uint32_t lineno; + int nsym; + Symbol sym[3]; + unsigned char *buf; +} Input; + +typedef struct { + int idx_top; + int idx_lim; + Symbol *items; +} Stack; + +/* LL(3) parser */ +typedef struct { + bool error; + bool hold; + Input *in; + Stack *stack; +} P21Parser; + +typedef void (p21_action_cb_t) (P21Parser *, int, void *); +typedef void (p21_error_cb_t) (P21Parser *, int, uint8_t); +typedef void (p21_ud_cb_t) (void *); + +typedef struct { + void *userdata; + p21_error_cb_t *error_cb; + p21_ud_cb_t *ud_init_cb; + p21_ud_cb_t *ud_exit_cb; + p21_action_cb_t *exchange_file_cb; + p21_action_cb_t *header_start_cb; + p21_action_cb_t *header_entity_list_cb; + p21_action_cb_t *data_section_list_cb; + p21_action_cb_t *data_start_cb; + p21_action_cb_t *header_entity_cb; + p21_action_cb_t *simple_entity_instance_cb; + p21_action_cb_t *complex_entity_instance_cb; + p21_action_cb_t *parameter_list_cb; + p21_action_cb_t *parameter_cb; + p21_action_cb_t *entity_instance_list_cb; + p21_action_cb_t *entity_instance_cb; + p21_action_cb_t *simple_record_list_cb; + p21_action_cb_t *simple_record_cb; +} P21ParserActions; + + +void report_error(P21Parser *, const char *); +void _recover(Input *, uint8_t, uint8_t, uint8_t); +Symbol lpop(Input *, uint8_t); + +void p21_parse(P21Parser *, P21ParserActions *); +void p21_exchange_file(P21Parser *, P21ParserActions *); +void p21_header_section(P21Parser *, P21ParserActions *); +void p21_header_entity_list(P21Parser *, P21ParserActions *); +void p21_header_entity(P21Parser *, P21ParserActions *); +void p21_data_section_list(P21Parser *, P21ParserActions *); +void p21_data_section(P21Parser *, P21ParserActions *); +void p21_entity_instance(P21Parser *, P21ParserActions *); +void p21_simple_entity_instance(P21Parser *, P21ParserActions *); +void p21_complex_entity_instance(P21Parser *, P21ParserActions *); +void p21_entity_instance_list(P21Parser *, P21ParserActions *); +void p21_parameter(P21Parser *, P21ParserActions *); +void p21_parameter_list(P21Parser *, P21ParserActions *); +void p21_simple_record(P21Parser *, P21ParserActions *); +void p21_simple_record_list(P21Parser *, P21ParserActions *); + + +void push(Stack *stack, Symbol it) { + if (stack->idx_top == stack->idx_lim) { + Symbol *nitems = realloc(stack->items, 2 * stack->idx_lim * sizeof stack->items[0]); + if (!nitems) { + fprintf(stderr, "failed to grow parser stack, memory exhausted\n"); + exit(1); + } + stack->items = nitems; + stack->idx_lim *= 2; + } + + stack->items[stack->idx_top++] = it; +} + +/* mock implementations */ +void drop(Stack *stack, uint32_t n) { + assert(stack->idx_top >= n); + stack->idx_top -= n; +} + +void unwind(Stack *stack, int bsp) { + stack->idx_top = bsp; +} + +Symbol *pop(Stack *stack) { + assert(stack->idx_top >= 1); + stack->idx_top--; + return stack->items + stack->idx_top; +} + +Symbol *peek(Stack *stack) { + assert(stack->idx_top >= 1); + return stack->items + stack->idx_top - 1; +} + +Symbol lpop(Input *in, uint8_t token) { + Symbol *stack = in->sym; + Symbol sym = stack[0]; + + /* missing input or unexpected lookahead token */ + if (in->nsym == 0) + return (Symbol){T_ERROR, token, 0, in->lineno}; + else if (sym.token != token) + return (Symbol){T_ERROR, token, 0, sym.lineno}; + + if (!--in->nsym) { + memset(&in->sym[0], 0, sizeof in->sym[0]); + } else { + memmove(&in->sym[0], &in->sym[1], in->nsym * sizeof in->sym[0]); + memset(&in->sym[in->nsym], 0, sizeof in->sym[0]); + } + + return sym; +} + +static int fill(Input *in, size_t need) +{ + size_t free; + unsigned char *newbuf; + + if (in->eof) { + return 1; + } + free = in->basemrk - in->buf; + if (free < need) { + newbuf = realloc(in->buf, 2 * in->bufsz + YYMAXFILL); + if (!newbuf) { + fprintf(stderr, "fatal - buffer memory exhausted, exiting\n"); + return 2; + } + in->bufsz *= 2; + in->lim = newbuf + (in->lim - in->buf); + in->cur = newbuf + (in->cur - in->buf); + in->mrk = newbuf + (in->mrk - in->buf); + in->ctxmrk = newbuf + (in->ctxmrk - in->buf); + in->basemrk = newbuf + (in->basemrk - in->buf); + in->sp = newbuf + (in->sp - in->buf); + in->buf = newbuf; + + /* don't memmove() here! */ + free = (in->buf + in->bufsz) - in->lim; + } else { + memmove(in->buf, in->basemrk, in->lim - in->basemrk); + in->lim -= free; + in->cur -= free; + in->mrk -= free; + in->ctxmrk -= free; + in->basemrk -= free; + in->sp -= free; + } + + in->lim += fread(in->lim, 1, free, in->file); + if (in->lim < in->buf + in->bufsz) { + in->eof = 1; + memset(in->lim, 0, YYMAXFILL); + in->lim += YYMAXFILL; + } + return 0; +} + +static void p21_init(P21Parser *p, FILE *file) +{ + Stack *stack; + Input *in; + + in = malloc(sizeof *in); + if (!in) + goto err; + memset(in, 0, sizeof *in); + in->bufsz = INIT_BUF_SZ; + in->buf = malloc(INIT_BUF_SZ + YYMAXFILL); + if (!in->buf) + goto err; + in->file = file; + in->cur = in->basemrk = in->sp = in->lim = in->buf + INIT_BUF_SZ; + in->lineno = 1; + fill(in, 1); + + stack = malloc(sizeof *stack); + if (!stack) + goto err; + memset(stack, 0, sizeof *stack); + stack->idx_lim = 16; + stack->idx_top = 0; + stack->items = malloc(stack->idx_lim * sizeof stack->items[0]); + if (!stack->items) + goto err; + + p->in = in; + p->stack = stack; + p->error = false; + + return; + +err: + fprintf(stderr, "failed to initialise parser\n"); + exit(1); +} + +/* noop error handler */ +void default_error_handler(P21Parser *p, int bsp, uint8_t t) { + Symbol *sym = peek(p->stack); + if (sym->token == T_ERROR) + pop(p->stack); + push(p->stack, (Symbol){t}); +} + +/* TODO: this needs to be reworked */ +void report_error(P21Parser *p, const char *cxt) { + Input *in = p->in; + Symbol *it = peek(p->stack); + int lineno; + unsigned char *cur; + + fprintf(stderr, cxt); + + if (it->token == T_ERROR) { + fprintf(stderr, " syntax error - line: %d\n", it->lineno); + fprintf(stderr, " expected '%c' (token type) ", it->errtoken); + } else { + cur = in->cur; + lineno = in->lineno; + while (1) { + if (*(cur - 2) == '\r' && *(cur - 1) == '\n') { cur -= 2; --lineno; } + else if (*(cur - 1) == '\n') { --cur; --lineno; } + else { break; } + } + fprintf(stderr, " syntax error - line: %d\n", lineno); + } + + if (!in->nsym) { + cur = in->cur; + lineno = in->lineno; + while (1) { + if (*cur == '\r' && *(cur + 1) == '\n') { cur -= 2; --lineno; } + else if (*cur == '\n') { --cur; --lineno; } + else { break; } + } + fprintf(stderr, " unexpected character '%c' (line: %d)\n", *cur, lineno); + } else { + fprintf(stderr, " got '%c' (token type)\n", in->sym[0].token); + } +} + + +void lex_comment(Input *in) { + size_t n; + int comment_lvl = 1; + + while (1) { + in->sp = in->cur; + /*!use:re2c + NOT_SLASH_STAR = [][!"#$%&'()+,\-.:;<=>?@\\^`{|}~0-9A-Z_a-z ] ; + + "*"+ "/" { + if (!--comment_lvl) { break; } + else { continue; } + } + "*"+ { continue; } + NOT_SLASH_STAR+ { continue; } + "/" { continue; } + "/*" { ++comment_lvl; continue; } */ + } + + return; + +err: + fprintf(stderr, "invalid character in comment, exiting\n"); + exit(1); +} + +#define recover(in, ...) GET_MACRO(__VA_ARGS__, _4, _RECOVER3, _RECOVER2, _RECOVER1)(in, __VA_ARGS__) +#define _RECOVER1(in, u0) _recover((in), (u0), 0U, 0U) +#define _RECOVER2(in, u0, u1) _recover((in), (u0), (u1), 0U) +#define _RECOVER3(in, u0, u1, u2) _recover((in), (u0), (u1), (u2)) + +void _recover(Input *in, uint8_t u0, uint8_t u1, uint8_t u2) { + size_t n; + Symbol sym; + + while (in->nsym) { + if (LOOKAHEAD(in->sym[0], u0, u1, u2, T_EOF)) + break; + --in->nsym; + memmove(&in->sym[0], &in->sym[1], in->nsym * sizeof in->sym[0]); + memset(&in->sym[in->nsym], 0, sizeof in->sym[0]); + } + + if (in->nsym) + return; + + while (1) { + in->sp = in->cur; + /*!use:re2c + P21_START { sym = (Symbol){T_P21_START}; goto check; } + P21_END { sym = (Symbol){T_P21_END}; goto check; } + HEADER { sym = (Symbol){T_HEADER}; goto check; } + DATA / PUNCTUATION { sym = (Symbol){T_DATA}; goto check; } + ENDSEC { sym = (Symbol){T_ENDSEC}; goto check; } + EID { sym = (Symbol){T_EID}; goto check; } + KEYWORD { sym = (Symbol){T_KEYWORD}; goto check; } + REAL { sym = (Symbol){T_VARIANT, V_REAL}; goto check; } + INTEGER { sym = (Symbol){T_VARIANT, V_INTEGER}; goto check; } + STRING { sym = (Symbol){T_VARIANT, V_STRING}; goto check; } + BINARY { sym = (Symbol){T_VARIANT, V_BINARY}; goto check; } + ENUMERATION { sym = (Symbol){T_VARIANT, V_ENUMERATION}; goto check; } + "*" { sym = (Symbol){T_VARIANT, V_DERIVED}; goto check; } + "$" { sym = (Symbol){T_VARIANT, V_EMPTY}; goto check; } + [();] { sym = (Symbol){*in->sp}; goto check; } + */ +check: + if (LOOKAHEAD(sym, u0, u1, u2, T_EOF)) { + PUSH_SYMBOL(sym.token, sym.vtype); + break; + } + } + + return; + +err: + fprintf(stderr, "fatal, failed to resolve follow set (%c, %c, %c)\n", u0, u1, u2); + exit(1); +} + + +/* + * P21Parser + */ +void p21_parse(P21Parser *p, P21ParserActions *act) { + if (act->ud_init_cb) + act->ud_init_cb(act->userdata); + + p21_exchange_file(p, act); + + if (act->ud_exit_cb) + act->ud_exit_cb(act->userdata); + + assert(p->stack->idx_top == 1); + return; + +err: + report_error(p, "exchange_file' << 0 >>\n"); +} + +void p21_exchange_file(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c + P21_START { PUSH_SYMBOL(T_P21_START); continue;} */ + } + PUSH_TERMINAL(p->stack, lpop(in, T_P21_START)); + + p21_header_section(p, act); + p21_data_section_list(p, act); + + PUSH_TERMINAL(p->stack, lpop(in, T_P21_END)); + + if (p->error) + goto err; + + /* user action */ + if (act->exchange_file_cb) + act->exchange_file_cb(p, bsp, act->userdata); + + /* default reduction */ + p->stack->items[bsp] = (Symbol){P_FILE}; + drop(p->stack, p->stack->idx_top - bsp - 1); + + return; + +err: + report_error(p, "exchange_file << 1 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_FILE); + else default_error_handler(p, bsp, P_FILE); + recover(in, T_EOF); +} + +void p21_header_section(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c re2c:labelprefix = 'yya'; + HEADER { PUSH_SYMBOL(T_HEADER); continue; } */ + } + PUSH_TERMINAL(p->stack, lpop(in, T_HEADER)); + + /* section callback */ + if (act->header_start_cb) + act->header_start_cb(p, bsp, act->userdata); + + /* mandatory headers */ + p21_header_entity(p, act); + p21_header_entity(p, act); + p21_header_entity(p, act); + + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c re2c:labelprefix = 'yyb'; + ENDSEC { PUSH_SYMBOL(T_ENDSEC); continue; } + KEYWORD { PUSH_SYMBOL(T_KEYWORD); continue; } */ + } + + /* optional headers */ + if (LOOKAHEAD(in->sym[0], T_KEYWORD)) + p21_header_entity_list(p, act); + + PUSH_TERMINAL(p->stack, lpop(in, T_ENDSEC)); + + if (p->error) + goto err; + + /* default reduction */ + p->stack->items[bsp] = (Symbol){P_HEADERSECTION}; + drop(p->stack, p->stack->idx_top - bsp - 1); + + return; + +err: + report_error(p, "header_section << 2 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_HEADERSECTION); + else default_error_handler(p, bsp, P_HEADERSECTION); + recover(in, T_DATA); +} + +void p21_data_section_list(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + uint32_t len = 0; + Input *in = p->in; + + do { + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c + DATA / PUNCTUATION { PUSH_SYMBOL(T_DATA); continue; } + P21_END { PUSH_SYMBOL(T_P21_END); continue; } */ + } + if (!LOOKAHEAD(in->sym[0], T_DATA)) + break; + p21_data_section(p, act); + } while (++len); + + /* one or more */ + if (!len) { + push(p->stack, (Symbol){T_ERROR, T_DATA, 0, in->sym[0].lineno}); + p->error = true; + } + + if(p->error) + goto err; + + /* user action */ + if (act->data_section_list_cb) + act->data_section_list_cb(p, bsp, act->userdata); + + /* default reduction */ + p->stack->items[bsp] = (Symbol){P_LIST}; + drop(p->stack, p->stack->idx_top - bsp - 1); + + return; + +err: + report_error(p, "data_section_list << 3 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, T_P21_END); +} + +void p21_data_section(P21Parser *p, P21ParserActions *act) { + size_t n, cxt; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + while (in->nsym < 2) { + in->sp = in->cur; + /*!use:re2c re2c:labelprefix = 'yya'; + [(;] { PUSH_SYMBOL(*in->sp); continue; } */ + } + PUSH_TERMINAL(p->stack, lpop(in, T_DATA)); + + if (LOOKAHEAD(in->sym[0], '(')) { + PUSH_TERMINAL(p->stack, lpop(in, '(')); + + p21_parameter_list(p, act); + while (in->nsym < 2) { + in->sp = in->cur; + /*!use:re2c re2c:labelprefix = 'yyb'; + ";" { PUSH_SYMBOL(';'); continue; } */ + } + + PUSH_TERMINAL(p->stack, lpop(in, ')')); + } + PUSH_TERMINAL(p->stack, lpop(in, ';')); + + if (act->data_start_cb) + act->data_start_cb(p, bsp, act->userdata); + + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c re2c:labelprefix = 'yyc'; + ENDSEC { PUSH_SYMBOL(T_ENDSEC); continue; } + EID { PUSH_SYMBOL(T_EID); continue; } */ + } + if (LOOKAHEAD(in->sym[0], T_EID)) + p21_entity_instance_list(p, act); + + PUSH_TERMINAL(p->stack, lpop(in, T_ENDSEC)); + + if (p->error) + goto err; + + /* default reduction */ + p->stack->items[bsp] = (Symbol){P_DATASECTION}; + drop(p->stack, p->stack->idx_top - bsp - 1); + + return; + +err: + report_error(p, "data_section << 4 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_DATASECTION); + else default_error_handler(p, bsp, P_DATASECTION); + recover(in, T_P21_END, T_DATA); +} + +void p21_header_entity(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + /* set KEYWORD as basemrk to prevent fill() recycling the buffer before user action */ + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c + KEYWORD { PUSH_SYMBOL(T_KEYWORD); continue; } */ + } + + /* set KEYWORD as basemrk to prevent fill() recycling the buffer before user action */ + assert(in->nsym == 1); + in->basemrk += in->sym[0].offset; + in->sym[0].offset = 0; + + p21_simple_record(p, act); + + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c + ";" { PUSH_SYMBOL(';'); continue; } */ + } + PUSH_TERMINAL(p->stack, lpop(in, ';')); + + if (p->error) + goto err; + + /* user action */ + if (act->header_entity_cb) + act->header_entity_cb(p, bsp, act->userdata); + + /* reduction */ + assert(!p->hold); + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_HEADERENTITY}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "header_entity << 5 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_HEADERENTITY); + else default_error_handler(p, bsp, P_HEADERENTITY); + recover(in, T_ENDSEC, T_KEYWORD); +} + +void p21_header_entity_list(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + p21_header_entity(p, act); + + do { + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c + KEYWORD { PUSH_SYMBOL(T_KEYWORD); continue; } + ENDSEC { PUSH_SYMBOL(T_ENDSEC); continue; } */ + } + if (!LOOKAHEAD(in->sym[0], T_KEYWORD)) + break; + p21_header_entity(p, act); + } while (1); + + if (p->error) + goto err; + + + /* user action */ + if (act->header_entity_list_cb) + act->header_entity_list_cb(p, bsp, act->userdata); + + /* reduction */ + assert(!p->hold); + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_LIST}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "header_entity_list << 6 >>"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, T_ENDSEC); +} + +void p21_entity_instance_list(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + p21_entity_instance(p, act); + + do { + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c + EID { PUSH_SYMBOL(T_EID); continue; } + ENDSEC { PUSH_SYMBOL(T_ENDSEC); continue; } */ + } + if (!LOOKAHEAD(in->sym[0], T_EID)) + break; + p21_entity_instance(p, act); + } while (1); + + if (p->error) + goto err; + + /* user action */ + if (act->entity_instance_list_cb) + act->entity_instance_list_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_LIST}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "entity_instance_list << 7 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, T_ENDSEC); +} + +void p21_parameter_list(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + p21_parameter(p, act); + + do { + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c + [,)] { PUSH_SYMBOL(*in->sp); continue; } */ + } + if (LOOKAHEAD(in->sym[0], ')')) + break; + + PUSH_TERMINAL(p->stack, lpop(in, ',')); + p21_parameter(p, act); + } while (1); + + if (p->error) + goto err; + + /* user action */ + if (act->parameter_list_cb) + act->parameter_list_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_LIST}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "parameter_list << 8 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, ')', ';'); +} + +void p21_entity_instance(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + /* set EID as basemrk to prevent fill() recycling the buffer before user action */ + assert(in->nsym == 1); + in->basemrk += in->sym[0].offset; + in->sym[0].offset = 0; + + while (in->nsym < 3) { + in->sp = in->cur; + /*!use:re2c + KEYWORD { PUSH_SYMBOL(T_KEYWORD); continue; } + [(=] { PUSH_SYMBOL(*in->sp); continue; } */ + } + if (!LOOKAHEAD(in->sym[0], T_EID) || !LOOKAHEAD(in->sym[1], '=')) + goto err; + + if (LOOKAHEAD(in->sym[2], T_KEYWORD)) { + p21_simple_entity_instance(p, act); + } else if (LOOKAHEAD(in->sym[2], '(')) { + p21_complex_entity_instance(p, act); + } + + if (p->error) + goto err; + + /* user action */ + if (act->entity_instance_cb) + act->entity_instance_cb(p, bsp, act->userdata); + + /* no default reduction */ + + return; + +err: + report_error(p, "entity_instance << 9 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, T_ENDSEC, T_EID); +} + +void p21_simple_entity_instance(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + PUSH_TERMINAL(p->stack, lpop(in, T_EID)); + PUSH_TERMINAL(p->stack, lpop(in, '=')); + + p21_simple_record(p, act); + + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c + ";" { PUSH_SYMBOL(';'); continue; } */ + } + PUSH_TERMINAL(p->stack, lpop(in, ';')); + + if (p->error) + goto err; + + /* user action */ + if (act->simple_entity_instance_cb) + act->simple_entity_instance_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_SIMPLEENTITY}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "simple_entity_instance << 10 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_SIMPLEENTITY); + else default_error_handler(p, bsp, P_SIMPLEENTITY); + recover(in, T_ENDSEC, T_EID); +} + + +void p21_complex_entity_instance(P21Parser *p, P21ParserActions *act) { + size_t n, c; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + PUSH_TERMINAL(p->stack, lpop(in, T_EID)); + PUSH_TERMINAL(p->stack, lpop(in, '=')); + PUSH_TERMINAL_EXT(c, p->stack, lpop(in, '(')); + + p21_simple_record_list(p, act); + + while (in->nsym < 2) { + in->sp = in->cur; + /*!use:re2c + ";" { PUSH_SYMBOL(';'); continue; } */ + } + + PUSH_TERMINAL_EXT(c, p->stack, lpop(in, ')')); + PUSH_TERMINAL(p->stack, lpop(in, ';')); + + if (p->error) + goto err; + + /* user action */ + if (act->complex_entity_instance_cb) + act->complex_entity_instance_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_COMPLEXENTITY}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "complex_entity_instance << 11 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_COMPLEXENTITY); + else default_error_handler(p, bsp, P_COMPLEXENTITY); + recover(in, T_ENDSEC, T_EID); +} + +void p21_simple_record(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + while (in->nsym < 3) { + in->sp = in->cur; + /*!use:re2c + KEYWORD { PUSH_SYMBOL(T_KEYWORD); continue; } + REAL { PUSH_SYMBOL(T_VARIANT, V_REAL); continue; } + INTEGER { PUSH_SYMBOL(T_VARIANT, V_INTEGER); continue; } + STRING { PUSH_SYMBOL(T_VARIANT, V_STRING); continue; } + BINARY { PUSH_SYMBOL(T_VARIANT, V_BINARY); continue; } + ENUMERATION { PUSH_SYMBOL(T_VARIANT, V_ENUMERATION); continue; } + EID { PUSH_SYMBOL(T_VARIANT, V_EID); continue; } + "*" { PUSH_SYMBOL(T_VARIANT, V_DERIVED); continue; } + "$" { PUSH_SYMBOL(T_VARIANT, V_EMPTY); continue; } + [()] { PUSH_SYMBOL(*in->sp); continue; } */ + } + + PUSH_TERMINAL(p->stack, lpop(in, T_KEYWORD)); + PUSH_TERMINAL_EXT(n, p->stack, lpop(in, '(')); + + if (LOOKAHEAD(in->sym[0], '(', T_KEYWORD, T_VARIANT)) + p21_parameter_list(p, act); + + PUSH_TERMINAL_EXT(n, p->stack, lpop(in, ')')); + + if (p->error) + goto err; + + /* user action */ + if (act->simple_record_cb) + act->simple_record_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_SIMPLERECORD}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "simple_record << 12 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_SIMPLERECORD); + else default_error_handler(p, bsp, P_SIMPLERECORD); + recover(in, ';', ')', T_KEYWORD); +} + +void p21_simple_record_list(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + p21_simple_record(p, act); + + do { + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c + KEYWORD { PUSH_SYMBOL(T_KEYWORD); continue; } + ")" { PUSH_SYMBOL(')'); continue; } */ + } + if (!LOOKAHEAD(in->sym[0], T_KEYWORD)) + break; + p21_simple_record(p, act); + } while (1); + + if (p->error) + goto err; + + /* user action */ + if (act->simple_record_list_cb) + act->simple_record_list_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_LIST}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "simple_record_list << 13 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_LIST); + else default_error_handler(p, bsp, P_LIST); + recover(in, ')', ';'); +} + +void p21_parameter(P21Parser *p, P21ParserActions *act) { + size_t n; + uint32_t bsp = p->stack->idx_top; + Input *in = p->in; + + while (in->nsym < 2) { + in->sp = in->cur; + /*!use:re2c re2c:labelprefix='yya'; + KEYWORD { PUSH_SYMBOL(T_KEYWORD); continue; } + REAL { PUSH_SYMBOL(T_VARIANT, V_REAL); continue; } + INTEGER { PUSH_SYMBOL(T_VARIANT, V_INTEGER); continue; } + STRING { PUSH_SYMBOL(T_VARIANT, V_STRING); continue; } + BINARY { PUSH_SYMBOL(T_VARIANT, V_BINARY); continue; } + ENUMERATION { PUSH_SYMBOL(T_VARIANT, V_ENUMERATION); continue; } + EID { PUSH_SYMBOL(T_VARIANT, V_EID); continue; } + "*" { PUSH_SYMBOL(T_VARIANT, V_DERIVED); continue; } + "$" { PUSH_SYMBOL(T_VARIANT, V_EMPTY); continue; } + [(),] { PUSH_SYMBOL(*in->sp); continue; } */ + } + + if (LOOKAHEAD(in->sym[0], T_VARIANT)) { + PUSH_TERMINAL(p->stack, lpop(in, T_VARIANT)); + } else { + if (LOOKAHEAD(in->sym[0], T_KEYWORD)) { + PUSH_TERMINAL(p->stack, lpop(in, T_KEYWORD)); + PUSH_TERMINAL(p->stack, lpop(in, '(')); + p21_parameter(p, act); + } else { + PUSH_TERMINAL(p->stack, lpop(in, '(')); + if (LOOKAHEAD(in->sym[0], '(', T_KEYWORD, T_VARIANT)) { + p21_parameter_list(p, act); + } + } + while (in->nsym < 1) { + in->sp = in->cur; + /*!use:re2c re2c:labelprefix='yyb'; + ")" { PUSH_SYMBOL(')'); continue; } */ + } + PUSH_TERMINAL(p->stack, lpop(in, ')')); + } + + if (p->error) + goto err; + + /* user action */ + if (act->parameter_cb) + act->parameter_cb(p, bsp, act->userdata); + + /* reduction */ + if (!p->hold) { + p->stack->items[bsp] = (Symbol){P_PARAMETER}; + drop(p->stack, p->stack->idx_top - bsp - 1); + } + + return; + +err: + report_error(p, "parameter << 14 >>\n"); + if (act->error_cb) act->error_cb(p, bsp, P_PARAMETER); + else default_error_handler(p, bsp, P_PARAMETER); + recover(in, ')', ',', ';'); +} + +void mock_error(P21Parser *, int, uint8_t); +void mock_ud_init(void *); +void mock_ud_exit(void *); +void mock_exchange_file(P21Parser *, int, void *); +void mock_header_start(P21Parser *, int, void *); +void mock_header_entity_list(P21Parser *, int, void *); +void mock_data_section_list(P21Parser *, int, void *); +void mock_data_start(P21Parser *, int, void *); +void mock_header_entity(P21Parser *, int, void *); +void mock_simple_entity_instance(P21Parser *, int, void *); +void mock_complex_entity_instance(P21Parser *, int, void *); +void mock_parameter_list(P21Parser *, int, void *); +void mock_parameter(P21Parser *, int, void *); +void mock_entity_instance_list(P21Parser *, int, void *); +void mock_entity_instance(P21Parser *, int, void *); +void mock_simple_record_list(P21Parser *, int, void *); +void mock_simple_record(P21Parser *, int, void *); +void mock_noop(P21Parser *, int, void *); + +typedef struct { + sqlite3 *db; + sqlite3_stmt *sec_stmt; + sqlite3_stmt *sei_stmt; + sqlite3_stmt *cei_stmt; + sqlite3_stmt *hei_stmt; + int section_idx; +} P21UserData; + +P21UserData mockdata = {0}; + +P21ParserActions mockact = { + .userdata = &mockdata, + .error_cb = mock_error, + .ud_init_cb = mock_ud_init, + .ud_exit_cb = mock_ud_exit, + .header_start_cb = mock_header_start, + .data_start_cb = mock_data_start, + .exchange_file_cb = NULL, + .header_entity_list_cb = NULL, + .data_section_list_cb = NULL, + .header_entity_cb = mock_header_entity, + .simple_entity_instance_cb = mock_simple_entity_instance, + .complex_entity_instance_cb = mock_complex_entity_instance, + .parameter_list_cb = mock_noop, + .parameter_cb = mock_noop, + .entity_instance_list_cb = NULL, + .entity_instance_cb = NULL, + .simple_record_list_cb = mock_noop, + .simple_record_cb = mock_noop +}; + +void mock_error(P21Parser *p, int bsp, uint8_t cxt) { + switch (cxt) { + case P_SIMPLEENTITY: + case P_COMPLEXENTITY: + case P_HEADERENTITY: + dprintf("caught error: '%c'\n", cxt); + p->error = false; + drop(p->stack, p->stack->idx_top - bsp - 1); + break; + default: + p->error = true; + break; + } +} + + +void mock_ud_init(void *d) { + P21UserData *ud = d; + char ddl_sql[] = + "PRAGMA foreign_keys = ON;\n" + "CREATE TABLE entity_enum (type TEXT(1) PRIMARY KEY);\n" + "INSERT INTO entity_enum (type) VALUES ('S'), ('C');\n" + "CREATE TABLE section_enum (type TEXT(1) PRIMARY KEY);\n" + "INSERT INTO section_enum (type) VALUES ('D'), ('H');\n" + + "CREATE TABLE section_table (\n" + " id INTEGER PRIMARY KEY,\n" + " lineno INTEGER NOT NULL,\n" + " section_type TEXT(1) NOT NULL REFERENCES section_enum(type)\n" + ");\n" + + "CREATE TABLE section_headers (\n" + " id INTEGER PRIMARY KEY,\n" + " type_name TEXT COLLATE NOCASE,\n" + " raw_data TEXT NOT NULL,\n" + " lineno INTEGER NOT NULL,\n" + " fk_section INTEGER NOT NULL REFERENCES section_table(id)\n" + ");\n" + + "CREATE TABLE data_table (\n" + " id TEXT PRIMARY KEY,\n" + " type_name TEXT COLLATE NOCASE,\n" + " raw_data TEXT NOT NULL,\n" + " lineno INTEGER NOT NULL,\n" + " entity_type TEXT(1) NOT NULL REFERENCES entity_enum(type),\n" + " fk_section INTEGER NOT NULL REFERENCES section_table(id)\n" + ") WITHOUT ROWID;\n" + + "BEGIN DEFERRED TRANSACTION;"; + + char sei_sql[] = "INSERT INTO data_table VALUES (?,?,?,?,'S',?)"; + char cei_sql[] = "INSERT INTO data_table VALUES (?,NULL,?,?,'C',?)"; + char hei_sql[] = "INSERT INTO section_headers(type_name, raw_data, lineno, fk_section) VALUES (?, ?, ?, ?)"; + int rc; + + rc = sqlite3_open_v2(":memory:", &ud->db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); + + /* TODO: read ddl sql from external file */ + rc = sqlite3_exec(ud->db, ddl_sql, NULL, NULL, NULL); + + rc |= sqlite3_prepare_v3(ud->db, sei_sql, sizeof sei_sql, SQLITE_PREPARE_PERSISTENT, &ud->sei_stmt, NULL); + rc |= sqlite3_prepare_v3(ud->db, cei_sql, sizeof cei_sql, SQLITE_PREPARE_PERSISTENT, &ud->cei_stmt, NULL); + rc |= sqlite3_prepare_v3(ud->db, hei_sql, sizeof hei_sql, SQLITE_PREPARE_PERSISTENT, &ud->hei_stmt, NULL); + + if (rc != SQLITE_OK) + exit(1); + + ud->section_idx = 0; +} + +void mock_ud_exit(void *d) { + P21UserData *ud = d; + int rc; + char ddl_sql[] = + "CREATE INDEX ix_type_name ON data_table(type_name);\n" + "CREATE INDEX ix_entity_type ON data_table(entity_type);\n" + "CREATE INDEX ix_fk_section ON data_table(fk_section);"; + + rc = sqlite3_finalize(ud->sei_stmt); + rc |= sqlite3_finalize(ud->cei_stmt); + rc |= sqlite3_finalize(ud->hei_stmt); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_exec(ud->db, "COMMIT TRANSACTION", NULL, NULL, NULL); + if (rc != SQLITE_OK) goto err; + + /* TODO: benchmark index creation here vs on db init */ + rc = sqlite3_exec(ud->db, ddl_sql, NULL, NULL, NULL); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_close(ud->db); + if (rc != SQLITE_OK) goto err; + + return; +err: + dprintf("db error\n"); + exit(1); +} + +void mock_exchange_file(P21Parser *p, int bsp, void *d) { Stack *s = p->stack; } +void mock_header_start(P21Parser *p, int bsp, void *d) { + char sec_sql[] = "INSERT INTO section_table VALUES(?,?,'H')"; + Stack *s = p->stack; + P21UserData *ud = d; + Symbol *t = s->items + bsp; + sqlite3_stmt *stmt; + int rc; + + rc = sqlite3_prepare_v2(ud->db, sec_sql, sizeof sec_sql, &stmt, NULL); + if (rc != SQLITE_OK) goto err; + + rc |= sqlite3_bind_int(stmt, 1, ++ud->section_idx); + rc |= sqlite3_bind_int(stmt, 2, t->lineno); + if (rc != SQLITE_OK) goto err; + + rc |= sqlite3_step(stmt); + if (rc != SQLITE_DONE) goto err; + + sqlite3_finalize(stmt); + + /* + s->items[bsp] = (Symbol){P_HEADERSECTION}; + drop(s, s->idx_top - bsp - 1); + */ + + return; + +err: + dprintf("db error\n"); + exit(1); +} +void mock_header_entity_list(P21Parser *p, int bsp, void *d) { Stack *s = p->stack; } +void mock_data_section_list(P21Parser *p, int bsp, void *d) { Stack *s = p->stack; } +void mock_data_start(P21Parser *p, int bsp, void *d) { + char sec_sql[] = "INSERT INTO section_table VALUES(?,?,'D')"; + Stack *s = p->stack; + P21UserData *ud = d; + Symbol *t = s->items + bsp; + sqlite3_stmt *stmt; + int rc; + + rc = sqlite3_prepare_v2(ud->db, sec_sql, sizeof sec_sql, &stmt, NULL); + if (rc != SQLITE_OK) goto err; + + rc |= sqlite3_bind_int(stmt, 1, ++ud->section_idx); + rc |= sqlite3_bind_int(stmt, 2, t->lineno); + if (rc != SQLITE_OK) goto err; + + rc |= sqlite3_step(stmt); + if (rc!= SQLITE_DONE) goto err; + + sqlite3_finalize(stmt); + + return; + +err: + dprintf("db error\n"); + exit(1); +} + +void mock_header_entity(P21Parser *p, int bsp, void *d) { + Stack *s = p->stack; + P21UserData *ud = d; + HeaderEntity e = {s->items + bsp, s->items + bsp + 1}; + size_t i, nargs = e.args->n; + unsigned char *basemrk = p->in->basemrk; + ptrdiff_t ep; + int rc; + + /* rewrite (normalise) args member before bind */ + e.args->offset = (e.args + 1)->offset; + e.args->n = (e.args + 1)->n; + for (i = 2, ep = e.args->offset + 1; i < nargs; i++) { + Symbol *t = e.args + i; + if (t->token == '(') t->n = 1; + if (ep != t->offset) memmove(basemrk + ep, basemrk + t->offset, t->n); + ep += t->n; + } + e.args->n = ep - e.args->offset; + + rc = sqlite3_reset(ud->hei_stmt); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_bind_text(ud->hei_stmt, 1, basemrk + e.kw->offset, e.kw->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_text(ud->hei_stmt, 2, basemrk + e.args->offset, e.args->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_int(ud->hei_stmt, 3, e.kw->lineno); + rc |= sqlite3_bind_int(ud->hei_stmt, 4, ud->section_idx); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_step(ud->hei_stmt); + if (rc != SQLITE_DONE) goto err; + + p->hold = false; + return; + +err: + mock_error(p, bsp, P_HEADERENTITY); + dprintf("db error\n"); +} + +void mock_simple_entity_instance(P21Parser *p, int bsp, void *d) { + Stack *s = p->stack; + P21UserData *ud = d; + SimpleEntity e = {s->items + bsp, s->items + bsp + 1, s->items + bsp + 2, s->items + bsp + 3}; + size_t i, nargs = e.args->n; + unsigned char *basemrk = p->in->basemrk; + ptrdiff_t ep; + int rc; + + /* rewrite (normalise) args before bind */ + e.args->offset = (e.args + 1)->offset; + e.args->n = (e.args + 1)->n; + for (i = 2, ep = e.args->offset + e.args->n; i < nargs; i++) { + Symbol *t = e.args + i; + if (t->token == '(') t->n = 1; + if (ep != t->offset) memmove(basemrk + ep, basemrk + t->offset, t->n); + ep += t->n; + } + e.args->n = ep - e.args->offset; + + /* */ + rc = sqlite3_reset(ud->sei_stmt); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_bind_text(ud->sei_stmt, 1, basemrk + e.eid->offset, e.eid->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_text(ud->sei_stmt, 2, basemrk + e.kw->offset, e.kw->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_text(ud->sei_stmt, 3, basemrk + e.args->offset, e.args->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_int(ud->sei_stmt, 4, e.eid->lineno); + rc |= sqlite3_bind_int(ud->sei_stmt, 5, ud->section_idx); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_step(ud->sei_stmt); + if (rc != SQLITE_DONE) goto err; + + p->hold = false; + + return; + +err: + mock_error(p, bsp, P_SIMPLEENTITY); + dprintf("db error\n"); +} + + +void mock_complex_entity_instance(P21Parser *p, int bsp, void *d) { + Stack *s = p->stack; + P21UserData *ud = d; + ComplexEntity e = {s->items + bsp, s->items + bsp + 1, s->items + bsp + 2}; + size_t i, nsubsupers = e.subsupers->n; + unsigned char *basemrk = p->in->basemrk; + ptrdiff_t ep; + int rc; + + /* rewrite (normalise) list before bind */ + for (i = 1, ep = e.subsupers->offset + 1; i < nsubsupers; i++) { + Symbol *t = e.subsupers + i; + if (t->token == '(') t->n = 1; + if (ep != t->offset) memmove(basemrk + ep, basemrk + t->offset, t->n); + ep += t->n; + } + e.subsupers->n = ep - e.subsupers->offset; + + rc = sqlite3_reset(ud->cei_stmt); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_bind_text(ud->cei_stmt, 1, basemrk + e.eid->offset, e.eid->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_text(ud->cei_stmt, 2, basemrk + e.subsupers->offset, e.subsupers->n, SQLITE_TRANSIENT); + rc |= sqlite3_bind_int(ud->cei_stmt, 3, e.eid->lineno); + rc |= sqlite3_bind_int(ud->cei_stmt, 4, ud->section_idx); + if (rc != SQLITE_OK) goto err; + + rc = sqlite3_step(ud->cei_stmt); + if (rc != SQLITE_DONE) goto err; + + p->hold = false; + return; + +err: + mock_error(p, bsp, P_COMPLEXENTITY); + dprintf("db error \n"); +} + +void mock_parameter_list(P21Parser *p, int bsp, void *d) { } +void mock_parameter(P21Parser *p, int bsp, void *d) { } +void mock_entity_instance_list(P21Parser *p, int bsp, void *d) { } +void mock_entity_instance(P21Parser *p, int bsp, void *d) { } +void mock_simple_record_list(P21Parser *p, int bsp, void *d) { } +void mock_simple_record(P21Parser *p, int bsp, void *d) {} + +void mock_noop(P21Parser *p, int bsp, void *d) { + p->hold = true; +} + +int main(char *argv[], int argc) { + const char *paths[] = { + "/home/chorler/projects/src/stepcode/test/p21/test_array_bounds_FAIL1.p21", + "/home/chorler/projects/src/stepcode/test/p21/comments.p21", + "/home/chorler/projects/src/stepcode/test/p21/test_inverse_attr.p21", + "/home/chorler/projects/src/stepcode/test/p21/missing_and_required.p21", + "/home/chorler/projects/src/stepcode/test/p21/test_array_bounds.p21", + "/home/chorler/projects/src/stepcode/test/p21/test_inherit_inverse.p21", + "/home/chorler/projects/src/stepcode/data/ap214e3/as1-oc-214.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/dm1-id-214.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/MAINBODY.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/HEAD_BACK.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/HEAD_FRONT.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/TAIL.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/MAINBODY_FRONT.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/FOOT_BACK_000.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/FOOT_FRONT_000.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/s1-c5-214.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/MAINBODY_BACK.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/HEAD.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/TAIL_TURBINE.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/TAIL_MIDDLE_PART.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/FOOT.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/sg1-c5-214.stp", + "/home/chorler/projects/src/stepcode/data/ap214e3/io1-cm-214.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS7-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS1Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS2-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS1Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS3-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS10Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS2Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS8-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS3Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS4Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS7Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS4Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS10Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS3Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS8Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS4-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS7Mod0-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS2Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS8Mod0-outresult.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS10-out.stp", + "/home/chorler/projects/src/stepcode/data/ap209/ATS1-out.stp" + }; + + P21Parser myp; + P21UserData mydata; + FILE *fp; + memset(&mydata, 0, sizeof mydata); + + for (unsigned int i = 0; i < (sizeof paths / sizeof paths[0]); i++) { + fp = fopen(paths[i], "rb"); + if (!fp) { fprintf(stderr, "failed to read input: %s\n", paths[i]); continue; } + else { fprintf(stderr, "processing: %s\n", paths[i]); } + p21_init(&myp, fp); + p21_parse(&myp, &mockact); + } +} diff --git a/src/exp2python/python/stepcode/cPart21.py b/src/exp2python/python/stepcode/cPart21.py new file mode 100644 index 000000000..6e4b9a697 --- /dev/null +++ b/src/exp2python/python/stepcode/cPart21.py @@ -0,0 +1,586 @@ +# +# STEP Part 21 Parser +# +# Copyright (c) 2020, Christopher HORLER (cshorler@googlemail.com) +# +# All rights reserved. +# +# This file is part of the STEPCODE project. +# +# 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 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 HOLDER 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. + +import logging +import os.path, sqlite3, datetime, tempfile + +import re +import ply.lex as lex +import ply.yacc as yacc +from ply.lex import LexError, TOKEN + +logger = logging.getLogger(__name__) +#logger.addHandler(logging.NullHandler()) + +# assemble catchall regexp +p21_real = r'(?:[+-]*[0-9][0-9]*\.[0-9]*(?:E[+-]*[0-9][0-9]*)?)' +p21_integer = r'(?:[+-]*[0-9][0-9]*)' +p21_string = r"""(?x)(?:' + (?: + # basic string + [][!"*$%&.#+,\-()?/:;<=>@{}|^`~0-9a-zA-Z_ ]|''|\\\\| + # \P\A, \P\B, ... --> iso8859-1, iso8859-2,... applicable to following \S\c directives + \\P[A-I]\\| + # page control directive \S\c + \\S\\[][!"'*$%&.#+,\-()?/:;<=>@{}|^`~0-9a-zA-Z_\\ ]| + # hex string encodings + \\X2\\(?:[0-9A-F]{4})+\\X0\\|\\X4\\(?:[0-9A-F]{8})+\\X0\\| + # hex byte encoding + \\X\\[0-9A-F]{2} + )* +')""" +p21_binary = r'(?:"[0-3][0-9A-F]*")' +p21_enumeration = r'(?:\.[A-Z_][A-Z0-9_]*\.)' +p21_keyword = r'(?:!|)[A-Za-z_][0-9A-Za-z_]*' +p21_eid = r'\#[0-9]+' + +_catchall_types = [p21_real, p21_integer, p21_string, p21_binary, p21_enumeration, + p21_keyword, p21_eid] + +groups_re = re.compile(r"(?P\()|(?P\#[0-9]+)|(?P\))|(?P')") +p21_string_re = re.compile(p21_string) + +def _mkgroups(s): + """used to populate the xref database table""" + stack_idx = 0 + stack_depth = 2 + stack = [set(), set()] + + cp = 0 + while True: + m = groups_re.search(s, cp) + if not m: break + + if m.group('eid'): + stack[stack_idx].add(m.group()) + elif m.group('lparens'): + stack_idx += 1 + if stack_idx == len(stack): + stack_depth += 2 + stack.extend((set(), set())) + elif m.group('rparens'): + stack_idx -= 1 + else: + m = p21_string_re.match(s, m.start()) + + cp = m.end() + + groups = [] + if any(stack): + _stack = filter(bool, stack) + # expand the first level + stack = tuple((x,) for x in next(_stack)) + tuple(_stack) + groups = list(enumerate(stack, 1)) + + return groups + + +base_tokens = ['PART21_START', 'PART21_END', 'HEADER', 'DATA', 'ENDSEC', + 'INTEGER', 'REAL', 'KEYWORD', 'STRING', 'BINARY', 'ENUMERATION', + 'EID', 'RAW'] + +#################################################################################################### +# Lexer +#################################################################################################### +class Lexer(object): + tokens = list(base_tokens) + literals = '()=;,*$' + + states = (('slurp', 'exclusive'), + ('header', 'exclusive'), + ('data', 'exclusive'), + ('raw', 'exclusive'), + ('params', 'exclusive')) + + def __init__(self, debug=False, optimize=False, header_limit=4096): + self.base_tokens = list(base_tokens) + self.schema_dict = {} + self.active_schema = {} + self.header_limit = header_limit + self.lexer = lex.lex(module=self, debug=debug, optimize=optimize, lextab='cl21tab', + debuglog=logger, errorlog=logger) + self.reset() + + def __getattr__(self, name): + if name == 'lineno': + return self.lexer.lineno + elif name == 'lexpos': + return self.lexer.lexpos + else: + raise AttributeError + + def input(self, s): + self.lexer.input(s) + + def reset(self): + self.lexer.lineno = 1 + self.lexer.lvl = 0 + self.lexer.begin('slurp') + + def token(self): + return self.lexer.token() + + def activate_schema(self, schema_name): + if schema_name in self.schema_dict: + self.active_schema = self.schema_dict[schema_name] + else: + raise ValueError('schema not registered') + + def register_schema(self, schema_name, entities): + if schema_name in self.schema_dict: + raise ValueError('schema already registered') + + for k in entities: + if k in self.base_tokens: raise ValueError('schema cannot override base_tokens') + + if isinstance(entities, list): + entities = dict((k, k) for k in entities) + + self.schema_dict[schema_name] = entities + + def t_slurp_error(self, t): + m = re.search(r'(?P/\*)|(ISO-10303-21;)', t.value[:self.header_limit]) + if m: + if m.group('comment'): + t.lexer.skip(m.start()) + else: + t.type = 'PART21_START' + t.value = m.group() + t.lexpos += m.start() + t.lineno += t.value[:m.start()].count('\n') + t.lexer.lexpos += m.end() + t.lexer.begin('INITIAL') + return t + elif len(t.value) < self.header_limit: + t.lexer.skip(len(t.value)) + else: + raise LexError("Scanning error. try increasing lexer header_limit parameter", + "{0}...".format(t.value[0:20])) + + def t_error(self, t): + raise LexError("Scanning error, invalid input", "{0}...".format(t.value[0:20])) + + def t_ANY_COMMENT(self, t): + r'/\*(?:.|\n)*?\*/' + t.lexer.lineno += t.value.count('\n') + + + def t_PART21_END(self, t): + r'END-ISO-10303-21;' + self.lexer.lvl = 0 + self.lexer.begin('slurp') + return t + def t_HEADER(self, t): + r'HEADER;' + t.lexer.push_state('header') + return t + def t_header_data_ENDSEC(self, t): + r'ENDSEC;' + t.lexer.pop_state() + return t + def t_DATA(self, t): + r'DATA\b' + t.lexer.in_header = True + t.lexer.push_state('data') + return t + + + @TOKEN(p21_keyword) + def t_header_KEYWORD(self, t): + return t + def t_header_lparens(self, t): + r'\(' + t.lexer.lexpos -= 1 + t.lexer.push_state('params') + def t_header_rparens(self, t): + r'\)' + t.type = ')' + t.lexer.pop_state() + return t + + + def t_data_lparens(self, t): + r'\(' + if t.lexer.in_header: + t.type = '(' + t.lexer.push_state('header') + else: + t.type = 'RAW' + t.lexer.push_state('raw') + return t + def t_data_header_end(self, t): + r';' + t.type = ';' + t.lexer.in_header = False + return t + @TOKEN(p21_eid) + def t_data_EID(self, t): + return t + @TOKEN(p21_keyword) + def t_data_KEYWORD(self, t): + t.lexer.push_state('raw') + return t + + + def t_params_lparens(self, t): + r'\(' + t.type = 'RAW' + t.lexer.lvl += 1 + return t + def t_params_rparens(self, t): + r'\)' + t.type = 'RAW' + t.lexer.lvl -= 1 + if t.lexer.lvl == 0: + t.lexer.pop_state() + return t + @TOKEN('(?:' + '|'.join(_catchall_types) + r'|(?:[,*$]))+') + def t_params_RAW(self, t): + return t + + + def t_raw_end(self, t): + r';' + t.lexer.pop_state() + t.type = ';' + return t + @TOKEN('(?:' + '|'.join(_catchall_types) + r'|(?:[(),*$]))+') + def t_raw_RAW(self, t): + return t + + + def t_ANY_newline(self, t): + r'\n+' + t.lexer.lineno += len(t.value) + t_ANY_ignore = ' \t\r' + + +#################################################################################################### +# Parser +#################################################################################################### +class Parser(object): + tokens = list(base_tokens) + + def __init__(self, lexer=None, debug=False, tabmodule=None, start=None, optimize=False, + tempdb=False): + # defaults + start_tabs = {'exchange_file': 'cp21tab', 'extract_header': 'cp21hdrtab'} + if start and tabmodule: start_tabs[start] = tabmodule + if not start: start = 'exchange_file' + if start not in start_tabs: raise ValueError('please pass (dedicated) tabmodule') + + self.tempdb = tempdb + self.lexer = lexer if lexer else Lexer() + self.parser = yacc.yacc(debug=debug, module=self, tabmodule=start_tabs[start], start=start, + optimize=optimize, debuglog=logger, errorlog=logger) + + def parse(self, p21_data, db_path=None, **kwargs): + #TODO: will probably need to change this function if the lexer is ever to support t_eof + self.reset(self.tempdb, db_path) + self.lexer.input(p21_data) + + if 'debug' in kwargs: + result = self.parser.parse(lexer=self.lexer, debug=logger, + ** dict((k, v) for k, v in kwargs.items() if k != 'debug')) + else: + result = self.parser.parse(lexer=self.lexer, **kwargs) + return result + + def reset(self, tempdb=None, db_path=None): + self.lexer.reset() + self.initdb(tempdb, db_path) + + def closedb(self): + try: + self.db_cxn.commit() + self.db_cxn.close() + except AttributeError: + pass + + def initdb(self, tempdb, db_path=None): + if tempdb and not db_path: + tm = datetime.datetime.utcnow().isoformat(timespec='seconds').replace(':','-') + db_path = os.path.join(tempfile.mkdtemp(), tm + '_test.db') + elif not db_path: + db_path = ":memory:" + logger.info('db_path: %s', db_path) + self.db_cxn = sqlite3.connect(db_path) + self.db_writer = self.db_cxn.cursor() + self.db_writer.executescript(""" + PRAGMA foreign_keys = ON; + CREATE TABLE entity_enum (type TEXT(1) PRIMARY KEY); + INSERT INTO entity_enum (type) VALUES ('S'), ('C'); + CREATE TABLE section_enum (type TEXT(1) PRIMARY KEY); + INSERT INTO section_enum (type) VALUES ('D'), ('H'); + + CREATE TABLE section_table ( + id INTEGER PRIMARY KEY, + lineno INTEGER NOT NULL, + section_type TEXT(1) NOT NULL REFERENCES section_enum(type) + ); + + CREATE TABLE section_headers ( + id INTEGER PRIMARY KEY, + type_name TEXT COLLATE NOCASE, + raw_data TEXT NOT NULL, + lineno INTEGER NOT NULL, + fk_section INTEGER NOT NULL REFERENCES section_table(id) + ); + + CREATE TABLE data_table ( + id TEXT PRIMARY KEY, + type_name TEXT COLLATE NOCASE, + raw_data TEXT NOT NULL, + lineno INTEGER NOT NULL, + entity_type TEXT(1) NOT NULL REFERENCES entity_enum(type), + fk_section INTEGER NOT NULL REFERENCES section_table(id) + ) WITHOUT ROWID; + + CREATE TABLE data_xref ( + id_from TEXT NOT NULL REFERENCES data_table(id) DEFERRABLE INITIALLY DEFERRED, + id_to TEXT NOT NULL REFERENCES data_table(id), + id_group INTEGER NOT NULL, + PRIMARY KEY (id_from, id_to, id_group) + ) WITHOUT ROWID; + + CREATE INDEX ix_type_name ON data_table(type_name); + CREATE INDEX ix_entity_type ON data_table(entity_type); + CREATE INDEX ix_fk_section ON data_table(fk_section); + CREATE INDEX ix_id_from ON data_xref(id_from); + """) + self.db_cxn.commit() + + def p_exchange_file(self, p): + """exchange_file : PART21_START header_section data_section_list PART21_END""" + self.closedb() + + def p_header_section(self, p): + """header_section : header_start header_entity header_entity header_entity ENDSEC""" + + def p_header_section_with_entity_list(self, p): + """header_section : header_start header_entity header_entity header_entity header_entity_list ENDSEC""" + + def p_header_section_start(self, p): + """header_start : HEADER""" + tmpl = "INSERT INTO section_table(lineno, section_type) VALUES (?,?)" + self.db_writer.execute(tmpl, (p.lineno(1), 'H')) + self.db_writer.execute('SELECT last_insert_rowid();') + (self.sid,) = self.db_writer.fetchone() + + def p_header_entity(self, p): + """header_entity : KEYWORD raw_data ';'""" + tmpl = "INSERT INTO section_headers(type_name, raw_data, lineno, fk_section) VALUES (?, ?, ?, ?)" + self.db_writer.execute(tmpl, (p[1], p[2], p.lineno(1), self.sid)) + + def p_header_entity_list_init(self, p): + """header_entity_list : header_entity""" + + def p_header_entity_list(self, p): + """header_entity_list : header_entity_list header_entity""" + + def p_data_section(self, p): + """data_section : data_start entity_instance_list ENDSEC""" + + def p_data_start(self, p): + """data_start : DATA '(' parameter_list ')' ';'""" + tmpl = "INSERT INTO section_table(lineno, section_type) VALUES (?,?)" + lineno = p.lineno(1) + self.db_writer.execute(tmpl, (lineno, 'D')) + self.db_writer.execute('SELECT last_insert_rowid();') + (self.sid,) = self.db_writer.fetchone() + tmpl = "INSERT INTO section_headers(type_name, raw_data, lineno, fk_section) VALUES (?, ?, ?, ?)" + self.db_writer.executemany(tmpl, [(t, x, lineno, self.sid) for t, x in p[3]]) + + def p_data_start_empty(self, p): + """data_start : DATA '(' ')' ';' + | DATA ';'""" + tmpl = "INSERT INTO section_table(lineno, section_type) VALUES (?,?)" + self.db_writer.execute(tmpl, (p.lineno(1), 'D')) + self.db_writer.execute('SELECT last_insert_rowid();') + (self.sid,) = self.db_writer.fetchone() + + def p_data_section_list_init(self, p): + """data_section_list : data_section""" + + def p_data_section_list(self, p): + """data_section_list : data_section_list data_section""" + + def p_entity_instance_list_init(self, p): + """entity_instance_list : entity_instance""" + + def p_entity_instance_list(self, p): + """entity_instance_list : entity_instance_list entity_instance""" + + def p_entity_instance(self, p): + """entity_instance : simple_entity_instance + | complex_entity_instance""" + + def p_entity_instance_error(self, p): + """entity_instance : EID '=' error ';'""" + logger.error('resyncing parser, check input between lineno %d and %d', p.lineno(2), p.lineno(4)) + + def p_simple_entity_instance(self, p): + """simple_entity_instance : EID '=' KEYWORD raw_data ';'""" + eid = p[1] + tmpl = "INSERT INTO data_table VALUES (?,?,?,?,?,?)" + self.db_writer.execute(tmpl, (p[1], p[3], p[4][1:-1], p.lineno(1), 'S', self.sid)) + tmpl = "INSERT INTO data_xref(id_from, id_to, id_group) VALUES (?, ?, ?)" + xrefs = [(rid, eid, n) for n, x in _mkgroups(p[4]) for rid in x] + self.db_writer.executemany(tmpl, xrefs) + + def p_complex_entity_instance(self, p): + """complex_entity_instance : EID '=' raw_data ';'""" + eid = p[1] + tmpl = "INSERT INTO data_table VALUES (?,NULL,?,?,?,?)" + self.db_writer.execute(tmpl, (p[1], p[3], p.lineno(1), 'C', self.sid)) + tmpl = "INSERT INTO data_xref(id_from, id_to, id_group) VALUES (?, ?, ?)" + xrefs = [(rid, eid, n) for n, x in _mkgroups(p[3]) for rid in x] + self.db_writer.executemany(tmpl, xrefs) + + def p_parameter_list_init(self, p): + """parameter_list : parameter""" + p[0] = [p[1],] + + def p_parameter_list(self, p): + """parameter_list : parameter_list ',' parameter""" + p[0] = p[1] + p[0].append(p[3]) + + def p_typed_parameter(self, p): + """parameter : KEYWORD raw_data""" + p[0] = (p[1], p[2]) + + def p_other_parameter(self, p): + """parameter : raw_data""" + p[0] = (None, p[1]) + + def p_raw_concat(self, p): + """raw_data : raw_data RAW + | RAW""" + try: p[0] = p[1] + p[2] + except IndexError: p[0] = p[1] + + +def debug_lexer(): + import codecs + from os.path import normpath, expanduser + + logging.basicConfig() + logger.setLevel(logging.DEBUG) + + lexer = Lexer(debug=True) + + p = normpath(expanduser('~/projects/src/stepcode/data/ap214e3/s1-c5-214/s1-c5-214.stp')) + with codecs.open(p, 'r', encoding='iso-8859-1') as f: + s = f.read() + lexer.input(s) + while True: + tok = lexer.token() + if not tok: break + logger.debug(tok) + +def debug_parser(): + import codecs + from os.path import normpath, expanduser + + logging.basicConfig() + logger.setLevel(logging.DEBUG) + + parser = Parser(debug=True, tempdb=True) + + logger.info("***** parser debug *****") + p = normpath(expanduser('~/projects/src/stepcode/data/ap214e3/s1-c5-214/s1-c5-214.stp')) + with codecs.open(p, 'r', encoding='iso-8859-1') as f: + s = f.read() + parser.parse(s, debug=1) + + # test reverse lookup + logger.info('***** testing xrefs *****') + tm = datetime.datetime.utcnow().isoformat(timespec='seconds').replace(':', '-') + db_path = os.path.join(tempfile.mkdtemp(), tm + '_xref_test.db') + + parser = Parser() + + p = normpath(expanduser('~/projects/src/stepcode/data/ap214e3/s1-c5-214/s1-c5-214.stp')) + with codecs.open(p, 'r', encoding='iso-8859-1') as f: + s = f.read() + parser.parse(s, db_path=db_path) + + # contrived use case: we're looking for the objects referencing each of these [set] of items + items = [('#53','#93','#133','#173','#191'), ('#174','#192'), ('#193','#196','#195'), ('#1',)] + tmpl = "SELECT id_to FROM data_xref WHERE id_from IN (%s) GROUP BY id_group, id_to HAVING count(id_to) = ?" + with sqlite3.connect(db_path) as db_cxn: + for grp in items: + db_cursor = db_cxn.execute(tmpl % ','.join('?'*len(grp)), grp + (len(grp),)) + for eid in db_cursor: + logger.info('grp: %s, ref: %r', grp, eid) + + logger.info("***** finished *****") + +def test(): + import os, codecs + from os.path import normpath, expanduser + + logging.basicConfig() + logger.setLevel(logging.INFO) + + lexer = Lexer(optimize=True) + parser = Parser(lexer=lexer, optimize=True) + + def parse_check(p): + logger.info("processing {0}".format(p)) + parser.reset() + with codecs.open(p, 'r', encoding='iso-8859-1') as f: + s = f.read() + parser.parse(s) + + logger.info("***** standard test *****") + stepcode_dir = normpath(os.path.expanduser('~/projects/src/stepcode')) + for d, _, files in os.walk(stepcode_dir): + for f in filter(lambda x: x.endswith('.stp'), files): + p = os.path.join(d, f) + try: + parse_check(p) + except LexError: + logger.exception('Lexer failure: {0}'.format(os.path.basename(p))) + + logger.info("***** finished *****") + + +if __name__ == '__main__': + #debug_lexer() + #debug_parser() + test() + diff --git a/src/exp2python/python/SCL/essa_par.py b/src/exp2python/python/stepcode/essa_par.py similarity index 98% rename from src/exp2python/python/SCL/essa_par.py rename to src/exp2python/python/stepcode/essa_par.py index 9c21ee4bd..314a91d4e 100644 --- a/src/exp2python/python/SCL/essa_par.py +++ b/src/exp2python/python/stepcode/essa_par.py @@ -1,4 +1,3 @@ -from __future__ import print_function def process_nested_parent_str(attr_str): ''' The first letter should be a parenthesis diff --git a/src/exp2python/python/stepcode/p21sql.c b/src/exp2python/python/stepcode/p21sql.c new file mode 100644 index 000000000..d13fdf7eb --- /dev/null +++ b/src/exp2python/python/stepcode/p21sql.c @@ -0,0 +1,3512 @@ +/* Generated by re2c 1.0.3 on Mon Apr 6 21:17:12 2020 */ +#line 1 "p21sql.l" +/* +** 2015-08-12 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This SQLite extension implements P21 functions. The interface is +** modeled after MySQL JSON functions: +** +** https://dev.mysql.com/doc/refman/5.7/en/json.html +** +** For the time being, all P21 params are stored as pure text. +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_P21SQL) +#if !defined(SQLITEINT_H) +#include "sqlite3ext.h" +#endif +SQLITE_EXTENSION_INIT1 +#include +#include +#include +#include + +/* Mark a function parameter as unused, to suppress nuisance compiler +** warnings. */ +#ifndef UNUSED_PARAM +# define UNUSED_PARAM(X) (void)(X) +#endif + +#ifndef LARGEST_INT64 +# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) +# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) +#endif + +/* +** Versions of isspace(), isalnum() and isdigit() to which it is safe +** to pass signed char values. +*/ +#ifdef sqlite3Isdigit + /* Use the SQLite core versions if this routine is part of the + ** SQLite amalgamation */ +# define safe_isdigit(x) sqlite3Isdigit(x) +# define safe_isalnum(x) sqlite3Isalnum(x) +# define safe_isxdigit(x) sqlite3Isxdigit(x) +#else + /* Use the standard library for separate compilation */ +#include /* amalgamator: keep */ +# define safe_isdigit(x) isdigit((unsigned char)(x)) +# define safe_isalnum(x) isalnum((unsigned char)(x)) +# define safe_isxdigit(x) isxdigit((unsigned char)(x)) +#endif + +/* +** Growing our own isspace() routine this way is twice as fast as +** the library isspace() function, resulting in a 7% overall performance +** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). +*/ +static const char p21IsSpace[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +#define safe_isspace(x) (p21IsSpace[(unsigned char)x]) + +#ifndef SQLITE_AMALGAMATION + /* Unsigned integer types. These are already defined in the sqliteInt.h, + ** but the definitions need to be repeated for separate compilation. */ + typedef sqlite3_uint64 u64; + typedef unsigned int u32; + typedef unsigned short int u16; + typedef unsigned char u8; +#endif + +/* some C implementations don't have these? (inttypes.h / stdint.h) */ +#ifndef UINT16_WIDTH +# define UINT16_WIDTH 16 +#endif +#ifndef UINT16_MAX +# define UINT16_MAX 65535 +#endif + +/* Objects */ +typedef struct P21String P21String; +typedef struct P21Node P21Node; +typedef struct P21Parse P21Parse; + +/* An instance of this object represents a P21 parameter string +** under construction. Really, this is a generic string accumulator +** that can be and is used to create strings other than JSON (here P21!). +*/ +struct P21String { + sqlite3_context *pCtx; /* Function context - put error messages here */ + char *zBuf; /* Append P21 content here */ + u64 nAlloc; /* Bytes of storage available in zBuf[] */ + u64 nUsed; /* Bytes of zBuf[] currently used */ + u8 bStatic; /* True if zBuf is static space */ + u8 bErr; /* True if an error has been encountered */ + char zSpace[100]; /* Initial static space */ +}; + +#define P21_EMPTY 0x1 /* optional attribute not provided : '$' */ +#define P21_DERIVED 0x2 /* derived attribute not provided : '*' */ +#define P21_ENUMERATION 0x3 /* (also) includes boolean and logical values */ +#define P21_INTEGER 0x4 +#define P21_REAL 0x5 +#define P21_STRING 0x6 +#define P21_BINARY 0x7 +#define P21_EID 0x8 /* entity_instance_name */ +#define P21_LIST 0x9 +#define P21_RECORD 0xA /* simple_record */ + +#define P21_SUBTYPE 80 /* Ascii for "P" */ + + +/* +** Names of the various P21 types: +*/ +static const char * const p21Type[] = { + "", + "empty", "derived", "enumeration", "integer", "real", + "string", "binary", "eid", "list", "record" +}; + +/* Bit values for the P21Node.jnFlag field +*/ +#define PNODE_RAW 0x01 /* Content is raw, not P21 encoded */ +#define PNODE_ESCAPE 0x02 /* Content is text with \ escapes */ +#define PNODE_REMOVE 0x04 /* Do not output */ +#define PNODE_REPLACE 0x08 /* Replace with P21Node.u.iReplace */ +#define PNODE_PATCH 0x10 /* Patch with P21Node.u.pPatch */ +#define PNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */ +#define PNODE_LABEL 0x40 /* Is a label of an object */ + + +/* A single node of parsed P21 params +*/ +struct P21Node { + u8 eType; /* One of the P21_ type values */ + u8 jnFlags; /* P21Node flags */ + u16 n_kw; /* store the KEYWORD length */ + u32 n; /* Bytes of content, or number of sub-nodes */ + union { + const char *zJContent; /* Content for INT, REAL, and STRING */ + u32 iAppend; /* More terms for ARRAY and OBJECT */ + u32 iKey; /* Key for ARRAY objects in p21_tree() */ + u32 iReplace; /* Replacement content for PNODE_REPLACE */ + P21Node *pPatch; /* Node chain of patch for PNODE_PATCH */ + } u; +}; + +/* A completely parsed P21 string +*/ +struct P21Parse { + u32 nNode; /* Number of slots of aNode[] used */ + u32 nAlloc; /* Number of slots of aNode[] allocated */ + P21Node *aNode; /* Array of nodes containing the parse */ + const char *zP21; /* Original P21 string */ + u32 *aUp; /* Index of parent of each node */ + u8 oom; /* Set to true if out of memory */ + u8 nErr; /* Number of errors seen */ + u16 iDepth; /* Nesting depth */ + int nP21; /* Length of the zP21 string in bytes */ + u32 iHold; /* Replace cache line with the lowest iHold value */ +}; + +/* +** Maximum nesting depth of P21 for this implementation. +*/ +#define P21_MAX_DEPTH 20 + +/************************************************************************** +** Utility routines for dealing with P21String objects +**************************************************************************/ + +/* Set the P21String object to an empty string +*/ +static void p21Zero(P21String *p){ + p->zBuf = p->zSpace; + p->nAlloc = sizeof(p->zSpace); + p->nUsed = 0; + p->bStatic = 1; +} + +/* Initialize the P21String object +*/ +static void p21Init(P21String *p, sqlite3_context *pCtx){ + p->pCtx = pCtx; + p->bErr = 0; + p21Zero(p); +} + + +/* Free all allocated memory and reset the P21String object back to its +** initial state. +*/ +static void p21Reset(P21String *p){ + if( !p->bStatic ) sqlite3_free(p->zBuf); + p21Zero(p); +} + + +/* Report an out-of-memory (OOM) condition +*/ +static void p21Oom(P21String *p){ + p->bErr = 1; + sqlite3_result_error_nomem(p->pCtx); + p21Reset(p); +} + +/* Enlarge p->zBuf so that it can hold at least N more bytes. +** Return zero on success. Return non-zero on an OOM error +*/ +static int p21Grow(P21String *p, u32 N){ + u64 nTotal = NnAlloc ? p->nAlloc*2 : p->nAlloc+N+10; + char *zNew; + if( p->bStatic ){ + if( p->bErr ) return 1; + zNew = sqlite3_malloc64(nTotal); + if( zNew==0 ){ + p21Oom(p); + return SQLITE_NOMEM; + } + memcpy(zNew, p->zBuf, (size_t)p->nUsed); + p->zBuf = zNew; + p->bStatic = 0; + }else{ + zNew = sqlite3_realloc64(p->zBuf, nTotal); + if( zNew==0 ){ + p21Oom(p); + return SQLITE_NOMEM; + } + p->zBuf = zNew; + } + p->nAlloc = nTotal; + return SQLITE_OK; +} + +/* Append N bytes from zIn onto the end of the P21String string. +*/ +static void p21AppendRaw(P21String *p, const char *zIn, u32 N){ + if( (N+p->nUsed >= p->nAlloc) && p21Grow(p,N)!=0 ) return; + memcpy(p->zBuf+p->nUsed, zIn, N); + p->nUsed += N; +} + +/* Append formatted text (not to exceed N bytes) to the P21String. +*/ +static void p21Printf(int N, P21String *p, const char *zFormat, ...){ + va_list ap; + if( (p->nUsed + N >= p->nAlloc) && p21Grow(p, N) ) return; + va_start(ap, zFormat); + sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); + va_end(ap); + p->nUsed += (int)strlen(p->zBuf+p->nUsed); +} + +/* Append a single character +*/ +static void p21AppendChar(P21String *p, char c){ + if( p->nUsed>=p->nAlloc && p21Grow(p,1)!=0 ) return; + p->zBuf[p->nUsed++] = c; +} + +/* Append a comma separator to the output buffer, if the previous +** character is not '[' or '{'. +*/ +static void p21AppendSeparator(P21String *p){ + char c; + if( p->nUsed==0 ) return; + c = p->zBuf[p->nUsed-1]; + if( c!='(' ) p21AppendChar(p, ','); +} + +/* Append the N-byte string in zIn to the end of the P21String string +** under construction. Enclose the string in '...' and escape +** any double-quotes or backslash characters contained within the +** string. +*/ +static void p21AppendString(P21String *p, const char *zIn, u32 N){ + u32 i; + if( (N+p->nUsed+2 >= p->nAlloc) && p21Grow(p,N+2)!=0 ) return; + p->zBuf[p->nUsed++] = '\''; + for(i=0; inUsed+N+3-i > p->nAlloc) && p21Grow(p,N+3-i)!=0 ) return; + p->zBuf[p->nUsed++] = '\\'; + }else if( c<=0x1f ){ + static const char aSpecial[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + assert( sizeof(aSpecial)==32 ); + assert( aSpecial['\b']=='b' ); + assert( aSpecial['\f']=='f' ); + assert( aSpecial['\n']=='n' ); + assert( aSpecial['\r']=='r' ); + assert( aSpecial['\t']=='t' ); + if( aSpecial[c] ){ + c = aSpecial[c]; + goto p21_simple_escape; + } + if( (p->nUsed+N+7+i > p->nAlloc) && p21Grow(p,N+7-i)!=0 ) return; + p->zBuf[p->nUsed++] = '\\'; + p->zBuf[p->nUsed++] = 'u'; + p->zBuf[p->nUsed++] = '0'; + p->zBuf[p->nUsed++] = '0'; + p->zBuf[p->nUsed++] = '0' + (c>>4); + c = "0123456789abcdef"[c&0xf]; + } + p->zBuf[p->nUsed++] = c; + } + p->zBuf[p->nUsed++] = '\''; + assert( p->nUsednAlloc ); +} + +/* +** Append a function parameter value to the P21 string under +** construction. +*/ +static void p21AppendValue( + P21String *p, /* Append to this P21 string */ + sqlite3_value *pValue /* Value to append */ +){ + switch( sqlite3_value_type(pValue) ){ + case SQLITE_NULL: { + p21AppendRaw(p, "$", 1); + break; + } + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + const char *z = (const char*)sqlite3_value_text(pValue); + /* TODO: confirm format is valid */ + u32 n = (u32)sqlite3_value_bytes(pValue); + p21AppendRaw(p, z, n); + break; + } + case SQLITE_TEXT: { + const char *z = (const char*)sqlite3_value_text(pValue); + u32 n = (u32)sqlite3_value_bytes(pValue); + if( sqlite3_value_subtype(pValue)==P21_SUBTYPE ){ + p21AppendRaw(p, z, n); + }else{ + p21AppendString(p, z, n); + } + break; + } + default: { + if( p->bErr==0 ){ + sqlite3_result_error(p->pCtx, "P21 cannot hold BLOB values", -1); + p->bErr = 2; + p21Reset(p); + } + break; + } + } +} + + +/* Make the P21 in p the result of the SQL function. +*/ +static void p21Result(P21String *p){ + if( p->bErr==0 ){ + sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, + p->bStatic ? SQLITE_TRANSIENT : sqlite3_free, + SQLITE_UTF8); + p21Zero(p); + } + assert( p->bStatic ); +} + +/************************************************************************** +** Utility routines for dealing with P21Node and P21Parse objects +**************************************************************************/ + +/* +** Return the number of consecutive P21Node slots need to represent +** the parsed P21 at pNode. The minimum answer is 1. For ARRAY and +** OBJECT types, the number might be larger. +** +** Appended elements are not counted. The value returned is the number +** by which the P21Node counter should increment in order to go to the +** next peer value. +*/ +static u32 p21NodeSize(P21Node *pNode){ + return pNode->eType < P21_LIST ? 1 : pNode->n + 1; +} + +/* +** Reclaim all memory allocated by a P21Parse object. But do not +** delete the P21Parse object itself. +*/ +static void p21ParseReset(P21Parse *pParse){ + sqlite3_free(pParse->aNode); + pParse->aNode = 0; + pParse->nNode = 0; + pParse->nAlloc = 0; + sqlite3_free(pParse->aUp); + pParse->aUp = 0; +} + +/* +** Free a P21Parse object that was obtained from sqlite3_malloc(). +*/ +static void p21ParseFree(P21Parse *pParse){ + p21ParseReset(pParse); + sqlite3_free(pParse); +} + +/* +** Convert the P21Node pNode into a pure P21 string and +** append to pOut. Subsubstructure is also included. Return +** the number of P21Node objects that are encoded. +*/ +static void p21RenderNode( + P21Node *pNode, /* The node to render */ + P21String *pOut, /* Write P21 here */ + sqlite3_value **aReplace /* Replacement values */ +){ + if( pNode->jnFlags & (PNODE_REPLACE|PNODE_PATCH) ){ + if( pNode->jnFlags & PNODE_REPLACE ){ + p21AppendValue(pOut, aReplace[pNode->u.iReplace]); + return; + } + pNode = pNode->u.pPatch; + } + switch( pNode->eType ){ + default: { + assert( pNode->eType==P21_EMPTY ); + p21AppendChar(pOut, '$'); + break; + } + case P21_ENUMERATION: { + p21AppendRaw(pOut, pNode->u.zJContent, pNode->n); + break; + } + case P21_DERIVED: { + p21AppendChar(pOut, '*'); + break; + } + case P21_BINARY: { + p21AppendRaw(pOut, pNode->u.zJContent, pNode->n); + break; + } + case P21_EID: { + p21AppendRaw(pOut, pNode->u.zJContent, pNode->n); + break; + } + case P21_STRING: { + if( pNode->jnFlags & PNODE_RAW ){ + p21AppendString(pOut, pNode->u.zJContent, pNode->n); + break; + } + /* Fall through into the next case */ + } + case P21_REAL: + case P21_INTEGER: { + p21AppendRaw(pOut, pNode->u.zJContent, pNode->n); + break; + } + case P21_LIST: { + u32 j = 1; + p21AppendChar(pOut, '('); + for(;;){ + while( j<=pNode->n ){ + if( (pNode[j].jnFlags & PNODE_REMOVE)==0 ){ + p21AppendSeparator(pOut); + p21RenderNode(&pNode[j], pOut, aReplace); + } + j += p21NodeSize(&pNode[j]); + } + if( (pNode->jnFlags & PNODE_APPEND)==0 ) break; + pNode = &pNode[pNode->u.iAppend]; + j = 1; + } + p21AppendChar(pOut, ')'); + break; + } + case P21_RECORD: { + u32 j = 1; + p21AppendRaw(pOut, pNode->u.zJContent, pNode->n_kw); + p21AppendChar(pOut, '('); + for(;;){ + while( j<= pNode->n ){ + if( (pNode[j].jnFlags & PNODE_REMOVE)==0 ){ + p21AppendSeparator(pOut); + p21RenderNode(&pNode[j], pOut, aReplace); + } + j += p21NodeSize(&pNode[j]); + } + if( (pNode->jnFlags & PNODE_APPEND)==0 ) break; + pNode = &pNode[pNode->u.iAppend]; + j = 1; + } + p21AppendChar(pOut, ')'); + break; + } + } +} + +/* +** Return a P21Node and all its descendents as a P21 string. +*/ +static void p21ReturnP21( + P21Node *pNode, /* Node to return */ + sqlite3_context *pCtx, /* Return value for this function */ + sqlite3_value **aReplace /* Array of replacement values */ +){ + P21String s; + p21Init(&s, pCtx); + p21RenderNode(pNode, &s, aReplace); + p21Result(&s); + sqlite3_result_subtype(pCtx, P21_SUBTYPE); +} + +/* +** Translate a single byte of Hex into an integer. +** This routine only works if h really is a valid hexadecimal +** character: 0..9a..fA..F +*/ +static u8 p21HexToInt(int h){ + assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') ); +#ifdef SQLITE_EBCDIC + h += 9*(1&~(h>>4)); +#else + h += 9*(1&(h>>6)); +#endif + return (u8)(h & 0xf); +} + +/* +** Convert a 4-byte hex string into an integer +*/ +static u32 p21HexToInt4(const char *z){ + u32 v; + assert( safe_isxdigit(z[0]) ); + assert( safe_isxdigit(z[1]) ); + assert( safe_isxdigit(z[2]) ); + assert( safe_isxdigit(z[3]) ); + v = (p21HexToInt(z[0])<<12) + + (p21HexToInt(z[1])<<8) + + (p21HexToInt(z[2])<<4) + + p21HexToInt(z[3]); + return v; +} +/* +** Make the P21Node the return value of the function. +*/ +static void p21Return( + P21Node *pNode, /* Node to return */ + sqlite3_context *pCtx, /* Return value for this function */ + sqlite3_value **aReplace /* Array of replacement values */ +){ + switch( pNode->eType ){ + default: { + assert( pNode->eType==P21_EMPTY ); + sqlite3_result_null(pCtx); + break; + } + case P21_DERIVED: { + assert(0); + } + case P21_ENUMERATION: { + assert(0); + } + case P21_BINARY: { + assert(0); + } + case P21_EID: { + sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n, SQLITE_TRANSIENT); + break; + } + case P21_INTEGER: { + sqlite3_int64 i = 0; + const char *z = pNode->u.zJContent; + if( z[0]=='-' ){ z++; } + while( z[0]>='0' && z[0]<='9' ){ + unsigned v = *(z++) - '0'; + if( i>=LARGEST_INT64/10 ){ + if( i>LARGEST_INT64/10 ) goto int_as_real; + if( z[0]>='0' && z[0]<='9' ) goto int_as_real; + if( v==9 ) goto int_as_real; + if( v==8 ){ + if( pNode->u.zJContent[0]=='-' ){ + sqlite3_result_int64(pCtx, SMALLEST_INT64); + goto int_done; + }else{ + goto int_as_real; + } + } + } + i = i*10 + v; + } + if( pNode->u.zJContent[0]=='-' ){ i = -i; } + sqlite3_result_int64(pCtx, i); + int_done: + break; + int_as_real: /* fall through to real */; + } + case P21_REAL: { + double r; +#ifdef SQLITE_AMALGAMATION + const char *z = pNode->u.zJContent; + sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); +#else + r = strtod(pNode->u.zJContent, 0); +#endif + sqlite3_result_double(pCtx, r); + break; + } + case P21_STRING: { +#if 0 /* Never happens because PNODE_RAW is only set by p21_set(), + ** p21_insert() and p21_replace() and those routines do not + ** call p21Return() */ + if( pNode->jnFlags & PNODE_RAW ){ + sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n, + SQLITE_TRANSIENT); + }else +#endif + assert( (pNode->jnFlags & PNODE_RAW)==0 ); + if( (pNode->jnFlags & PNODE_ESCAPE)==0 ){ + /* P21 formatted without any backslash-escapes */ + sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2, + SQLITE_TRANSIENT); + }else{ + /* Translate P21 formatted string into raw text */ + u32 i; + u32 n = pNode->n; + const char *z = pNode->u.zJContent; + char *zOut; + u32 j; + /* TODO: */ + assert(0); + zOut = sqlite3_malloc( n+1 ); + if( zOut==0 ){ + sqlite3_result_error_nomem(pCtx); + break; + } + for(i=1, j=0; i>6)); + zOut[j++] = 0x80 | (v&0x3f); + }else{ + u32 vlo; + if( (v&0xfc00)==0xd800 + && i>18); + zOut[j++] = 0x80 | ((v>>12)&0x3f); + zOut[j++] = 0x80 | ((v>>6)&0x3f); + zOut[j++] = 0x80 | (v&0x3f); + }else{ + zOut[j++] = 0xe0 | (v>>12); + zOut[j++] = 0x80 | ((v>>6)&0x3f); + zOut[j++] = 0x80 | (v&0x3f); + } + } + }else{ + if( c=='b' ){ + c = '\b'; + }else if( c=='f' ){ + c = '\f'; + }else if( c=='n' ){ + c = '\n'; + }else if( c=='r' ){ + c = '\r'; + }else if( c=='t' ){ + c = '\t'; + } + zOut[j++] = c; + } + } + } + zOut[j] = 0; + sqlite3_result_text(pCtx, zOut, j, sqlite3_free); + } + break; + } + case P21_LIST: + case P21_RECORD: { + p21ReturnP21(pNode, pCtx, aReplace); + break; + } + } +} + +/* Forward reference */ +static int p21ParseAddNode(P21Parse*,u32,u32,const char*); + +/* +** A macro to hint to the compiler that a function should not be +** inlined. +*/ +#if defined(__GNUC__) +# define P21_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) && _MSC_VER>=1310 +# define P21_NOINLINE __declspec(noinline) +#else +# define P21_NOINLINE +#endif + + +static P21_NOINLINE int p21ParseAddNodeExpand( + P21Parse *pParse, /* Append the node to this object */ + u32 eType, /* Node type */ + u32 n, /* Content size or sub-node count */ + const char *zContent /* Content */ +){ + u32 nNew; + P21Node *pNew; + assert( pParse->nNode>=pParse->nAlloc ); + if( pParse->oom ) return -1; + nNew = pParse->nAlloc*2 + 10; + pNew = sqlite3_realloc64(pParse->aNode, sizeof(P21Node)*nNew); + if( pNew==0 ){ + pParse->oom = 1; + return -1; + } + pParse->nAlloc = nNew; + pParse->aNode = pNew; + assert( pParse->nNodenAlloc ); + return p21ParseAddNode(pParse, eType, n, zContent); +} + +/* +** Create a new P21Node instance based on the arguments and append that +** instance to the P21Parse. Return the index in pParse->aNode[] of the +** new node, or -1 if a memory allocation fails. +*/ +static int p21ParseAddNode( + P21Parse *pParse, /* Append the node to this object */ + u32 eType, /* Node type */ + u32 n, /* Content size or sub-node count */ + const char *zContent /* Content */ +){ + P21Node *p; + if( pParse->nNode>=pParse->nAlloc ){ + return p21ParseAddNodeExpand(pParse, eType, n, zContent); + } + p = &pParse->aNode[pParse->nNode]; + p->eType = (u8)eType; + p->jnFlags = 0; + p->n = n; + p->u.zJContent = zContent; + return pParse->nNode++; +} + +/* +** Return true if z[] begins with 4 (or more) hexadecimal digits +*/ +static int p21Is4Hex(const char *z){ + int i; + for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0; + return 1; +} + +/* +** Parse P21 value which begins at pParse->zP21[i]. Return the +** index of the first character past the end of the value parsed. +** +** Return negative for a syntax error. +*/ +static int p21ParseValue(P21Parse *pParse, u32 i) { + static int cxtStack[P21_MAX_DEPTH]; + const unsigned char *sp, *cur, *mrk, *tok, *end; + const unsigned char *yyt1; + int *piThis, x; + u32 n; + P21Node *pNode; + + sp = cur = tok = &pParse->zP21[i]; + piThis = cxtStack + pParse->iDepth; + +#line 832 "p21sql.l" + + +start: + + tok = cur; + +#line 822 "p21sql.c" +{ + unsigned char yych; + yych = *cur; + if (yych <= '\r') { + if (yych <= 0x0008) goto yy2; + if (yych <= '\n') goto yy3; + if (yych >= '\r') goto yy3; + } else { + if (yych <= ' ') { + if (yych >= ' ') goto yy3; + } else { + if (yych == '(') goto yy6; + } + } +yy2: +#line 850 "p21sql.l" + { + /* (simple_entity_instance) parameter_list */ + *piThis = p21ParseAddNode(pParse, P21_RECORD, 0, 0); + if (*piThis < 0) return -1; + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params1; + } +#line 848 "p21sql.c" +yy3: + yych = *++cur; + if (yych <= '\f') { + if (yych <= 0x0008) goto yy5; + if (yych <= '\n') goto yy3; + } else { + if (yych <= '\r') goto yy3; + if (yych == ' ') goto yy3; + } +yy5: +#line 838 "p21sql.l" + { + goto start; + } +#line 863 "p21sql.c" +yy6: + ++cur; +#line 841 "p21sql.l" + { + /* (complex_entity_instance) parameter_list */ + *piThis = p21ParseAddNode(pParse, P21_LIST, 0, 0); + if (*piThis < 0) return -1; + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto keywords; + } +#line 876 "p21sql.c" +} +#line 859 "p21sql.l" + + +keywords: + tok = cur; + + +#line 885 "p21sql.c" +{ + unsigned char yych; + yych = *(mrk = cur); + if (yych <= '(') { + if (yych <= '\r') { + if (yych <= 0x0008) goto yy10; + if (yych <= '\n') goto yy11; + if (yych >= '\r') goto yy11; + } else { + if (yych <= 0x001F) goto yy10; + if (yych <= ' ') goto yy11; + if (yych <= '!') goto yy14; + } + } else { + if (yych <= '^') { + if (yych <= ')') goto yy16; + if (yych <= '@') goto yy10; + if (yych <= 'Z') goto yy18; + } else { + if (yych == '`') goto yy10; + if (yych <= 'z') goto yy18; + } + } +yy10: +#line 885 "p21sql.l" + { + /* fix-up and revert to P21_RECORD */ + pNode = pParse->aNode + *(piThis - 1); + pNode->eType = P21_RECORD; + assert(pParse->iDepth == 1); + goto params1; + } +#line 918 "p21sql.c" +yy11: + yych = *++cur; + if (yych <= '\f') { + if (yych <= 0x0008) goto yy13; + if (yych <= '\n') goto yy11; + } else { + if (yych <= '\r') goto yy11; + if (yych == ' ') goto yy11; + } +yy13: +#line 865 "p21sql.l" + { + goto keywords; + } +#line 933 "p21sql.c" +yy14: + yych = *++cur; + if (yych <= '^') { + if (yych <= '@') goto yy15; + if (yych <= 'Z') goto yy18; + } else { + if (yych == '`') goto yy15; + if (yych <= 'z') goto yy18; + } +yy15: + cur = mrk; + goto yy10; +yy16: + ++cur; +#line 877 "p21sql.l" + { + piThis = cxtStack + --pParse->iDepth; + pNode = pParse->aNode + *piThis; + assert(pNode->eType == P21_LIST); + + pNode->n = pParse->nNode - (u32)*piThis - 1; + goto eol; + } +#line 957 "p21sql.c" +yy18: + yych = *++cur; + if (yych <= '(') { + if (yych <= '\r') { + if (yych <= 0x0008) goto yy15; + if (yych <= '\n') { + yyt1 = cur; + goto yy20; + } + if (yych <= '\f') goto yy15; + yyt1 = cur; + } else { + if (yych == ' ') { + yyt1 = cur; + goto yy20; + } + if (yych <= '\'') goto yy15; + yyt1 = cur; + goto yy22; + } + } else { + if (yych <= 'Z') { + if (yych <= '/') goto yy15; + if (yych <= '9') goto yy18; + if (yych <= '@') goto yy15; + goto yy18; + } else { + if (yych <= '_') { + if (yych <= '^') goto yy15; + goto yy18; + } else { + if (yych <= '`') goto yy15; + if (yych <= 'z') goto yy18; + goto yy15; + } + } + } +yy20: + yych = *++cur; + if (yych <= '\r') { + if (yych <= 0x0008) goto yy15; + if (yych <= '\n') goto yy20; + if (yych <= '\f') goto yy15; + goto yy20; + } else { + if (yych <= ' ') { + if (yych <= 0x001F) goto yy15; + goto yy20; + } else { + if (yych != '(') goto yy15; + } + } +yy22: + ++cur; + end = yyt1; +#line 868 "p21sql.l" + { + *piThis = p21ParseAddNode(pParse, P21_RECORD, 0, tok); + if (*piThis < 0) return -1; + pParse->aNode[*piThis].n_kw = (u16)(end - tok); + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params2; + } +#line 1023 "p21sql.c" +} +#line 892 "p21sql.l" + + +params1: + tok = cur; + + +#line 1032 "p21sql.c" +{ + unsigned char yych; + unsigned int yyaccept = 0; + yych = *(mrk = cur); + if (yych <= ')') { + if (yych <= '!') { + if (yych <= '\f') { + if (yych <= 0x0008) goto yy26; + if (yych <= '\n') goto yy27; + } else { + if (yych <= '\r') goto yy27; + if (yych <= 0x001F) goto yy26; + if (yych <= ' ') goto yy27; + goto yy30; + } + } else { + if (yych <= '$') { + if (yych <= '"') goto yy32; + if (yych <= '#') goto yy33; + goto yy34; + } else { + if (yych <= '&') goto yy26; + if (yych <= '\'') goto yy36; + if (yych <= '(') goto yy38; + goto yy40; + } + } + } else { + if (yych <= '9') { + if (yych <= ',') { + if (yych <= '*') goto yy42; + if (yych <= '+') goto yy44; + goto yy46; + } else { + if (yych <= '-') goto yy44; + if (yych <= '.') goto yy48; + if (yych >= '0') goto yy49; + } + } else { + if (yych <= '^') { + if (yych <= '@') goto yy26; + if (yych <= 'Z') goto yy52; + } else { + if (yych == '`') goto yy26; + if (yych <= 'z') goto yy52; + } + } + } +yy26: +#line 959 "p21sql.l" + { + if (pParse->iDepth) --pParse->iDepth; + piThis = cxtStack + pParse->iDepth; + pNode = pParse->aNode + *piThis; + assert(pNode->eType == P21_RECORD); + pNode->n = pParse->nNode - (u32)*piThis - 1; + goto eol; + } +#line 1091 "p21sql.c" +yy27: + yych = *++cur; + if (yych <= '\f') { + if (yych <= 0x0008) goto yy29; + if (yych <= '\n') goto yy27; + } else { + if (yych <= '\r') goto yy27; + if (yych == ' ') goto yy27; + } +yy29: +#line 898 "p21sql.l" + { + goto params1; + } +#line 1106 "p21sql.c" +yy30: + yych = *++cur; + if (yych <= '^') { + if (yych <= '@') goto yy31; + if (yych <= 'Z') goto yy52; + } else { + if (yych == '`') goto yy31; + if (yych <= 'z') goto yy52; + } +yy31: + cur = mrk; + if (yyaccept <= 1) { + if (yyaccept == 0) { + goto yy26; + } else { + goto yy60; + } + } else { + goto yy67; + } +yy32: + yych = *++cur; + if (yych <= '/') goto yy31; + if (yych <= '3') goto yy54; + goto yy31; +yy33: + yych = *++cur; + if (yych <= '/') goto yy31; + if (yych <= '9') goto yy56; + goto yy31; +yy34: + ++cur; +#line 945 "p21sql.l" + { + p21ParseAddNode(pParse, P21_EMPTY, cur - tok, tok); + goto params1; + } +#line 1144 "p21sql.c" +yy36: + yych = *++cur; + if (yych <= 'Z') { + if (yych <= 0x001F) goto yy31; + if (yych == '\'') goto yy59; + goto yy36; + } else { + if (yych <= '\\') { + if (yych <= '[') goto yy31; + goto yy61; + } else { + if (yych <= ']') goto yy31; + if (yych <= '~') goto yy36; + goto yy31; + } + } +yy38: + ++cur; +#line 910 "p21sql.l" + { + *piThis = p21ParseAddNode(pParse, P21_LIST, 0, 0); + if (*piThis < 0) return -1; + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params1; + } +#line 1172 "p21sql.c" +yy40: + ++cur; +#line 953 "p21sql.l" + { + piThis = cxtStack + --pParse->iDepth; + pNode = pParse->aNode + *piThis; + pNode->n = pParse->nNode - (u32)*piThis - 1; + goto params1; + } +#line 1182 "p21sql.c" +yy42: + ++cur; +#line 949 "p21sql.l" + { + p21ParseAddNode(pParse, P21_DERIVED, cur - tok, tok); + goto params1; + } +#line 1190 "p21sql.c" +yy44: + yych = *++cur; + if (yych <= ',') { + if (yych == '+') goto yy44; + goto yy31; + } else { + if (yych <= '-') goto yy44; + if (yych <= '/') goto yy31; + if (yych <= '9') goto yy49; + goto yy31; + } +yy46: + ++cur; +#line 918 "p21sql.l" + { + goto params1; + } +#line 1208 "p21sql.c" +yy48: + yych = *++cur; + if (yych <= '@') goto yy31; + if (yych <= 'Z') goto yy63; + if (yych == '_') goto yy63; + goto yy31; +yy49: + yych = *++cur; + if (yych == '.') goto yy65; + if (yych <= '/') goto yy51; + if (yych <= '9') goto yy49; +yy51: +#line 925 "p21sql.l" + { + p21ParseAddNode(pParse, P21_INTEGER, cur - tok, tok); + goto params1; + } +#line 1226 "p21sql.c" +yy52: + yych = *++cur; + if (yych <= '(') { + if (yych <= '\r') { + if (yych <= 0x0008) goto yy31; + if (yych <= '\n') { + yyt1 = cur; + goto yy68; + } + if (yych <= '\f') goto yy31; + yyt1 = cur; + goto yy68; + } else { + if (yych == ' ') { + yyt1 = cur; + goto yy68; + } + if (yych <= '\'') goto yy31; + yyt1 = cur; + goto yy70; + } + } else { + if (yych <= 'Z') { + if (yych <= '/') goto yy31; + if (yych <= '9') goto yy52; + if (yych <= '@') goto yy31; + goto yy52; + } else { + if (yych <= '_') { + if (yych <= '^') goto yy31; + goto yy52; + } else { + if (yych <= '`') goto yy31; + if (yych <= 'z') goto yy52; + goto yy31; + } + } + } +yy54: + yych = *++cur; + if (yych <= '/') { + if (yych == '"') goto yy72; + goto yy31; + } else { + if (yych <= '9') goto yy54; + if (yych <= '@') goto yy31; + if (yych <= 'F') goto yy54; + goto yy31; + } +yy56: + yych = *++cur; + if (yych <= '/') goto yy58; + if (yych <= '9') goto yy56; +yy58: +#line 941 "p21sql.l" + { + p21ParseAddNode(pParse, P21_EID, cur - tok, tok); + goto params1; + } +#line 1286 "p21sql.c" +yy59: + yyaccept = 1; + yych = *(mrk = ++cur); + if (yych == '\'') goto yy36; +yy60: +#line 929 "p21sql.l" + { + p21ParseAddNode(pParse, P21_STRING, cur - tok, tok); + goto params1; + } +#line 1297 "p21sql.c" +yy61: + yych = *++cur; + if (yych <= 'S') { + if (yych <= '&') { + if (yych <= 0x001F) goto yy31; + goto yy36; + } else { + if (yych <= '\'') goto yy59; + if (yych <= 'R') goto yy36; + goto yy74; + } + } else { + if (yych <= '\\') { + if (yych <= 'Z') goto yy36; + if (yych <= '[') goto yy31; + goto yy61; + } else { + if (yych <= ']') goto yy31; + if (yych <= '~') goto yy36; + goto yy31; + } + } +yy63: + yych = *++cur; + if (yych <= '9') { + if (yych == '.') goto yy75; + if (yych <= '/') goto yy31; + goto yy63; + } else { + if (yych <= 'Z') { + if (yych <= '@') goto yy31; + goto yy63; + } else { + if (yych == '_') goto yy63; + goto yy31; + } + } +yy65: + yyaccept = 2; + yych = *(mrk = ++cur); + if (yych <= '/') goto yy67; + if (yych <= '9') goto yy65; + if (yych == 'E') goto yy77; +yy67: +#line 921 "p21sql.l" + { + p21ParseAddNode(pParse, P21_REAL, cur - tok, tok); + goto params1; + } +#line 1347 "p21sql.c" +yy68: + yych = *++cur; + if (yych <= '\r') { + if (yych <= 0x0008) goto yy31; + if (yych <= '\n') goto yy68; + if (yych <= '\f') goto yy31; + goto yy68; + } else { + if (yych <= ' ') { + if (yych <= 0x001F) goto yy31; + goto yy68; + } else { + if (yych != '(') goto yy31; + } + } +yy70: + ++cur; + end = yyt1; +#line 901 "p21sql.l" + { + *piThis = p21ParseAddNode(pParse, P21_RECORD, 0, tok); + if (*piThis < 0) return -1; + pParse->aNode[*piThis].n_kw = (u16)(end - tok); + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params1; + } +#line 1376 "p21sql.c" +yy72: + ++cur; +#line 933 "p21sql.l" + { + p21ParseAddNode(pParse, P21_BINARY, cur - tok, tok); + goto params1; + } +#line 1384 "p21sql.c" +yy74: + yych = *++cur; + if (yych <= 'Z') { + if (yych <= 0x001F) goto yy31; + if (yych == '\'') goto yy59; + goto yy36; + } else { + if (yych <= '\\') { + if (yych <= '[') goto yy31; + goto yy79; + } else { + if (yych <= ']') goto yy31; + if (yych <= '~') goto yy36; + goto yy31; + } + } +yy75: + ++cur; +#line 937 "p21sql.l" + { + p21ParseAddNode(pParse, P21_ENUMERATION, cur - tok, tok); + goto params1; + } +#line 1408 "p21sql.c" +yy77: + yych = *++cur; + if (yych <= ',') { + if (yych == '+') goto yy77; + goto yy31; + } else { + if (yych <= '-') goto yy77; + if (yych <= '/') goto yy31; + if (yych <= '9') goto yy80; + goto yy31; + } +yy79: + yych = *++cur; + if (yych <= 'S') { + if (yych <= '&') { + if (yych <= 0x001F) goto yy31; + goto yy36; + } else { + if (yych <= '\'') goto yy82; + if (yych <= 'R') goto yy36; + goto yy74; + } + } else { + if (yych <= '\\') { + if (yych <= 'Z') goto yy36; + if (yych <= '[') goto yy31; + goto yy61; + } else { + if (yych <= ']') goto yy31; + if (yych <= '~') goto yy36; + goto yy31; + } + } +yy80: + yych = *++cur; + if (yych <= '/') goto yy67; + if (yych <= '9') goto yy80; + goto yy67; +yy82: + yyaccept = 1; + yych = *(mrk = ++cur); + if (yych <= 'Z') { + if (yych <= 0x001F) goto yy60; + if (yych == '\'') goto yy82; + goto yy36; + } else { + if (yych <= '\\') { + if (yych <= '[') goto yy60; + goto yy61; + } else { + if (yych <= ']') goto yy60; + if (yych <= '~') goto yy36; + goto yy60; + } + } +} +#line 967 "p21sql.l" + + +params2: + tok = cur; + + +#line 1472 "p21sql.c" +{ + unsigned char yych; + unsigned int yyaccept = 0; + yych = *cur; + if (yych <= ')') { + if (yych <= '!') { + if (yych <= '\f') { + if (yych <= 0x0008) goto yy86; + if (yych <= '\n') goto yy87; + } else { + if (yych <= '\r') goto yy87; + if (yych <= 0x001F) goto yy86; + if (yych <= ' ') goto yy87; + goto yy90; + } + } else { + if (yych <= '$') { + if (yych <= '"') goto yy91; + if (yych <= '#') goto yy92; + goto yy93; + } else { + if (yych <= '&') goto yy86; + if (yych <= '\'') goto yy95; + if (yych <= '(') goto yy97; + goto yy99; + } + } + } else { + if (yych <= '9') { + if (yych <= ',') { + if (yych <= '*') goto yy101; + if (yych <= '+') goto yy103; + goto yy105; + } else { + if (yych <= '-') goto yy103; + if (yych <= '.') goto yy107; + if (yych >= '0') goto yy108; + } + } else { + if (yych <= '^') { + if (yych <= '@') goto yy86; + if (yych <= 'Z') goto yy111; + } else { + if (yych == '`') goto yy86; + if (yych <= 'z') goto yy111; + } + } + } +yy86: + cur = mrk; + if (yyaccept == 0) { + goto yy119; + } else { + goto yy126; + } +yy87: + yych = *++cur; + if (yych <= '\f') { + if (yych <= 0x0008) goto yy89; + if (yych <= '\n') goto yy87; + } else { + if (yych <= '\r') goto yy87; + if (yych == ' ') goto yy87; + } +yy89: +#line 973 "p21sql.l" + { + goto params2; + } +#line 1542 "p21sql.c" +yy90: + yych = *++cur; + if (yych <= '^') { + if (yych <= '@') goto yy86; + if (yych <= 'Z') goto yy111; + goto yy86; + } else { + if (yych == '`') goto yy86; + if (yych <= 'z') goto yy111; + goto yy86; + } +yy91: + yych = *++cur; + if (yych <= '/') goto yy86; + if (yych <= '3') goto yy113; + goto yy86; +yy92: + yych = *++cur; + if (yych <= '/') goto yy86; + if (yych <= '9') goto yy115; + goto yy86; +yy93: + ++cur; +#line 1020 "p21sql.l" + { + p21ParseAddNode(pParse, P21_EMPTY, cur - tok, tok); + goto params2; + } +#line 1571 "p21sql.c" +yy95: + yych = *++cur; + if (yych <= 'Z') { + if (yych <= 0x001F) goto yy86; + if (yych == '\'') goto yy118; + goto yy95; + } else { + if (yych <= '\\') { + if (yych <= '[') goto yy86; + goto yy120; + } else { + if (yych <= ']') goto yy86; + if (yych <= '~') goto yy95; + goto yy86; + } + } +yy97: + ++cur; +#line 985 "p21sql.l" + { + *piThis = p21ParseAddNode(pParse, P21_LIST, 0, 0); + if (*piThis < 0) return -1; + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params2; + } +#line 1599 "p21sql.c" +yy99: + ++cur; +#line 1028 "p21sql.l" + { + piThis = cxtStack + --pParse->iDepth; + pNode = pParse->aNode + *piThis; + pNode->n = pParse->nNode - (u32)*piThis - 1; + if (pParse->iDepth > 1) { + goto params2; + } else { + goto keywords; + } + } +#line 1613 "p21sql.c" +yy101: + ++cur; +#line 1024 "p21sql.l" + { + p21ParseAddNode(pParse, P21_DERIVED, cur - tok, tok); + goto params2; + } +#line 1621 "p21sql.c" +yy103: + yych = *++cur; + if (yych <= ',') { + if (yych == '+') goto yy103; + goto yy86; + } else { + if (yych <= '-') goto yy103; + if (yych <= '/') goto yy86; + if (yych <= '9') goto yy108; + goto yy86; + } +yy105: + ++cur; +#line 993 "p21sql.l" + { + goto params2; + } +#line 1639 "p21sql.c" +yy107: + yych = *++cur; + if (yych <= '@') goto yy86; + if (yych <= 'Z') goto yy122; + if (yych == '_') goto yy122; + goto yy86; +yy108: + yych = *++cur; + if (yych == '.') goto yy124; + if (yych <= '/') goto yy110; + if (yych <= '9') goto yy108; +yy110: +#line 1000 "p21sql.l" + { + p21ParseAddNode(pParse, P21_INTEGER, cur - tok, tok); + goto params2; + } +#line 1657 "p21sql.c" +yy111: + yych = *++cur; + if (yych <= '(') { + if (yych <= '\r') { + if (yych <= 0x0008) goto yy86; + if (yych <= '\n') { + yyt1 = cur; + goto yy127; + } + if (yych <= '\f') goto yy86; + yyt1 = cur; + goto yy127; + } else { + if (yych == ' ') { + yyt1 = cur; + goto yy127; + } + if (yych <= '\'') goto yy86; + yyt1 = cur; + goto yy129; + } + } else { + if (yych <= 'Z') { + if (yych <= '/') goto yy86; + if (yych <= '9') goto yy111; + if (yych <= '@') goto yy86; + goto yy111; + } else { + if (yych <= '_') { + if (yych <= '^') goto yy86; + goto yy111; + } else { + if (yych <= '`') goto yy86; + if (yych <= 'z') goto yy111; + goto yy86; + } + } + } +yy113: + yych = *++cur; + if (yych <= '/') { + if (yych == '"') goto yy131; + goto yy86; + } else { + if (yych <= '9') goto yy113; + if (yych <= '@') goto yy86; + if (yych <= 'F') goto yy113; + goto yy86; + } +yy115: + yych = *++cur; + if (yych <= '/') goto yy117; + if (yych <= '9') goto yy115; +yy117: +#line 1016 "p21sql.l" + { + p21ParseAddNode(pParse, P21_EID, cur - tok, tok); + goto params2; + } +#line 1717 "p21sql.c" +yy118: + yyaccept = 0; + yych = *(mrk = ++cur); + if (yych == '\'') goto yy95; +yy119: +#line 1004 "p21sql.l" + { + p21ParseAddNode(pParse, P21_STRING, cur - tok, tok); + goto params2; + } +#line 1728 "p21sql.c" +yy120: + yych = *++cur; + if (yych <= 'S') { + if (yych <= '&') { + if (yych <= 0x001F) goto yy86; + goto yy95; + } else { + if (yych <= '\'') goto yy118; + if (yych <= 'R') goto yy95; + goto yy133; + } + } else { + if (yych <= '\\') { + if (yych <= 'Z') goto yy95; + if (yych <= '[') goto yy86; + goto yy120; + } else { + if (yych <= ']') goto yy86; + if (yych <= '~') goto yy95; + goto yy86; + } + } +yy122: + yych = *++cur; + if (yych <= '9') { + if (yych == '.') goto yy134; + if (yych <= '/') goto yy86; + goto yy122; + } else { + if (yych <= 'Z') { + if (yych <= '@') goto yy86; + goto yy122; + } else { + if (yych == '_') goto yy122; + goto yy86; + } + } +yy124: + yyaccept = 1; + yych = *(mrk = ++cur); + if (yych <= '/') goto yy126; + if (yych <= '9') goto yy124; + if (yych == 'E') goto yy136; +yy126: +#line 996 "p21sql.l" + { + p21ParseAddNode(pParse, P21_REAL, cur - tok, tok); + goto params2; + } +#line 1778 "p21sql.c" +yy127: + yych = *++cur; + if (yych <= '\r') { + if (yych <= 0x0008) goto yy86; + if (yych <= '\n') goto yy127; + if (yych <= '\f') goto yy86; + goto yy127; + } else { + if (yych <= ' ') { + if (yych <= 0x001F) goto yy86; + goto yy127; + } else { + if (yych != '(') goto yy86; + } + } +yy129: + ++cur; + end = yyt1; +#line 976 "p21sql.l" + { + *piThis = p21ParseAddNode(pParse, P21_RECORD, 0, tok); + if (*piThis < 0) return -1; + pParse->aNode[*piThis].n_kw = (u16)(end - tok); + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params2; + } +#line 1807 "p21sql.c" +yy131: + ++cur; +#line 1008 "p21sql.l" + { + p21ParseAddNode(pParse, P21_BINARY, cur - tok, tok); + goto params2; + } +#line 1815 "p21sql.c" +yy133: + yych = *++cur; + if (yych <= 'Z') { + if (yych <= 0x001F) goto yy86; + if (yych == '\'') goto yy118; + goto yy95; + } else { + if (yych <= '\\') { + if (yych <= '[') goto yy86; + goto yy138; + } else { + if (yych <= ']') goto yy86; + if (yych <= '~') goto yy95; + goto yy86; + } + } +yy134: + ++cur; +#line 1012 "p21sql.l" + { + p21ParseAddNode(pParse, P21_ENUMERATION, cur - tok, tok); + goto params2; + } +#line 1839 "p21sql.c" +yy136: + yych = *++cur; + if (yych <= ',') { + if (yych == '+') goto yy136; + goto yy86; + } else { + if (yych <= '-') goto yy136; + if (yych <= '/') goto yy86; + if (yych <= '9') goto yy139; + goto yy86; + } +yy138: + yych = *++cur; + if (yych <= 'S') { + if (yych <= '&') { + if (yych <= 0x001F) goto yy86; + goto yy95; + } else { + if (yych <= '\'') goto yy141; + if (yych <= 'R') goto yy95; + goto yy133; + } + } else { + if (yych <= '\\') { + if (yych <= 'Z') goto yy95; + if (yych <= '[') goto yy86; + goto yy120; + } else { + if (yych <= ']') goto yy86; + if (yych <= '~') goto yy95; + goto yy86; + } + } +yy139: + yych = *++cur; + if (yych <= '/') goto yy126; + if (yych <= '9') goto yy139; + goto yy126; +yy141: + yyaccept = 0; + yych = *(mrk = ++cur); + if (yych <= 'Z') { + if (yych <= 0x001F) goto yy119; + if (yych == '\'') goto yy141; + goto yy95; + } else { + if (yych <= '\\') { + if (yych <= '[') goto yy119; + goto yy120; + } else { + if (yych <= ']') goto yy119; + if (yych <= '~') goto yy95; + goto yy119; + } + } +} +#line 1039 "p21sql.l" + + +eol: + tok = cur; + + +#line 1903 "p21sql.c" +{ + unsigned char yych; + yych = *cur; + if (yych >= 0x0001) goto yy147; + ++cur; +#line 1045 "p21sql.l" + { + return cur - sp; + } +#line 1913 "p21sql.c" +yy147: + ++cur; +#line 1048 "p21sql.l" + { + return -1; + } +#line 1920 "p21sql.c" +} +#line 1051 "p21sql.l" + + +} + + +/* +** Parse a complete P21 string. Return 0 on success or non-zero if there +** are any errors. If an error occurs, free all memory associated with +** pParse. +** +** pParse is uninitialized when this routine is called. +*/ +static int p21Parse( + P21Parse *pParse, /* Initialize and fill this P21Parse object */ + sqlite3_context *pCtx, /* Report errors here */ + const char *zP21 /* Input P21 text to be parsed */ +){ + int i; + memset(pParse, 0, sizeof(*pParse)); + if( zP21==0 ) return 1; + pParse->zP21 = zP21; + i = p21ParseValue(pParse, 0); + if( pParse->oom ) i = -1; + if( i>0 ){ + assert( pParse->iDepth==0 ); + } + if( i<=0 ){ + if( pCtx!=0 ){ + if( pParse->oom ){ + sqlite3_result_error_nomem(pCtx); + }else{ + sqlite3_result_error(pCtx, "malformed P21", -1); + } + } + p21ParseReset(pParse); + return 1; + } + return 0; +} + +/* Mark node i of pParse as being a child of iParent. Call recursively +** to fill in all the descendants of node i. +*/ +static void p21ParseFillInParentage(P21Parse *pParse, u32 i, u32 iParent){ + P21Node *pNode = &pParse->aNode[i]; + u32 j; + pParse->aUp[i] = iParent; + switch( pNode->eType ){ + case P21_RECORD: + case P21_LIST: { + for(j=1; j<=pNode->n; j += p21NodeSize(pNode+j)){ + p21ParseFillInParentage(pParse, i+j, i); + } + break; + } + default: { + break; + } + } +} + +/* +** Compute the parentage of all nodes in a completed parse. +*/ +static int p21ParseFindParents(P21Parse *pParse){ + u32 *aUp; + assert( pParse->aUp==0 ); + aUp = pParse->aUp = sqlite3_malloc64( sizeof(u32)*pParse->nNode ); + if( aUp==0 ){ + pParse->oom = 1; + return SQLITE_NOMEM; + } + p21ParseFillInParentage(pParse, 0, 0); + return SQLITE_OK; +} + +/* +** Magic number used for the P21 parse cache in sqlite3_get_auxdata() +*/ +#define P21_CACHE_ID (-429938) /* First cache entry */ +#define P21_CACHE_SZ 4 /* Max number of cache entries */ + +/* +** Obtain a complete parse of the P21 found in the first argument +** of the argv array. Use the sqlite3_get_auxdata() cache for this +** parse if it is available. If the cache is not available or if it +** is no longer valid, parse the P21 again and return the new parse, +** and also register the new parse so that it will be available for +** future sqlite3_get_auxdata() calls. +*/ +static P21Parse *p21ParseCached( + sqlite3_context *pCtx, + sqlite3_value **argv, + sqlite3_context *pErrCtx +){ + const char *zP21 = (const char*)sqlite3_value_text(argv[0]); + int nP21 = sqlite3_value_bytes(argv[0]); + P21Parse *p; + P21Parse *pMatch = 0; + int iKey; + int iMinKey = 0; + u32 iMinHold = 0xffffffff; + u32 iMaxHold = 0; + if( zP21==0 ) return 0; + for(iKey=0; iKeynP21==nP21 + && memcmp(p->zP21,zP21,nP21)==0 + ){ + p->nErr = 0; + pMatch = p; + }else if( p->iHoldiHold; + iMinKey = iKey; + } + if( p->iHold>iMaxHold ){ + iMaxHold = p->iHold; + } + } + if( pMatch ){ + pMatch->nErr = 0; + pMatch->iHold = iMaxHold+1; + return pMatch; + } + p = sqlite3_malloc64( sizeof(*p) + nP21 + 1 ); + if( p==0 ){ + sqlite3_result_error_nomem(pCtx); + return 0; + } + memset(p, 0, sizeof(*p)); + p->zP21 = (char*)&p[1]; + memcpy((char*)p->zP21, zP21, nP21+1); + if( p21Parse(p, pErrCtx, p->zP21) ){ + sqlite3_free(p); + return 0; + } + p->nP21 = nP21; + p->iHold = iMaxHold+1; + sqlite3_set_auxdata(pCtx, P21_CACHE_ID+iMinKey, p, + (void(*)(void*))p21ParseFree); + return (P21Parse*)sqlite3_get_auxdata(pCtx, P21_CACHE_ID+iMinKey); +} + +/* +** Compare the OBJECT label at pNode against zKey,nKey. Return true on +** a match. +*/ +static int p21LabelCompare(P21Node *pNode, const char *zKey, u32 nKey){ + if( pNode->jnFlags & PNODE_RAW ){ + if( pNode->n!=nKey ) return 0; + return strncmp(pNode->u.zJContent, zKey, nKey)==0; + }else{ + if( pNode->n!=nKey+2 ) return 0; + return strncmp(pNode->u.zJContent+1, zKey, nKey)==0; + } +} + +/* forward declaration */ +static P21Node *p21LookupAppend(P21Parse*,const char*,int*,const char**); + +/* +** Search along zPath to find the node specified. Return a pointer +** to that node, or NULL if zPath is malformed or if there is no such +** node. +** +** If pApnd!=0, then try to append new nodes to complete zPath if it is +** possible to do so and if no existing node corresponds to zPath. If +** new nodes are appended *pApnd is set to 1. +*/ +static P21Node *p21LookupStep( + P21Parse *pParse, /* The P21 to search */ + u32 iRoot, /* Begin the search at this node */ + const char *zPath, /* The path to search */ + int *pApnd, /* Append nodes to complete path if not NULL */ + const char **pzErr /* Make *pzErr point to any syntax error in zPath */ +){ + u32 i, j, nKey; + const char *zKey; + P21Node *pRoot = &pParse->aNode[iRoot]; + if( zPath[0]==0 ) return pRoot; + if( pRoot->jnFlags & PNODE_REPLACE ) return 0; + if( zPath[0]=='.' ){ + if( pRoot->eType!=P21_RECORD ) return 0; + zPath++; + if( zPath[0]=='"' ){ + zKey = zPath + 1; + for(i=1; zPath[i] && zPath[i]!='"'; i++){} + nKey = i-1; + if( zPath[i] ){ + i++; + }else{ + *pzErr = zPath; + return 0; + } + }else{ + zKey = zPath; + for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} + nKey = i; + } + if( nKey==0 ){ + *pzErr = zPath; + return 0; + } + j = 1; + for(;;){ + while( j<=pRoot->n ){ + if( p21LabelCompare(pRoot+j, zKey, nKey) ){ + return p21LookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr); + } + j++; + j += p21NodeSize(&pRoot[j]); + } + if( (pRoot->jnFlags & PNODE_APPEND)==0 ) break; + iRoot += pRoot->u.iAppend; + pRoot = &pParse->aNode[iRoot]; + j = 1; + } + if( pApnd ){ + u32 iStart, iLabel; + P21Node *pNode; + iStart = p21ParseAddNode(pParse, P21_RECORD, 2, 0); + iLabel = p21ParseAddNode(pParse, P21_STRING, nKey, zKey); + zPath += i; + pNode = p21LookupAppend(pParse, zPath, pApnd, pzErr); + if( pParse->oom ) return 0; + if( pNode ){ + pRoot = &pParse->aNode[iRoot]; + pRoot->u.iAppend = iStart - iRoot; + pRoot->jnFlags |= PNODE_APPEND; + pParse->aNode[iLabel].jnFlags |= PNODE_RAW; + } + return pNode; + } + }else if( zPath[0]=='[' ){ + i = 0; + j = 1; + while( safe_isdigit(zPath[j]) ){ + i = i*10 + zPath[j] - '0'; + j++; + } + if( j<2 || zPath[j]!=']' ){ + if( zPath[1]=='#' ){ + P21Node *pBase = pRoot; + int iBase = iRoot; + if( pRoot->eType!=P21_LIST && pRoot->eType!=P21_RECORD) return 0; + for(;;){ + while( j<=pBase->n ){ + if( (pBase[j].jnFlags & PNODE_REMOVE)==0 ) i++; + j += p21NodeSize(&pBase[j]); + } + if( (pBase->jnFlags & PNODE_APPEND)==0 ) break; + iBase += pBase->u.iAppend; + pBase = &pParse->aNode[iBase]; + j = 1; + } + j = 2; + if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){ + unsigned int x = 0; + j = 3; + do{ + x = x*10 + zPath[j] - '0'; + j++; + }while( safe_isdigit(zPath[j]) ); + if( x>i ) return 0; + i -= x; + } + if( zPath[j]!=']' ){ + *pzErr = zPath; + return 0; + } + }else{ + *pzErr = zPath; + return 0; + } + } + if( pRoot->eType!=P21_LIST && pRoot->eType!=P21_RECORD ) return 0; + zPath += j + 1; + j = 1; + for(;;){ + while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & PNODE_REMOVE)!=0) ){ + if( (pRoot[j].jnFlags & PNODE_REMOVE)==0 ) i--; + j += p21NodeSize(&pRoot[j]); + } + if( (pRoot->jnFlags & PNODE_APPEND)==0 ) break; + iRoot += pRoot->u.iAppend; + pRoot = &pParse->aNode[iRoot]; + j = 1; + } + if( j<=pRoot->n ){ + return p21LookupStep(pParse, iRoot+j, zPath, pApnd, pzErr); + } + if( i==0 && pApnd ){ + u32 iStart; + P21Node *pNode; + iStart = p21ParseAddNode(pParse, P21_LIST, 1, 0); + pNode = p21LookupAppend(pParse, zPath, pApnd, pzErr); + if( pParse->oom ) return 0; + if( pNode ){ + pRoot = &pParse->aNode[iRoot]; + pRoot->u.iAppend = iStart - iRoot; + pRoot->jnFlags |= PNODE_APPEND; + } + return pNode; + } + }else{ + *pzErr = zPath; + } + return 0; +} + +/* +** Append content to pParse that will complete zPath. Return a pointer +** to the inserted node, or return NULL if the append fails. +*/ +static P21Node *p21LookupAppend( + P21Parse *pParse, /* Append content to the P21 parse */ + const char *zPath, /* Description of content to append */ + int *pApnd, /* Set this flag to 1 */ + const char **pzErr /* Make this point to any syntax error */ +){ + *pApnd = 1; + if( zPath[0]==0 ){ + p21ParseAddNode(pParse, P21_EMPTY, 0, 0); + return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1]; + } + if( zPath[0]=='.' ){ + p21ParseAddNode(pParse, P21_RECORD, 0, 0); + }else if( strncmp(zPath,"[0]",3)==0 ){ + p21ParseAddNode(pParse, P21_LIST, 0, 0); + }else{ + return 0; + } + if( pParse->oom ) return 0; + return p21LookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr); +} + +/* +** Return the text of a syntax error message on a P21 path. Space is +** obtained from sqlite3_malloc(). +*/ +static char *p21PathSyntaxError(const char *zErr){ + return sqlite3_mprintf("P21 path error near '%q'", zErr); +} + +/* +** Do a node lookup using zPath. Return a pointer to the node on success. +** Return NULL if not found or if there is an error. +** +** On an error, write an error message into pCtx and increment the +** pParse->nErr counter. +** +** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if +** nodes are appended. +*/ +static P21Node *p21Lookup( + P21Parse *pParse, /* The P21 to search */ + const char *zPath, /* The path to search */ + int *pApnd, /* Append nodes to complete path if not NULL */ + sqlite3_context *pCtx /* Report errors here, if not NULL */ +){ + const char *zErr = 0; + P21Node *pNode = 0; + char *zMsg; + + if( zPath==0 ) return 0; + if( zPath[0]!='$' ){ + zErr = zPath; + goto lookup_err; + } + zPath++; + pNode = p21LookupStep(pParse, 0, zPath, pApnd, &zErr); + if( zErr==0 ) return pNode; + +lookup_err: + pParse->nErr++; + assert( zErr!=0 && pCtx!=0 ); + zMsg = p21PathSyntaxError(zErr); + if( zMsg ){ + sqlite3_result_error(pCtx, zMsg, -1); + sqlite3_free(zMsg); + }else{ + sqlite3_result_error_nomem(pCtx); + } + return 0; +} + + +/* +** Report the wrong number of arguments for p21_insert(), p21_replace() +** or p21_set(). +*/ +static void p21WrongNumArgs( + sqlite3_context *pCtx, + const char *zFuncName +){ + char *zMsg = sqlite3_mprintf("p21_%s() needs an odd number of arguments", + zFuncName); + sqlite3_result_error(pCtx, zMsg, -1); + sqlite3_free(zMsg); +} + +/* +** Mark all NULL entries in the Object passed in as PNODE_REMOVE. +*/ +static void p21RemoveAllNulls(P21Node *pNode){ + int i, n; + assert( pNode->eType==P21_RECORD ); + n = pNode->n; + for(i=2; i<=n; i += p21NodeSize(&pNode[i])+1){ + switch( pNode[i].eType ){ + case P21_EMPTY: + pNode[i].jnFlags |= PNODE_REMOVE; + break; + case P21_RECORD: + p21RemoveAllNulls(&pNode[i]); + break; + } + } +} + + +/**************************************************************************** +** SQL functions used for testing and debugging +****************************************************************************/ + +#ifdef SQLITE_DEBUG +/* +** The p21_parse(P21) function returns a string which describes +** a parse of the P21 provided. Or it returns NULL if P21 is not +** well-formed. +*/ +static void p21ParseFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21String s; /* Output string - not real P21 */ + P21Parse x; /* The parse */ + u32 i; + + assert( argc==1 ); + if( p21Parse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + p21ParseFindParents(&x); + p21Init(&s, ctx); + for(i=0; inNode ); + if( argc==2 ){ + const char *zPath = (const char*)sqlite3_value_text(argv[1]); + pNode = p21Lookup(p, zPath, 0, ctx); + }else{ + pNode = p->aNode; + } + if( pNode==0 ){ + return; + } + if( pNode->eType==P21_LIST ){ + assert( (pNode->jnFlags & PNODE_APPEND)==0 ); + for(i=1; i<=pNode->n; n++){ + i += p21NodeSize(&pNode[i]); + } + } + sqlite3_result_int64(ctx, n); +} + +/* +** p21_extract(P21, PATH, ...) +** +** Return the element described by PATH. Return NULL if there is no +** PATH element. If there are multiple PATHs, then return a P21 array +** with the result from each path. Throw an error if the P21 or any PATH +** is malformed. +*/ +static void p21ExtractFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse *p; /* The parse */ + P21Node *pNode; + const char *zPath; + P21String jx; + int i; + + if( argc<2 ) return; + p = p21ParseCached(ctx, argv, ctx); + if( p==0 ) return; + p21Init(&jx, ctx); + p21AppendChar(&jx, '['); + for(i=1; inErr ) break; + if( argc>2 ){ + p21AppendSeparator(&jx); + if( pNode ){ + p21RenderNode(pNode, &jx, 0); + }else{ + p21AppendRaw(&jx, "null", 4); + } + }else if( pNode ){ + p21Return(pNode, ctx, 0); + } + } + if( argc>2 && i==argc ){ + p21AppendChar(&jx, ']'); + p21Result(&jx); + sqlite3_result_subtype(ctx, P21_SUBTYPE); + } + p21Reset(&jx); +} + +#if 0 +/* TODO: a MergeRecord function could be useful + */ +static P21Node *p21MergePatch( + P21Parse *pParse, /* The P21 parser that contains the TARGET */ + u32 iTarget, /* Node of the TARGET in pParse */ + P21Node *pPatch /* The PATCH */ +){ + u32 i, j; + u32 iRoot; + P21Node *pTarget; + if( pPatch->eType!=P21_RECORD ){ + return pPatch; + } + assert( iTargetnNode ); + pTarget = &pParse->aNode[iTarget]; + assert( (pPatch->jnFlags & PNODE_APPEND)==0 ); + if( pTarget->eType!=P21_RECORD ){ + p21RemoveAllNulls(pPatch); + return pPatch; + } + iRoot = iTarget; + for(i=1; in; i += p21NodeSize(&pPatch[i+1])+1){ + u32 nKey; + const char *zKey; + assert( pPatch[i].eType==P21_STRING ); + assert( pPatch[i].jnFlags & PNODE_LABEL ); + nKey = pPatch[i].n; + zKey = pPatch[i].u.zJContent; + assert( (pPatch[i].jnFlags & PNODE_RAW)==0 ); + for(j=1; jn; j += p21NodeSize(&pTarget[j+1])+1 ){ + assert( pTarget[j].eType==P21_STRING ); + assert( pTarget[j].jnFlags & PNODE_LABEL ); + assert( (pPatch[i].jnFlags & PNODE_RAW)==0 ); + if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){ + if( pTarget[j+1].jnFlags & (PNODE_REMOVE|PNODE_PATCH) ) break; + if( pPatch[i+1].eType==P21_EMPTY ){ + pTarget[j+1].jnFlags |= PNODE_REMOVE; + }else{ + P21Node *pNew = p21MergePatch(pParse, iTarget+j+1, &pPatch[i+1]); + if( pNew==0 ) return 0; + pTarget = &pParse->aNode[iTarget]; + if( pNew!=&pTarget[j+1] ){ + pTarget[j+1].u.pPatch = pNew; + pTarget[j+1].jnFlags |= PNODE_PATCH; + } + } + break; + } + } + if( j>=pTarget->n && pPatch[i+1].eType!=P21_EMPTY ){ + int iStart, iPatch; + iStart = p21ParseAddNode(pParse, P21_RECORD, 2, 0); + p21ParseAddNode(pParse, P21_STRING, nKey, zKey); + iPatch = p21ParseAddNode(pParse, P21_TRUE, 0, 0); + if( pParse->oom ) return 0; + p21RemoveAllNulls(pPatch); + pTarget = &pParse->aNode[iTarget]; + pParse->aNode[iRoot].jnFlags |= PNODE_APPEND; + pParse->aNode[iRoot].u.iAppend = iStart - iRoot; + iRoot = iStart; + pParse->aNode[iPatch].jnFlags |= PNODE_PATCH; + pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; + } + } + return pTarget; +} + + +/* +** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a P21 +** object that is the result of running the RFC 7396 MergePatch() algorithm +** on the two arguments. +*/ +static void p21PatchFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse x; /* The P21 that is being patched */ + P21Parse y; /* The patch */ + P21Node *pResult; /* The result of the merge */ + + UNUSED_PARAM(argc); + if( p21Parse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + if( p21Parse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ + p21ParseReset(&x); + return; + } + pResult = p21MergePatch(&x, 0, y.aNode); + assert( pResult!=0 || x.oom ); + if( pResult ){ + p21ReturnP21(pResult, ctx, 0); + }else{ + sqlite3_result_error_nomem(ctx); + } + p21ParseReset(&x); + p21ParseReset(&y); +} +#endif + +/* +** Implementation of the p21_object(NAME,VALUE,...) function. Return a P21 +** object that contains all name/value given in arguments. Or if any name +** is not a string or if any value is a BLOB, throw an error. +*/ +static void p21ObjectFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + int i; + P21String jx; + const char *z; + u32 n; + + if( argc&1 ){ + sqlite3_result_error(ctx, "p21_object() requires an even number " + "of arguments", -1); + return; + } + p21Init(&jx, ctx); + p21AppendChar(&jx, '{'); + for(i=0; ijnFlags |= PNODE_REMOVE; + } + if( (x.aNode[0].jnFlags & PNODE_REMOVE)==0 ){ + p21ReturnP21(x.aNode, ctx, 0); + } +remove_done: + p21ParseReset(&x); +} + +/* +** p21_replace(P21, PATH, VALUE, ...) +** +** Replace the value at PATH with VALUE. If PATH does not already exist, +** this routine is a no-op. If P21 or PATH is malformed, throw an error. +*/ +static void p21ReplaceFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse x; /* The parse */ + P21Node *pNode; + const char *zPath; + u32 i; + + if( argc<1 ) return; + if( (argc&1)==0 ) { + p21WrongNumArgs(ctx, "replace"); + return; + } + if( p21Parse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + assert( x.nNode ); + for(i=1; i<(u32)argc; i+=2){ + zPath = (const char*)sqlite3_value_text(argv[i]); + pNode = p21Lookup(&x, zPath, 0, ctx); + if( x.nErr ) goto replace_err; + if( pNode ){ + pNode->jnFlags |= (u8)PNODE_REPLACE; + pNode->u.iReplace = i + 1; + } + } + if( x.aNode[0].jnFlags & PNODE_REPLACE ){ + sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); + }else{ + p21ReturnP21(x.aNode, ctx, argv); + } +replace_err: + p21ParseReset(&x); +} + +/* +** p21_set(P21, PATH, VALUE, ...) +** +** Set the value at PATH to VALUE. Create the PATH if it does not already +** exist. Overwrite existing values that do exist. +** If P21 or PATH is malformed, throw an error. +** +** p21_insert(P21, PATH, VALUE, ...) +** +** Create PATH and initialize it to VALUE. If PATH already exists, this +** routine is a no-op. If P21 or PATH is malformed, throw an error. +*/ +static void p21SetFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse x; /* The parse */ + P21Node *pNode; + const char *zPath; + u32 i; + int bApnd; + int bIsSet = *(int*)sqlite3_user_data(ctx); + + if( argc<1 ) return; + if( (argc&1)==0 ) { + p21WrongNumArgs(ctx, bIsSet ? "set" : "insert"); + return; + } + if( p21Parse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + assert( x.nNode ); + for(i=1; i<(u32)argc; i+=2){ + zPath = (const char*)sqlite3_value_text(argv[i]); + bApnd = 0; + pNode = p21Lookup(&x, zPath, &bApnd, ctx); + if( x.oom ){ + sqlite3_result_error_nomem(ctx); + goto p21SetDone; + }else if( x.nErr ){ + goto p21SetDone; + }else if( pNode && (bApnd || bIsSet) ){ + pNode->jnFlags |= (u8)PNODE_REPLACE; + pNode->u.iReplace = i + 1; + } + } + if( x.aNode[0].jnFlags & PNODE_REPLACE ){ + sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); + }else{ + p21ReturnP21(x.aNode, ctx, argv); + } +p21SetDone: + p21ParseReset(&x); +} + +/* +** p21_type(P21) +** p21_type(P21, PATH) +** +** Return the top-level "type" of a P21 string. Throw an error if +** either the P21 or PATH inputs are not well-formed. +*/ +static void p21TypeFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse *p; /* The parse */ + const char *zPath; + P21Node *pNode; + + p = p21ParseCached(ctx, argv, ctx); + if( p==0 ) return; + if( argc==2 ){ + zPath = (const char*)sqlite3_value_text(argv[1]); + pNode = p21Lookup(p, zPath, 0, ctx); + }else{ + pNode = p->aNode; + } + if( pNode ){ + sqlite3_result_text(ctx, p21Type[pNode->eType], -1, SQLITE_STATIC); + } +} + +/* +** p21_valid(P21) +** +** Return 1 if P21 is a well-formed P21 string according to RFC-7159. +** Return 0 otherwise. +*/ +static void p21ValidFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse *p; /* The parse */ + UNUSED_PARAM(argc); + p = p21ParseCached(ctx, argv, 0); + sqlite3_result_int(ctx, p!=0); +} + + +/**************************************************************************** +** Aggregate SQL function implementations +****************************************************************************/ +/* +** p21_group_array(VALUE) +** +** Return a P21 array composed of all values in the aggregate. +*/ +static void p21ArrayStep( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21String *pStr; + UNUSED_PARAM(argc); + pStr = (P21String*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); + if( pStr ){ + if( pStr->zBuf==0 ){ + p21Init(pStr, ctx); + p21AppendChar(pStr, '['); + }else if( pStr->nUsed>1 ){ + p21AppendChar(pStr, ','); + pStr->pCtx = ctx; + } + p21AppendValue(pStr, argv[0]); + } +} +static void p21ArrayCompute(sqlite3_context *ctx, int isFinal){ + P21String *pStr; + pStr = (P21String*)sqlite3_aggregate_context(ctx, 0); + if( pStr ){ + pStr->pCtx = ctx; + p21AppendChar(pStr, ']'); + if( pStr->bErr ){ + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); + assert( pStr->bStatic ); + }else if( isFinal ){ + sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, + pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic = 1; + }else{ + sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); + pStr->nUsed--; + } + }else{ + sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); + } + sqlite3_result_subtype(ctx, P21_SUBTYPE); +} +static void p21ArrayValue(sqlite3_context *ctx){ + p21ArrayCompute(ctx, 0); +} +static void p21ArrayFinal(sqlite3_context *ctx){ + p21ArrayCompute(ctx, 1); +} + +#ifndef SQLITE_OMIT_WINDOWFUNC +/* +** This method works for both p21_group_array() and p21_group_object(). +** It works by removing the first element of the group by searching forward +** to the first comma (",") that is not within a string and deleting all +** text through that comma. +*/ +static void p21GroupInverse( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + unsigned int i; + int inStr = 0; + int nNest = 0; + char *z; + char c; + P21String *pStr; + UNUSED_PARAM(argc); + UNUSED_PARAM(argv); + pStr = (P21String*)sqlite3_aggregate_context(ctx, 0); +#ifdef NEVER + /* pStr is always non-NULL since p21ArrayStep() or p21ObjectStep() will + ** always have been called to initalize it */ + if( NEVER(!pStr) ) return; +#endif + z = pStr->zBuf; + for(i=1; (c = z[i])!=',' || inStr || nNest; i++){ + if( i>=pStr->nUsed ){ + pStr->nUsed = 1; + return; + } + if( c=='"' ){ + inStr = !inStr; + }else if( c=='\\' ){ + i++; + }else if( !inStr ){ + if( c=='{' || c=='[' ) nNest++; + if( c=='}' || c==']' ) nNest--; + } + } + pStr->nUsed -= i; + memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1); +} +#else +# define p21GroupInverse 0 +#endif + + +/* +** p21_group_obj(NAME,VALUE) +** +** Return a P21 object composed of all names and values in the aggregate. +*/ +static void p21ObjectStep( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21String *pStr; + const char *z; + u32 n; + UNUSED_PARAM(argc); + pStr = (P21String*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); + if( pStr ){ + if( pStr->zBuf==0 ){ + p21Init(pStr, ctx); + p21AppendChar(pStr, '{'); + }else if( pStr->nUsed>1 ){ + p21AppendChar(pStr, ','); + pStr->pCtx = ctx; + } + z = (const char*)sqlite3_value_text(argv[0]); + n = (u32)sqlite3_value_bytes(argv[0]); + p21AppendString(pStr, z, n); + p21AppendChar(pStr, ':'); + p21AppendValue(pStr, argv[1]); + } +} +static void p21ObjectCompute(sqlite3_context *ctx, int isFinal){ + P21String *pStr; + pStr = (P21String*)sqlite3_aggregate_context(ctx, 0); + if( pStr ){ + p21AppendChar(pStr, '}'); + if( pStr->bErr ){ + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); + assert( pStr->bStatic ); + }else if( isFinal ){ + sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, + pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic = 1; + }else{ + sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); + pStr->nUsed--; + } + }else{ + sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); + } + sqlite3_result_subtype(ctx, P21_SUBTYPE); +} +static void p21ObjectValue(sqlite3_context *ctx){ + p21ObjectCompute(ctx, 0); +} +static void p21ObjectFinal(sqlite3_context *ctx){ + p21ObjectCompute(ctx, 1); +} + + + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/**************************************************************************** +** The p21_each virtual table +****************************************************************************/ +typedef struct P21EachCursor P21EachCursor; +struct P21EachCursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + u32 iRowid; /* The rowid */ + u32 iBegin; /* The first node of the scan */ + u32 i; /* Index in sParse.aNode[] of current row */ + u32 iEnd; /* EOF when i equals or exceeds this value */ + u8 eType; /* Type of top-level element */ + char *zP21; /* Input P21 */ + char *zRoot; /* Path by which to filter zP21 */ + P21Parse sParse; /* Parse of the input P21 */ +}; + +/* Constructor for the p21_each virtual table */ +static int p21EachConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + sqlite3_vtab *pNew; + int rc; + +/* Column numbers */ +#define PEACH_KEY 0 +#define PEACH_VALUE 1 +#define PEACH_TYPE 2 +#define PEACH_ATOM 3 +#define PEACH_ID 4 +#define PEACH_PARENT 5 +#define PEACH_FULLKEY 6 +#define PEACH_PATH 7 +/* The xBestIndex method assumes that the P21 and ROOT columns are +** the last two columns in the table. Should this ever changes, be +** sure to update the xBestIndex method. */ +#define PEACH_P21 8 +#define PEACH_ROOT 9 + + UNUSED_PARAM(pzErr); + UNUSED_PARAM(argv); + UNUSED_PARAM(argc); + UNUSED_PARAM(pAux); + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," + "p21 HIDDEN,root HIDDEN)"); + if( rc==SQLITE_OK ){ + pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); + } + return rc; +} + +/* destructor for p21_each virtual table */ +static int p21EachDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* constructor for a P21EachCursor object for p21_each(). */ +static int p21EachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + P21EachCursor *pCur; + + UNUSED_PARAM(p); + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* Reset a P21EachCursor back to its original state. Free any memory +** held. */ +static void p21EachCursorReset(P21EachCursor *p){ + sqlite3_free(p->zP21); + sqlite3_free(p->zRoot); + p21ParseReset(&p->sParse); + p->iRowid = 0; + p->i = 0; + p->iEnd = 0; + p->eType = 0; + p->zP21 = 0; + p->zRoot = 0; +} + +/* Destructor for a p21EachCursor object */ +static int p21EachClose(sqlite3_vtab_cursor *cur){ + P21EachCursor *p = (P21EachCursor*)cur; + p21EachCursorReset(p); + sqlite3_free(cur); + return SQLITE_OK; +} + +/* Return TRUE if the p21EachCursor object has been advanced off the end +** of the P21 object */ +static int p21EachEof(sqlite3_vtab_cursor *cur){ + P21EachCursor *p = (P21EachCursor*)cur; + return p->i >= p->iEnd; +} + +/* Advance the cursor to the next element for p21_tree() */ +static int p21EachNext(sqlite3_vtab_cursor *cur){ + P21EachCursor *p = (P21EachCursor*)cur; + switch( p->eType ){ + case P21_RECORD: + case P21_LIST: { + p->i += p21NodeSize(&p->sParse.aNode[p->i]); + p->iRowid++; + break; + } + default: { + p->i = p->iEnd; + break; + } + } + return SQLITE_OK; +} + +/* Append the name of the path for element i to pStr +*/ +static void p21EachComputePath( + P21EachCursor *p, /* The cursor */ + P21String *pStr, /* Write the path here */ + u32 i /* Path to this element */ +){ + P21Node *pNode, *pUp; + u32 iUp; + if( i==0 ){ + p21AppendChar(pStr, '$'); + return; + } + iUp = p->sParse.aUp[i]; + p21EachComputePath(p, pStr, iUp); + pNode = &p->sParse.aNode[i]; + pUp = &p->sParse.aNode[iUp]; + if( pUp->eType==P21_LIST ){ + p21Printf(30, pStr, "[%d]", pUp->u.iKey); + }else{ + assert( pUp->eType==P21_RECORD ); + if( (pNode->jnFlags & PNODE_LABEL)==0 ) pNode--; + assert( pNode->eType==P21_STRING ); + assert( pNode->jnFlags & PNODE_LABEL ); + p21Printf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1); + } +} + +/* Return the value of a column */ +static int p21EachColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ +){ + P21EachCursor *p = (P21EachCursor*)cur; + P21Node *pThis = &p->sParse.aNode[p->i]; + switch( i ){ + case PEACH_KEY: { + if( p->i==0 ) break; + if( p->eType==P21_RECORD ){ + p21Return(pThis, ctx, 0); + }else if( p->eType==P21_LIST ){ + u32 iKey; + iKey = p->iRowid; + sqlite3_result_int64(ctx, (sqlite3_int64)iKey); + } + break; + } + case PEACH_VALUE: { + if( pThis->jnFlags & PNODE_LABEL ) pThis++; + p21Return(pThis, ctx, 0); + break; + } + case PEACH_TYPE: { + if( pThis->jnFlags & PNODE_LABEL ) pThis++; + sqlite3_result_text(ctx, p21Type[pThis->eType], -1, SQLITE_STATIC); + break; + } + case PEACH_ATOM: { + if( pThis->jnFlags & PNODE_LABEL ) pThis++; + if( pThis->eType>=P21_LIST ) break; + p21Return(pThis, ctx, 0); + break; + } + case PEACH_ID: { + sqlite3_result_int64(ctx, + (sqlite3_int64)p->i + ((pThis->jnFlags & PNODE_LABEL)!=0)); + break; + } + case PEACH_FULLKEY: { + P21String x; + p21Init(&x, ctx); + if( p->zRoot ){ + p21AppendRaw(&x, p->zRoot, (int)strlen(p->zRoot)); + }else{ + p21AppendChar(&x, '$'); + } + if( p->eType==P21_LIST ){ + p21Printf(30, &x, "[%d]", p->iRowid); + }else if( p->eType==P21_RECORD ){ + p21Printf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); + } + p21Result(&x); + break; + } + case PEACH_PATH: + default: { + const char *zRoot = p->zRoot; + if( zRoot==0 ) zRoot = "$"; + sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); + break; + } + case PEACH_P21: { + assert( i==PEACH_P21 ); + sqlite3_result_text(ctx, p->sParse.zP21, -1, SQLITE_STATIC); + break; + } + } + return SQLITE_OK; +} + +/* Return the current rowid value */ +static int p21EachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + P21EachCursor *p = (P21EachCursor*)cur; + *pRowid = p->iRowid; + return SQLITE_OK; +} + +/* The query strategy is to look for an equality constraint on the p21 +** column. Without such a constraint, the table cannot operate. idxNum is +** 1 if the constraint is found, 3 if the constraint and zRoot are found, +** and 0 otherwise. +*/ +static int p21EachBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + int i; /* Loop counter or computed array index */ + int aIdx[2]; /* Index of constraints for P21 and ROOT */ + int unusableMask = 0; /* Mask of unusable P21 and ROOT constraints */ + int idxMask = 0; /* Mask of usable == constraints P21 and ROOT */ + const struct sqlite3_index_constraint *pConstraint; + + /* This implementation assumes that P21 and ROOT are the last two + ** columns in the table */ + assert( PEACH_ROOT == PEACH_P21+1 ); + UNUSED_PARAM(tab); + aIdx[0] = aIdx[1] = -1; + pConstraint = pIdxInfo->aConstraint; + for(i=0; inConstraint; i++, pConstraint++){ + int iCol; + int iMask; + if( pConstraint->iColumn < PEACH_P21 ) continue; + iCol = pConstraint->iColumn - PEACH_P21; + assert( iCol==0 || iCol==1 ); + iMask = 1 << iCol; + if( pConstraint->usable==0 ){ + unusableMask |= iMask; + }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + aIdx[iCol] = i; + idxMask |= iMask; + } + } + if( (unusableMask & ~idxMask)!=0 ){ + /* If there are any unusable constraints on P21 or ROOT, then reject + ** this entire plan */ + return SQLITE_CONSTRAINT; + } + if( aIdx[0]<0 ){ + /* No P21 input. Leave estimatedCost at the huge value that it was + ** initialized to to discourage the query planner from selecting this + ** plan. */ + pIdxInfo->idxNum = 0; + }else{ + pIdxInfo->estimatedCost = 1.0; + i = aIdx[0]; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; + pIdxInfo->aConstraintUsage[i].omit = 1; + if( aIdx[1]<0 ){ + pIdxInfo->idxNum = 1; /* Only P21 supplied. Plan 1 */ + }else{ + i = aIdx[1]; + pIdxInfo->aConstraintUsage[i].argvIndex = 2; + pIdxInfo->aConstraintUsage[i].omit = 1; + pIdxInfo->idxNum = 3; /* Both P21 and ROOT are supplied. Plan 3 */ + } + } + return SQLITE_OK; +} + +/* Start a search on a new P21 string */ +static int p21EachFilter( + sqlite3_vtab_cursor *cur, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + P21EachCursor *p = (P21EachCursor*)cur; + const char *z; + const char *zRoot = 0; + sqlite3_int64 n; + + UNUSED_PARAM(idxStr); + UNUSED_PARAM(argc); + p21EachCursorReset(p); + if( idxNum==0 ) return SQLITE_OK; + z = (const char*)sqlite3_value_text(argv[0]); + if( z==0 ) return SQLITE_OK; + n = sqlite3_value_bytes(argv[0]); + p->zP21 = sqlite3_malloc64( n+1 ); + if( p->zP21==0 ) return SQLITE_NOMEM; + memcpy(p->zP21, z, (size_t)n+1); + if( p21Parse(&p->sParse, 0, p->zP21) ){ + int rc = SQLITE_NOMEM; + if( p->sParse.oom==0 ){ + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = sqlite3_mprintf("malformed P21"); + if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR; + } + p21EachCursorReset(p); + return rc; + }else{ + P21Node *pNode = 0; + if( idxNum==3 ){ + const char *zErr = 0; + zRoot = (const char*)sqlite3_value_text(argv[1]); + if( zRoot==0 ) return SQLITE_OK; + n = sqlite3_value_bytes(argv[1]); + p->zRoot = sqlite3_malloc64( n+1 ); + if( p->zRoot==0 ) return SQLITE_NOMEM; + memcpy(p->zRoot, zRoot, (size_t)n+1); + if( zRoot[0]!='$' ){ + zErr = zRoot; + }else{ + pNode = p21LookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr); + } + if( zErr ){ + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = p21PathSyntaxError(zErr); + p21EachCursorReset(p); + return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; + }else if( pNode==0 ){ + return SQLITE_OK; + } + }else{ + pNode = p->sParse.aNode; + } + p->iBegin = p->i = (int)(pNode - p->sParse.aNode); + p->eType = pNode->eType; + if( p->eType>=P21_LIST ){ + pNode->u.iKey = 0; + p->iEnd = p->i + pNode->n + 1; + p->i++; + }else{ + p->iEnd = p->i+1; + } + } + return SQLITE_OK; +} + +/* The methods of the p21_each virtual table */ +static sqlite3_module p21EachModule = { + 0, /* iVersion */ + 0, /* xCreate */ + p21EachConnect, /* xConnect */ + p21EachBestIndex, /* xBestIndex */ + p21EachDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + p21EachOpenEach, /* xOpen - open a cursor */ + p21EachClose, /* xClose - close a cursor */ + p21EachFilter, /* xFilter - configure scan constraints */ + p21EachNext, /* xNext - advance a cursor */ + p21EachEof, /* xEof - check for end of scan */ + p21EachColumn, /* xColumn - read data */ + p21EachRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ +}; + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/**************************************************************************** +** The following routines are the only publically visible identifiers in this +** file. Call the following routines in order to register the various SQL +** functions and the virtual table implemented by this file. +****************************************************************************/ + +int sqlite3P21sqlInit(sqlite3 *db){ + int rc = SQLITE_OK; + unsigned int i; + static const struct { + const char *zName; + int nArg; + int flag; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } aFunc[] = { + { "p21", 1, 0, p21RemoveFunc }, + { "p21_array", -1, 0, p21ArrayFunc }, + { "p21_array_length", 1, 0, p21ArrayLengthFunc }, + { "p21_array_length", 2, 0, p21ArrayLengthFunc }, + { "p21_extract", -1, 0, p21ExtractFunc }, + { "p21_insert", -1, 0, p21SetFunc }, + { "p21_object", -1, 0, p21ObjectFunc }, +#if 0 + { "p21_patch", 2, 0, p21PatchFunc }, +#endif + { "p21_quote", 1, 0, p21QuoteFunc }, + { "p21_remove", -1, 0, p21RemoveFunc }, + { "p21_replace", -1, 0, p21ReplaceFunc }, + { "p21_set", -1, 1, p21SetFunc }, + { "p21_type", 1, 0, p21TypeFunc }, + { "p21_type", 2, 0, p21TypeFunc }, + { "p21_valid", 1, 0, p21ValidFunc }, + +#if SQLITE_DEBUG + /* DEBUG and TESTING functions */ + { "p21_parse", 1, 0, p21ParseFunc }, + { "p21_test1", 1, 0, p21Test1Func }, +#endif + }; + static const struct { + const char *zName; + int nArg; + void (*xStep)(sqlite3_context*,int,sqlite3_value**); + void (*xFinal)(sqlite3_context*); + void (*xValue)(sqlite3_context*); + } aAgg[] = { + { "p21_group_array", 1, + p21ArrayStep, p21ArrayFinal, p21ArrayValue }, + { "p21_group_object", 2, + p21ObjectStep, p21ObjectFinal, p21ObjectValue }, + }; +#ifndef SQLITE_OMIT_VIRTUALTABLE + static const struct { + const char *zName; + sqlite3_module *pModule; + } aMod[] = { + { "p21_each", &p21EachModule }, + }; +#endif + static const int enc = + SQLITE_UTF8 | + SQLITE_DETERMINISTIC | + SQLITE_INNOCUOUS; + for(i=0; i +#include +#include +#include + +/* Mark a function parameter as unused, to suppress nuisance compiler +** warnings. */ +#ifndef UNUSED_PARAM +# define UNUSED_PARAM(X) (void)(X) +#endif + +#ifndef LARGEST_INT64 +# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) +# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) +#endif + +/* +** Versions of isspace(), isalnum() and isdigit() to which it is safe +** to pass signed char values. +*/ +#ifdef sqlite3Isdigit + /* Use the SQLite core versions if this routine is part of the + ** SQLite amalgamation */ +# define safe_isdigit(x) sqlite3Isdigit(x) +# define safe_isalnum(x) sqlite3Isalnum(x) +# define safe_isxdigit(x) sqlite3Isxdigit(x) +#else + /* Use the standard library for separate compilation */ +#include /* amalgamator: keep */ +# define safe_isdigit(x) isdigit((unsigned char)(x)) +# define safe_isalnum(x) isalnum((unsigned char)(x)) +# define safe_isxdigit(x) isxdigit((unsigned char)(x)) +#endif + +/* +** Growing our own isspace() routine this way is twice as fast as +** the library isspace() function, resulting in a 7% overall performance +** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os). +*/ +static const char p21IsSpace[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +#define safe_isspace(x) (p21IsSpace[(unsigned char)x]) + +#ifndef SQLITE_AMALGAMATION + /* Unsigned integer types. These are already defined in the sqliteInt.h, + ** but the definitions need to be repeated for separate compilation. */ + typedef sqlite3_uint64 u64; + typedef unsigned int u32; + typedef unsigned short int u16; + typedef unsigned char u8; +#endif + +/* some C implementations don't have these? (inttypes.h / stdint.h) */ +#ifndef UINT16_WIDTH +# define UINT16_WIDTH 16 +#endif +#ifndef UINT16_MAX +# define UINT16_MAX 65535 +#endif + +/* Objects */ +typedef struct P21String P21String; +typedef struct P21Node P21Node; +typedef struct P21Parse P21Parse; + +/* An instance of this object represents a P21 parameter string +** under construction. Really, this is a generic string accumulator +** that can be and is used to create strings other than JSON (here P21!). +*/ +struct P21String { + sqlite3_context *pCtx; /* Function context - put error messages here */ + char *zBuf; /* Append P21 content here */ + u64 nAlloc; /* Bytes of storage available in zBuf[] */ + u64 nUsed; /* Bytes of zBuf[] currently used */ + u8 bStatic; /* True if zBuf is static space */ + u8 bErr; /* True if an error has been encountered */ + char zSpace[100]; /* Initial static space */ +}; + +#define P21_EMPTY 0x1 /* optional attribute not provided : '$' */ +#define P21_DERIVED 0x2 /* derived attribute not provided : '*' */ +#define P21_ENUMERATION 0x3 /* (also) includes boolean and logical values */ +#define P21_INTEGER 0x4 +#define P21_REAL 0x5 +#define P21_STRING 0x6 +#define P21_BINARY 0x7 +#define P21_EID 0x8 /* entity_instance_name */ +#define P21_LIST 0x9 +#define P21_RECORD 0xA /* simple_record */ + +#define P21_SUBTYPE 80 /* Ascii for "P" */ + + +/* +** Names of the various P21 types: +*/ +static const char * const p21Type[] = { + "", + "empty", "derived", "enumeration", "integer", "real", + "string", "binary", "eid", "list", "record" +}; + +/* Bit values for the P21Node.jnFlag field +*/ +#define PNODE_RAW 0x01 /* Content is raw, not P21 encoded */ +#define PNODE_ESCAPE 0x02 /* Content is text with \ escapes */ +#define PNODE_REMOVE 0x04 /* Do not output */ +#define PNODE_REPLACE 0x08 /* Replace with P21Node.u.iReplace */ +#define PNODE_PATCH 0x10 /* Patch with P21Node.u.pPatch */ +#define PNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */ +#define PNODE_LABEL 0x40 /* Is a label of an object */ + + +/* A single node of parsed P21 params +*/ +struct P21Node { + u8 eType; /* One of the P21_ type values */ + u8 jnFlags; /* P21Node flags */ + u16 n_kw; /* store the KEYWORD length */ + u32 n; /* Bytes of content, or number of sub-nodes */ + union { + const char *zJContent; /* Content for INT, REAL, and STRING */ + u32 iAppend; /* More terms for ARRAY and OBJECT */ + u32 iKey; /* Key for ARRAY objects in p21_tree() */ + u32 iReplace; /* Replacement content for PNODE_REPLACE */ + P21Node *pPatch; /* Node chain of patch for PNODE_PATCH */ + } u; +}; + +/* A completely parsed P21 string +*/ +struct P21Parse { + u32 nNode; /* Number of slots of aNode[] used */ + u32 nAlloc; /* Number of slots of aNode[] allocated */ + P21Node *aNode; /* Array of nodes containing the parse */ + const char *zP21; /* Original P21 string */ + u32 *aUp; /* Index of parent of each node */ + u8 oom; /* Set to true if out of memory */ + u8 nErr; /* Number of errors seen */ + u16 iDepth; /* Nesting depth */ + int nP21; /* Length of the zP21 string in bytes */ + u32 iHold; /* Replace cache line with the lowest iHold value */ +}; + +/* +** Maximum nesting depth of P21 for this implementation. +*/ +#define P21_MAX_DEPTH 20 + +/************************************************************************** +** Utility routines for dealing with P21String objects +**************************************************************************/ + +/* Set the P21String object to an empty string +*/ +static void p21Zero(P21String *p){ + p->zBuf = p->zSpace; + p->nAlloc = sizeof(p->zSpace); + p->nUsed = 0; + p->bStatic = 1; +} + +/* Initialize the P21String object +*/ +static void p21Init(P21String *p, sqlite3_context *pCtx){ + p->pCtx = pCtx; + p->bErr = 0; + p21Zero(p); +} + + +/* Free all allocated memory and reset the P21String object back to its +** initial state. +*/ +static void p21Reset(P21String *p){ + if( !p->bStatic ) sqlite3_free(p->zBuf); + p21Zero(p); +} + + +/* Report an out-of-memory (OOM) condition +*/ +static void p21Oom(P21String *p){ + p->bErr = 1; + sqlite3_result_error_nomem(p->pCtx); + p21Reset(p); +} + +/* Enlarge p->zBuf so that it can hold at least N more bytes. +** Return zero on success. Return non-zero on an OOM error +*/ +static int p21Grow(P21String *p, u32 N){ + u64 nTotal = NnAlloc ? p->nAlloc*2 : p->nAlloc+N+10; + char *zNew; + if( p->bStatic ){ + if( p->bErr ) return 1; + zNew = sqlite3_malloc64(nTotal); + if( zNew==0 ){ + p21Oom(p); + return SQLITE_NOMEM; + } + memcpy(zNew, p->zBuf, (size_t)p->nUsed); + p->zBuf = zNew; + p->bStatic = 0; + }else{ + zNew = sqlite3_realloc64(p->zBuf, nTotal); + if( zNew==0 ){ + p21Oom(p); + return SQLITE_NOMEM; + } + p->zBuf = zNew; + } + p->nAlloc = nTotal; + return SQLITE_OK; +} + +/* Append N bytes from zIn onto the end of the P21String string. +*/ +static void p21AppendRaw(P21String *p, const char *zIn, u32 N){ + if( (N+p->nUsed >= p->nAlloc) && p21Grow(p,N)!=0 ) return; + memcpy(p->zBuf+p->nUsed, zIn, N); + p->nUsed += N; +} + +/* Append formatted text (not to exceed N bytes) to the P21String. +*/ +static void p21Printf(int N, P21String *p, const char *zFormat, ...){ + va_list ap; + if( (p->nUsed + N >= p->nAlloc) && p21Grow(p, N) ) return; + va_start(ap, zFormat); + sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); + va_end(ap); + p->nUsed += (int)strlen(p->zBuf+p->nUsed); +} + +/* Append a single character +*/ +static void p21AppendChar(P21String *p, char c){ + if( p->nUsed>=p->nAlloc && p21Grow(p,1)!=0 ) return; + p->zBuf[p->nUsed++] = c; +} + +/* Append a comma separator to the output buffer, if the previous +** character is not '[' or '{'. +*/ +static void p21AppendSeparator(P21String *p){ + char c; + if( p->nUsed==0 ) return; + c = p->zBuf[p->nUsed-1]; + if( c!='(' ) p21AppendChar(p, ','); +} + +/* Append the N-byte string in zIn to the end of the P21String string +** under construction. Enclose the string in '...' and escape +** any double-quotes or backslash characters contained within the +** string. +*/ +static void p21AppendString(P21String *p, const char *zIn, u32 N){ + u32 i; + if( (N+p->nUsed+2 >= p->nAlloc) && p21Grow(p,N+2)!=0 ) return; + p->zBuf[p->nUsed++] = '\''; + for(i=0; inUsed+N+3-i > p->nAlloc) && p21Grow(p,N+3-i)!=0 ) return; + p->zBuf[p->nUsed++] = '\\'; + }else if( c<=0x1f ){ + static const char aSpecial[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + assert( sizeof(aSpecial)==32 ); + assert( aSpecial['\b']=='b' ); + assert( aSpecial['\f']=='f' ); + assert( aSpecial['\n']=='n' ); + assert( aSpecial['\r']=='r' ); + assert( aSpecial['\t']=='t' ); + if( aSpecial[c] ){ + c = aSpecial[c]; + goto p21_simple_escape; + } + if( (p->nUsed+N+7+i > p->nAlloc) && p21Grow(p,N+7-i)!=0 ) return; + p->zBuf[p->nUsed++] = '\\'; + p->zBuf[p->nUsed++] = 'u'; + p->zBuf[p->nUsed++] = '0'; + p->zBuf[p->nUsed++] = '0'; + p->zBuf[p->nUsed++] = '0' + (c>>4); + c = "0123456789abcdef"[c&0xf]; + } + p->zBuf[p->nUsed++] = c; + } + p->zBuf[p->nUsed++] = '\''; + assert( p->nUsednAlloc ); +} + +/* +** Append a function parameter value to the P21 string under +** construction. +*/ +static void p21AppendValue( + P21String *p, /* Append to this P21 string */ + sqlite3_value *pValue /* Value to append */ +){ + switch( sqlite3_value_type(pValue) ){ + case SQLITE_NULL: { + p21AppendRaw(p, "$", 1); + break; + } + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + const char *z = (const char*)sqlite3_value_text(pValue); + /* TODO: confirm format is valid */ + u32 n = (u32)sqlite3_value_bytes(pValue); + p21AppendRaw(p, z, n); + break; + } + case SQLITE_TEXT: { + const char *z = (const char*)sqlite3_value_text(pValue); + u32 n = (u32)sqlite3_value_bytes(pValue); + if( sqlite3_value_subtype(pValue)==P21_SUBTYPE ){ + p21AppendRaw(p, z, n); + }else{ + p21AppendString(p, z, n); + } + break; + } + default: { + if( p->bErr==0 ){ + sqlite3_result_error(p->pCtx, "P21 cannot hold BLOB values", -1); + p->bErr = 2; + p21Reset(p); + } + break; + } + } +} + + +/* Make the P21 in p the result of the SQL function. +*/ +static void p21Result(P21String *p){ + if( p->bErr==0 ){ + sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed, + p->bStatic ? SQLITE_TRANSIENT : sqlite3_free, + SQLITE_UTF8); + p21Zero(p); + } + assert( p->bStatic ); +} + +/************************************************************************** +** Utility routines for dealing with P21Node and P21Parse objects +**************************************************************************/ + +/* +** Return the number of consecutive P21Node slots need to represent +** the parsed P21 at pNode. The minimum answer is 1. For ARRAY and +** OBJECT types, the number might be larger. +** +** Appended elements are not counted. The value returned is the number +** by which the P21Node counter should increment in order to go to the +** next peer value. +*/ +static u32 p21NodeSize(P21Node *pNode){ + return pNode->eType < P21_LIST ? 1 : pNode->n + 1; +} + +/* +** Reclaim all memory allocated by a P21Parse object. But do not +** delete the P21Parse object itself. +*/ +static void p21ParseReset(P21Parse *pParse){ + sqlite3_free(pParse->aNode); + pParse->aNode = 0; + pParse->nNode = 0; + pParse->nAlloc = 0; + sqlite3_free(pParse->aUp); + pParse->aUp = 0; +} + +/* +** Free a P21Parse object that was obtained from sqlite3_malloc(). +*/ +static void p21ParseFree(P21Parse *pParse){ + p21ParseReset(pParse); + sqlite3_free(pParse); +} + +/* +** Convert the P21Node pNode into a pure P21 string and +** append to pOut. Subsubstructure is also included. Return +** the number of P21Node objects that are encoded. +*/ +static void p21RenderNode( + P21Node *pNode, /* The node to render */ + P21String *pOut, /* Write P21 here */ + sqlite3_value **aReplace /* Replacement values */ +){ + if( pNode->jnFlags & (PNODE_REPLACE|PNODE_PATCH) ){ + if( pNode->jnFlags & PNODE_REPLACE ){ + p21AppendValue(pOut, aReplace[pNode->u.iReplace]); + return; + } + pNode = pNode->u.pPatch; + } + switch( pNode->eType ){ + default: { + assert( pNode->eType==P21_EMPTY ); + p21AppendChar(pOut, '$'); + break; + } + case P21_ENUMERATION: { + p21AppendRaw(pOut, pNode->u.zJContent, pNode->n); + break; + } + case P21_DERIVED: { + p21AppendChar(pOut, '*'); + break; + } + case P21_BINARY: { + p21AppendRaw(pOut, pNode->u.zJContent, pNode->n); + break; + } + case P21_EID: { + p21AppendRaw(pOut, pNode->u.zJContent, pNode->n); + break; + } + case P21_STRING: { + if( pNode->jnFlags & PNODE_RAW ){ + p21AppendString(pOut, pNode->u.zJContent, pNode->n); + break; + } + /* Fall through into the next case */ + } + case P21_REAL: + case P21_INTEGER: { + p21AppendRaw(pOut, pNode->u.zJContent, pNode->n); + break; + } + case P21_LIST: { + u32 j = 1; + p21AppendChar(pOut, '('); + for(;;){ + while( j<=pNode->n ){ + if( (pNode[j].jnFlags & PNODE_REMOVE)==0 ){ + p21AppendSeparator(pOut); + p21RenderNode(&pNode[j], pOut, aReplace); + } + j += p21NodeSize(&pNode[j]); + } + if( (pNode->jnFlags & PNODE_APPEND)==0 ) break; + pNode = &pNode[pNode->u.iAppend]; + j = 1; + } + p21AppendChar(pOut, ')'); + break; + } + case P21_RECORD: { + u32 j = 1; + p21AppendRaw(pOut, pNode->u.zJContent, pNode->n_kw); + p21AppendChar(pOut, '('); + for(;;){ + while( j<= pNode->n ){ + if( (pNode[j].jnFlags & PNODE_REMOVE)==0 ){ + p21AppendSeparator(pOut); + p21RenderNode(&pNode[j], pOut, aReplace); + } + j += p21NodeSize(&pNode[j]); + } + if( (pNode->jnFlags & PNODE_APPEND)==0 ) break; + pNode = &pNode[pNode->u.iAppend]; + j = 1; + } + p21AppendChar(pOut, ')'); + break; + } + } +} + +/* +** Return a P21Node and all its descendents as a P21 string. +*/ +static void p21ReturnP21( + P21Node *pNode, /* Node to return */ + sqlite3_context *pCtx, /* Return value for this function */ + sqlite3_value **aReplace /* Array of replacement values */ +){ + P21String s; + p21Init(&s, pCtx); + p21RenderNode(pNode, &s, aReplace); + p21Result(&s); + sqlite3_result_subtype(pCtx, P21_SUBTYPE); +} + +/* +** Translate a single byte of Hex into an integer. +** This routine only works if h really is a valid hexadecimal +** character: 0..9a..fA..F +*/ +static u8 p21HexToInt(int h){ + assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') ); +#ifdef SQLITE_EBCDIC + h += 9*(1&~(h>>4)); +#else + h += 9*(1&(h>>6)); +#endif + return (u8)(h & 0xf); +} + +/* +** Convert a 4-byte hex string into an integer +*/ +static u32 p21HexToInt4(const char *z){ + u32 v; + assert( safe_isxdigit(z[0]) ); + assert( safe_isxdigit(z[1]) ); + assert( safe_isxdigit(z[2]) ); + assert( safe_isxdigit(z[3]) ); + v = (p21HexToInt(z[0])<<12) + + (p21HexToInt(z[1])<<8) + + (p21HexToInt(z[2])<<4) + + p21HexToInt(z[3]); + return v; +} +/* +** Make the P21Node the return value of the function. +*/ +static void p21Return( + P21Node *pNode, /* Node to return */ + sqlite3_context *pCtx, /* Return value for this function */ + sqlite3_value **aReplace /* Array of replacement values */ +){ + switch( pNode->eType ){ + default: { + assert( pNode->eType==P21_EMPTY ); + sqlite3_result_null(pCtx); + break; + } + case P21_DERIVED: { + assert(0); + } + case P21_ENUMERATION: { + assert(0); + } + case P21_BINARY: { + assert(0); + } + case P21_EID: { + sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n, SQLITE_TRANSIENT); + break; + } + case P21_INTEGER: { + sqlite3_int64 i = 0; + const char *z = pNode->u.zJContent; + if( z[0]=='-' ){ z++; } + while( z[0]>='0' && z[0]<='9' ){ + unsigned v = *(z++) - '0'; + if( i>=LARGEST_INT64/10 ){ + if( i>LARGEST_INT64/10 ) goto int_as_real; + if( z[0]>='0' && z[0]<='9' ) goto int_as_real; + if( v==9 ) goto int_as_real; + if( v==8 ){ + if( pNode->u.zJContent[0]=='-' ){ + sqlite3_result_int64(pCtx, SMALLEST_INT64); + goto int_done; + }else{ + goto int_as_real; + } + } + } + i = i*10 + v; + } + if( pNode->u.zJContent[0]=='-' ){ i = -i; } + sqlite3_result_int64(pCtx, i); + int_done: + break; + int_as_real: /* fall through to real */; + } + case P21_REAL: { + double r; +#ifdef SQLITE_AMALGAMATION + const char *z = pNode->u.zJContent; + sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); +#else + r = strtod(pNode->u.zJContent, 0); +#endif + sqlite3_result_double(pCtx, r); + break; + } + case P21_STRING: { +#if 0 /* Never happens because PNODE_RAW is only set by p21_set(), + ** p21_insert() and p21_replace() and those routines do not + ** call p21Return() */ + if( pNode->jnFlags & PNODE_RAW ){ + sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n, + SQLITE_TRANSIENT); + }else +#endif + assert( (pNode->jnFlags & PNODE_RAW)==0 ); + if( (pNode->jnFlags & PNODE_ESCAPE)==0 ){ + /* P21 formatted without any backslash-escapes */ + sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2, + SQLITE_TRANSIENT); + }else{ + /* Translate P21 formatted string into raw text */ + u32 i; + u32 n = pNode->n; + const char *z = pNode->u.zJContent; + char *zOut; + u32 j; + /* TODO: */ + assert(0); + zOut = sqlite3_malloc( n+1 ); + if( zOut==0 ){ + sqlite3_result_error_nomem(pCtx); + break; + } + for(i=1, j=0; i>6)); + zOut[j++] = 0x80 | (v&0x3f); + }else{ + u32 vlo; + if( (v&0xfc00)==0xd800 + && i>18); + zOut[j++] = 0x80 | ((v>>12)&0x3f); + zOut[j++] = 0x80 | ((v>>6)&0x3f); + zOut[j++] = 0x80 | (v&0x3f); + }else{ + zOut[j++] = 0xe0 | (v>>12); + zOut[j++] = 0x80 | ((v>>6)&0x3f); + zOut[j++] = 0x80 | (v&0x3f); + } + } + }else{ + if( c=='b' ){ + c = '\b'; + }else if( c=='f' ){ + c = '\f'; + }else if( c=='n' ){ + c = '\n'; + }else if( c=='r' ){ + c = '\r'; + }else if( c=='t' ){ + c = '\t'; + } + zOut[j++] = c; + } + } + } + zOut[j] = 0; + sqlite3_result_text(pCtx, zOut, j, sqlite3_free); + } + break; + } + case P21_LIST: + case P21_RECORD: { + p21ReturnP21(pNode, pCtx, aReplace); + break; + } + } +} + +/* Forward reference */ +static int p21ParseAddNode(P21Parse*,u32,u32,const char*); + +/* +** A macro to hint to the compiler that a function should not be +** inlined. +*/ +#if defined(__GNUC__) +# define P21_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) && _MSC_VER>=1310 +# define P21_NOINLINE __declspec(noinline) +#else +# define P21_NOINLINE +#endif + + +static P21_NOINLINE int p21ParseAddNodeExpand( + P21Parse *pParse, /* Append the node to this object */ + u32 eType, /* Node type */ + u32 n, /* Content size or sub-node count */ + const char *zContent /* Content */ +){ + u32 nNew; + P21Node *pNew; + assert( pParse->nNode>=pParse->nAlloc ); + if( pParse->oom ) return -1; + nNew = pParse->nAlloc*2 + 10; + pNew = sqlite3_realloc64(pParse->aNode, sizeof(P21Node)*nNew); + if( pNew==0 ){ + pParse->oom = 1; + return -1; + } + pParse->nAlloc = nNew; + pParse->aNode = pNew; + assert( pParse->nNodenAlloc ); + return p21ParseAddNode(pParse, eType, n, zContent); +} + +/* +** Create a new P21Node instance based on the arguments and append that +** instance to the P21Parse. Return the index in pParse->aNode[] of the +** new node, or -1 if a memory allocation fails. +*/ +static int p21ParseAddNode( + P21Parse *pParse, /* Append the node to this object */ + u32 eType, /* Node type */ + u32 n, /* Content size or sub-node count */ + const char *zContent /* Content */ +){ + P21Node *p; + if( pParse->nNode>=pParse->nAlloc ){ + return p21ParseAddNodeExpand(pParse, eType, n, zContent); + } + p = &pParse->aNode[pParse->nNode]; + p->eType = (u8)eType; + p->jnFlags = 0; + p->n = n; + p->u.zJContent = zContent; + return pParse->nNode++; +} + +/* +** Return true if z[] begins with 4 (or more) hexadecimal digits +*/ +static int p21Is4Hex(const char *z){ + int i; + for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0; + return 1; +} + +/* +** Parse P21 value which begins at pParse->zP21[i]. Return the +** index of the first character past the end of the value parsed. +** +** Return negative for a syntax error. +*/ +static int p21ParseValue(P21Parse *pParse, u32 i) { + static int cxtStack[P21_MAX_DEPTH]; + const unsigned char *sp, *cur, *mrk, *tok, *end; + /*!stags:re2c format = 'const unsigned char *@@;'; */ + int *piThis, x; + u32 n; + P21Node *pNode; + + sp = cur = tok = &pParse->zP21[i]; + piThis = cxtStack + pParse->iDepth; + +/*!re2c + re2c:yyfill:enable = 0; + re2c:flags:tags = 1; + re2c:define:YYCTYPE = 'unsigned char'; + re2c:define:YYCURSOR = 'cur'; + re2c:define:YYMARKER = 'mrk'; + + ascii_encoding = [][!"*$%&.#+,\-()?/:;<=>@{}|^`~0-9a-zA-Z_ ] | "''" | "\\" ; + page_encoding = "\\" [A-I] "\\" | "\\S\\" [][!"'*$%&.#+,\-()?/:;<=>@{}|^`~0-9a-zA-Z_\\ ] ; + hex_encoding = "\\X2\\" ([0-9A-F]{4})+ "\\X0\\" | "\\X4\\" ([0-9A-F]{8})+ "\\X0\\" ; + byte_encoding = "\\X\\" [0-9A-F]{2} ; + + WS = [ \t\r\n] ; + KEYWORD = "!"? [A-Za-z_] [0-9A-Za-z_]* ; + REAL = [+-]* [0-9] [0-9]* "." [0-9]* ("E" [+-]* [0-9] [0-9]*)? ; + INTEGER = [+-]* [0-9] [0-9]* ; + STRING = "'" (ascii_encoding | page_encoding | hex_encoding | byte_encoding )* "'" ; + BINARY = '"' [0-3] [0-9A-F]* '"' ; + ENUMERATION = "." [A-Z_] [A-Z0-9_]* "." ; + EID = "#" [0-9]+ ; + */ + +start: + + tok = cur; +/*!re2c + WS+ { + goto start; + } + "(" { + /* (complex_entity_instance) parameter_list */ + *piThis = p21ParseAddNode(pParse, P21_LIST, 0, 0); + if (*piThis < 0) return -1; + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto keywords; + } + "" { + /* (simple_entity_instance) parameter_list */ + *piThis = p21ParseAddNode(pParse, P21_RECORD, 0, 0); + if (*piThis < 0) return -1; + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params1; + } + */ + +keywords: + tok = cur; + +/*!re2c + WS+ { + goto keywords; + } + KEYWORD @end WS* "(" { + *piThis = p21ParseAddNode(pParse, P21_RECORD, 0, tok); + if (*piThis < 0) return -1; + pParse->aNode[*piThis].n_kw = (u16)(end - tok); + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params2; + } + ")" { + piThis = cxtStack + --pParse->iDepth; + pNode = pParse->aNode + *piThis; + assert(pNode->eType == P21_LIST); + + pNode->n = pParse->nNode - (u32)*piThis - 1; + goto eol; + } + "" { + /* fix-up and revert to P21_RECORD */ + pNode = pParse->aNode + *(piThis - 1); + pNode->eType = P21_RECORD; + assert(pParse->iDepth == 1); + goto params1; + } + */ + +params1: + tok = cur; + +/*!re2c + WS+ { + goto params1; + } + KEYWORD @end WS* "(" { + *piThis = p21ParseAddNode(pParse, P21_RECORD, 0, tok); + if (*piThis < 0) return -1; + pParse->aNode[*piThis].n_kw = (u16)(end - tok); + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params1; + } + "(" { + *piThis = p21ParseAddNode(pParse, P21_LIST, 0, 0); + if (*piThis < 0) return -1; + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params1; + } + "," { + goto params1; + } + REAL { + p21ParseAddNode(pParse, P21_REAL, cur - tok, tok); + goto params1; + } + INTEGER { + p21ParseAddNode(pParse, P21_INTEGER, cur - tok, tok); + goto params1; + } + STRING { + p21ParseAddNode(pParse, P21_STRING, cur - tok, tok); + goto params1; + } + BINARY { + p21ParseAddNode(pParse, P21_BINARY, cur - tok, tok); + goto params1; + } + ENUMERATION { + p21ParseAddNode(pParse, P21_ENUMERATION, cur - tok, tok); + goto params1; + } + EID { + p21ParseAddNode(pParse, P21_EID, cur - tok, tok); + goto params1; + } + "$" { + p21ParseAddNode(pParse, P21_EMPTY, cur - tok, tok); + goto params1; + } + "*" { + p21ParseAddNode(pParse, P21_DERIVED, cur - tok, tok); + goto params1; + } + ")" { + piThis = cxtStack + --pParse->iDepth; + pNode = pParse->aNode + *piThis; + pNode->n = pParse->nNode - (u32)*piThis - 1; + goto params1; + } + "" { + if (pParse->iDepth) --pParse->iDepth; + piThis = cxtStack + pParse->iDepth; + pNode = pParse->aNode + *piThis; + assert(pNode->eType == P21_RECORD); + pNode->n = pParse->nNode - (u32)*piThis - 1; + goto eol; + } + */ + +params2: + tok = cur; + +/*!re2c + WS+ { + goto params2; + } + KEYWORD @end WS* "(" { + *piThis = p21ParseAddNode(pParse, P21_RECORD, 0, tok); + if (*piThis < 0) return -1; + pParse->aNode[*piThis].n_kw = (u16)(end - tok); + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params2; + } + "(" { + *piThis = p21ParseAddNode(pParse, P21_LIST, 0, 0); + if (*piThis < 0) return -1; + + if( ++pParse->iDepth > P21_MAX_DEPTH ) return -1; + piThis = cxtStack + pParse->iDepth; + goto params2; + } + "," { + goto params2; + } + REAL { + p21ParseAddNode(pParse, P21_REAL, cur - tok, tok); + goto params2; + } + INTEGER { + p21ParseAddNode(pParse, P21_INTEGER, cur - tok, tok); + goto params2; + } + STRING { + p21ParseAddNode(pParse, P21_STRING, cur - tok, tok); + goto params2; + } + BINARY { + p21ParseAddNode(pParse, P21_BINARY, cur - tok, tok); + goto params2; + } + ENUMERATION { + p21ParseAddNode(pParse, P21_ENUMERATION, cur - tok, tok); + goto params2; + } + EID { + p21ParseAddNode(pParse, P21_EID, cur - tok, tok); + goto params2; + } + "$" { + p21ParseAddNode(pParse, P21_EMPTY, cur - tok, tok); + goto params2; + } + "*" { + p21ParseAddNode(pParse, P21_DERIVED, cur - tok, tok); + goto params2; + } + ")" { + piThis = cxtStack + --pParse->iDepth; + pNode = pParse->aNode + *piThis; + pNode->n = pParse->nNode - (u32)*piThis - 1; + if (pParse->iDepth > 1) { + goto params2; + } else { + goto keywords; + } + } + /* continue to next block for error handling */ + */ + +eol: + tok = cur; + +/*!re2c + [\x00] { + return cur - sp; + } + * { + return -1; + } + */ + +} + + +/* +** Parse a complete P21 string. Return 0 on success or non-zero if there +** are any errors. If an error occurs, free all memory associated with +** pParse. +** +** pParse is uninitialized when this routine is called. +*/ +static int p21Parse( + P21Parse *pParse, /* Initialize and fill this P21Parse object */ + sqlite3_context *pCtx, /* Report errors here */ + const char *zP21 /* Input P21 text to be parsed */ +){ + int i; + memset(pParse, 0, sizeof(*pParse)); + if( zP21==0 ) return 1; + pParse->zP21 = zP21; + i = p21ParseValue(pParse, 0); + if( pParse->oom ) i = -1; + if( i>0 ){ + assert( pParse->iDepth==0 ); + } + if( i<=0 ){ + if( pCtx!=0 ){ + if( pParse->oom ){ + sqlite3_result_error_nomem(pCtx); + }else{ + sqlite3_result_error(pCtx, "malformed P21", -1); + } + } + p21ParseReset(pParse); + return 1; + } + return 0; +} + +/* Mark node i of pParse as being a child of iParent. Call recursively +** to fill in all the descendants of node i. +*/ +static void p21ParseFillInParentage(P21Parse *pParse, u32 i, u32 iParent){ + P21Node *pNode = &pParse->aNode[i]; + u32 j; + pParse->aUp[i] = iParent; + switch( pNode->eType ){ + case P21_RECORD: + case P21_LIST: { + for(j=1; j<=pNode->n; j += p21NodeSize(pNode+j)){ + p21ParseFillInParentage(pParse, i+j, i); + } + break; + } + default: { + break; + } + } +} + +/* +** Compute the parentage of all nodes in a completed parse. +*/ +static int p21ParseFindParents(P21Parse *pParse){ + u32 *aUp; + assert( pParse->aUp==0 ); + aUp = pParse->aUp = sqlite3_malloc64( sizeof(u32)*pParse->nNode ); + if( aUp==0 ){ + pParse->oom = 1; + return SQLITE_NOMEM; + } + p21ParseFillInParentage(pParse, 0, 0); + return SQLITE_OK; +} + +/* +** Magic number used for the P21 parse cache in sqlite3_get_auxdata() +*/ +#define P21_CACHE_ID (-429938) /* First cache entry */ +#define P21_CACHE_SZ 4 /* Max number of cache entries */ + +/* +** Obtain a complete parse of the P21 found in the first argument +** of the argv array. Use the sqlite3_get_auxdata() cache for this +** parse if it is available. If the cache is not available or if it +** is no longer valid, parse the P21 again and return the new parse, +** and also register the new parse so that it will be available for +** future sqlite3_get_auxdata() calls. +*/ +static P21Parse *p21ParseCached( + sqlite3_context *pCtx, + sqlite3_value **argv, + sqlite3_context *pErrCtx +){ + const char *zP21 = (const char*)sqlite3_value_text(argv[0]); + int nP21 = sqlite3_value_bytes(argv[0]); + P21Parse *p; + P21Parse *pMatch = 0; + int iKey; + int iMinKey = 0; + u32 iMinHold = 0xffffffff; + u32 iMaxHold = 0; + if( zP21==0 ) return 0; + for(iKey=0; iKeynP21==nP21 + && memcmp(p->zP21,zP21,nP21)==0 + ){ + p->nErr = 0; + pMatch = p; + }else if( p->iHoldiHold; + iMinKey = iKey; + } + if( p->iHold>iMaxHold ){ + iMaxHold = p->iHold; + } + } + if( pMatch ){ + pMatch->nErr = 0; + pMatch->iHold = iMaxHold+1; + return pMatch; + } + p = sqlite3_malloc64( sizeof(*p) + nP21 + 1 ); + if( p==0 ){ + sqlite3_result_error_nomem(pCtx); + return 0; + } + memset(p, 0, sizeof(*p)); + p->zP21 = (char*)&p[1]; + memcpy((char*)p->zP21, zP21, nP21+1); + if( p21Parse(p, pErrCtx, p->zP21) ){ + sqlite3_free(p); + return 0; + } + p->nP21 = nP21; + p->iHold = iMaxHold+1; + sqlite3_set_auxdata(pCtx, P21_CACHE_ID+iMinKey, p, + (void(*)(void*))p21ParseFree); + return (P21Parse*)sqlite3_get_auxdata(pCtx, P21_CACHE_ID+iMinKey); +} + +/* +** Compare the OBJECT label at pNode against zKey,nKey. Return true on +** a match. +*/ +static int p21LabelCompare(P21Node *pNode, const char *zKey, u32 nKey){ + if( pNode->jnFlags & PNODE_RAW ){ + if( pNode->n!=nKey ) return 0; + return strncmp(pNode->u.zJContent, zKey, nKey)==0; + }else{ + if( pNode->n!=nKey+2 ) return 0; + return strncmp(pNode->u.zJContent+1, zKey, nKey)==0; + } +} + +/* forward declaration */ +static P21Node *p21LookupAppend(P21Parse*,const char*,int*,const char**); + +/* +** Search along zPath to find the node specified. Return a pointer +** to that node, or NULL if zPath is malformed or if there is no such +** node. +** +** If pApnd!=0, then try to append new nodes to complete zPath if it is +** possible to do so and if no existing node corresponds to zPath. If +** new nodes are appended *pApnd is set to 1. +*/ +static P21Node *p21LookupStep( + P21Parse *pParse, /* The P21 to search */ + u32 iRoot, /* Begin the search at this node */ + const char *zPath, /* The path to search */ + int *pApnd, /* Append nodes to complete path if not NULL */ + const char **pzErr /* Make *pzErr point to any syntax error in zPath */ +){ + u32 i, j, nKey; + const char *zKey; + P21Node *pRoot = &pParse->aNode[iRoot]; + if( zPath[0]==0 ) return pRoot; + if( pRoot->jnFlags & PNODE_REPLACE ) return 0; + if( zPath[0]=='.' ){ + if( pRoot->eType!=P21_RECORD ) return 0; + zPath++; + if( zPath[0]=='"' ){ + zKey = zPath + 1; + for(i=1; zPath[i] && zPath[i]!='"'; i++){} + nKey = i-1; + if( zPath[i] ){ + i++; + }else{ + *pzErr = zPath; + return 0; + } + }else{ + zKey = zPath; + for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} + nKey = i; + } + if( nKey==0 ){ + *pzErr = zPath; + return 0; + } + j = 1; + for(;;){ + while( j<=pRoot->n ){ + if( p21LabelCompare(pRoot+j, zKey, nKey) ){ + return p21LookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr); + } + j++; + j += p21NodeSize(&pRoot[j]); + } + if( (pRoot->jnFlags & PNODE_APPEND)==0 ) break; + iRoot += pRoot->u.iAppend; + pRoot = &pParse->aNode[iRoot]; + j = 1; + } + if( pApnd ){ + u32 iStart, iLabel; + P21Node *pNode; + iStart = p21ParseAddNode(pParse, P21_RECORD, 2, 0); + iLabel = p21ParseAddNode(pParse, P21_STRING, nKey, zKey); + zPath += i; + pNode = p21LookupAppend(pParse, zPath, pApnd, pzErr); + if( pParse->oom ) return 0; + if( pNode ){ + pRoot = &pParse->aNode[iRoot]; + pRoot->u.iAppend = iStart - iRoot; + pRoot->jnFlags |= PNODE_APPEND; + pParse->aNode[iLabel].jnFlags |= PNODE_RAW; + } + return pNode; + } + }else if( zPath[0]=='[' ){ + i = 0; + j = 1; + while( safe_isdigit(zPath[j]) ){ + i = i*10 + zPath[j] - '0'; + j++; + } + if( j<2 || zPath[j]!=']' ){ + if( zPath[1]=='#' ){ + P21Node *pBase = pRoot; + int iBase = iRoot; + if( pRoot->eType!=P21_LIST && pRoot->eType!=P21_RECORD) return 0; + for(;;){ + while( j<=pBase->n ){ + if( (pBase[j].jnFlags & PNODE_REMOVE)==0 ) i++; + j += p21NodeSize(&pBase[j]); + } + if( (pBase->jnFlags & PNODE_APPEND)==0 ) break; + iBase += pBase->u.iAppend; + pBase = &pParse->aNode[iBase]; + j = 1; + } + j = 2; + if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){ + unsigned int x = 0; + j = 3; + do{ + x = x*10 + zPath[j] - '0'; + j++; + }while( safe_isdigit(zPath[j]) ); + if( x>i ) return 0; + i -= x; + } + if( zPath[j]!=']' ){ + *pzErr = zPath; + return 0; + } + }else{ + *pzErr = zPath; + return 0; + } + } + if( pRoot->eType!=P21_LIST && pRoot->eType!=P21_RECORD ) return 0; + zPath += j + 1; + j = 1; + for(;;){ + while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & PNODE_REMOVE)!=0) ){ + if( (pRoot[j].jnFlags & PNODE_REMOVE)==0 ) i--; + j += p21NodeSize(&pRoot[j]); + } + if( (pRoot->jnFlags & PNODE_APPEND)==0 ) break; + iRoot += pRoot->u.iAppend; + pRoot = &pParse->aNode[iRoot]; + j = 1; + } + if( j<=pRoot->n ){ + return p21LookupStep(pParse, iRoot+j, zPath, pApnd, pzErr); + } + if( i==0 && pApnd ){ + u32 iStart; + P21Node *pNode; + iStart = p21ParseAddNode(pParse, P21_LIST, 1, 0); + pNode = p21LookupAppend(pParse, zPath, pApnd, pzErr); + if( pParse->oom ) return 0; + if( pNode ){ + pRoot = &pParse->aNode[iRoot]; + pRoot->u.iAppend = iStart - iRoot; + pRoot->jnFlags |= PNODE_APPEND; + } + return pNode; + } + }else{ + *pzErr = zPath; + } + return 0; +} + +/* +** Append content to pParse that will complete zPath. Return a pointer +** to the inserted node, or return NULL if the append fails. +*/ +static P21Node *p21LookupAppend( + P21Parse *pParse, /* Append content to the P21 parse */ + const char *zPath, /* Description of content to append */ + int *pApnd, /* Set this flag to 1 */ + const char **pzErr /* Make this point to any syntax error */ +){ + *pApnd = 1; + if( zPath[0]==0 ){ + p21ParseAddNode(pParse, P21_EMPTY, 0, 0); + return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1]; + } + if( zPath[0]=='.' ){ + p21ParseAddNode(pParse, P21_RECORD, 0, 0); + }else if( strncmp(zPath,"[0]",3)==0 ){ + p21ParseAddNode(pParse, P21_LIST, 0, 0); + }else{ + return 0; + } + if( pParse->oom ) return 0; + return p21LookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr); +} + +/* +** Return the text of a syntax error message on a P21 path. Space is +** obtained from sqlite3_malloc(). +*/ +static char *p21PathSyntaxError(const char *zErr){ + return sqlite3_mprintf("P21 path error near '%q'", zErr); +} + +/* +** Do a node lookup using zPath. Return a pointer to the node on success. +** Return NULL if not found or if there is an error. +** +** On an error, write an error message into pCtx and increment the +** pParse->nErr counter. +** +** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if +** nodes are appended. +*/ +static P21Node *p21Lookup( + P21Parse *pParse, /* The P21 to search */ + const char *zPath, /* The path to search */ + int *pApnd, /* Append nodes to complete path if not NULL */ + sqlite3_context *pCtx /* Report errors here, if not NULL */ +){ + const char *zErr = 0; + P21Node *pNode = 0; + char *zMsg; + + if( zPath==0 ) return 0; + if( zPath[0]!='$' ){ + zErr = zPath; + goto lookup_err; + } + zPath++; + pNode = p21LookupStep(pParse, 0, zPath, pApnd, &zErr); + if( zErr==0 ) return pNode; + +lookup_err: + pParse->nErr++; + assert( zErr!=0 && pCtx!=0 ); + zMsg = p21PathSyntaxError(zErr); + if( zMsg ){ + sqlite3_result_error(pCtx, zMsg, -1); + sqlite3_free(zMsg); + }else{ + sqlite3_result_error_nomem(pCtx); + } + return 0; +} + + +/* +** Report the wrong number of arguments for p21_insert(), p21_replace() +** or p21_set(). +*/ +static void p21WrongNumArgs( + sqlite3_context *pCtx, + const char *zFuncName +){ + char *zMsg = sqlite3_mprintf("p21_%s() needs an odd number of arguments", + zFuncName); + sqlite3_result_error(pCtx, zMsg, -1); + sqlite3_free(zMsg); +} + +/* +** Mark all NULL entries in the Object passed in as PNODE_REMOVE. +*/ +static void p21RemoveAllNulls(P21Node *pNode){ + int i, n; + assert( pNode->eType==P21_RECORD ); + n = pNode->n; + for(i=2; i<=n; i += p21NodeSize(&pNode[i])+1){ + switch( pNode[i].eType ){ + case P21_EMPTY: + pNode[i].jnFlags |= PNODE_REMOVE; + break; + case P21_RECORD: + p21RemoveAllNulls(&pNode[i]); + break; + } + } +} + + +/**************************************************************************** +** SQL functions used for testing and debugging +****************************************************************************/ + +#ifdef SQLITE_DEBUG +/* +** The p21_parse(P21) function returns a string which describes +** a parse of the P21 provided. Or it returns NULL if P21 is not +** well-formed. +*/ +static void p21ParseFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21String s; /* Output string - not real P21 */ + P21Parse x; /* The parse */ + u32 i; + + assert( argc==1 ); + if( p21Parse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + p21ParseFindParents(&x); + p21Init(&s, ctx); + for(i=0; inNode ); + if( argc==2 ){ + const char *zPath = (const char*)sqlite3_value_text(argv[1]); + pNode = p21Lookup(p, zPath, 0, ctx); + }else{ + pNode = p->aNode; + } + if( pNode==0 ){ + return; + } + if( pNode->eType==P21_LIST ){ + assert( (pNode->jnFlags & PNODE_APPEND)==0 ); + for(i=1; i<=pNode->n; n++){ + i += p21NodeSize(&pNode[i]); + } + } + sqlite3_result_int64(ctx, n); +} + +/* +** p21_extract(P21, PATH, ...) +** +** Return the element described by PATH. Return NULL if there is no +** PATH element. If there are multiple PATHs, then return a P21 array +** with the result from each path. Throw an error if the P21 or any PATH +** is malformed. +*/ +static void p21ExtractFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse *p; /* The parse */ + P21Node *pNode; + const char *zPath; + P21String jx; + int i; + + if( argc<2 ) return; + p = p21ParseCached(ctx, argv, ctx); + if( p==0 ) return; + p21Init(&jx, ctx); + p21AppendChar(&jx, '['); + for(i=1; inErr ) break; + if( argc>2 ){ + p21AppendSeparator(&jx); + if( pNode ){ + p21RenderNode(pNode, &jx, 0); + }else{ + p21AppendRaw(&jx, "null", 4); + } + }else if( pNode ){ + p21Return(pNode, ctx, 0); + } + } + if( argc>2 && i==argc ){ + p21AppendChar(&jx, ']'); + p21Result(&jx); + sqlite3_result_subtype(ctx, P21_SUBTYPE); + } + p21Reset(&jx); +} + +#if 0 +/* TODO: a MergeRecord function could be useful + */ +static P21Node *p21MergePatch( + P21Parse *pParse, /* The P21 parser that contains the TARGET */ + u32 iTarget, /* Node of the TARGET in pParse */ + P21Node *pPatch /* The PATCH */ +){ + u32 i, j; + u32 iRoot; + P21Node *pTarget; + if( pPatch->eType!=P21_RECORD ){ + return pPatch; + } + assert( iTargetnNode ); + pTarget = &pParse->aNode[iTarget]; + assert( (pPatch->jnFlags & PNODE_APPEND)==0 ); + if( pTarget->eType!=P21_RECORD ){ + p21RemoveAllNulls(pPatch); + return pPatch; + } + iRoot = iTarget; + for(i=1; in; i += p21NodeSize(&pPatch[i+1])+1){ + u32 nKey; + const char *zKey; + assert( pPatch[i].eType==P21_STRING ); + assert( pPatch[i].jnFlags & PNODE_LABEL ); + nKey = pPatch[i].n; + zKey = pPatch[i].u.zJContent; + assert( (pPatch[i].jnFlags & PNODE_RAW)==0 ); + for(j=1; jn; j += p21NodeSize(&pTarget[j+1])+1 ){ + assert( pTarget[j].eType==P21_STRING ); + assert( pTarget[j].jnFlags & PNODE_LABEL ); + assert( (pPatch[i].jnFlags & PNODE_RAW)==0 ); + if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){ + if( pTarget[j+1].jnFlags & (PNODE_REMOVE|PNODE_PATCH) ) break; + if( pPatch[i+1].eType==P21_EMPTY ){ + pTarget[j+1].jnFlags |= PNODE_REMOVE; + }else{ + P21Node *pNew = p21MergePatch(pParse, iTarget+j+1, &pPatch[i+1]); + if( pNew==0 ) return 0; + pTarget = &pParse->aNode[iTarget]; + if( pNew!=&pTarget[j+1] ){ + pTarget[j+1].u.pPatch = pNew; + pTarget[j+1].jnFlags |= PNODE_PATCH; + } + } + break; + } + } + if( j>=pTarget->n && pPatch[i+1].eType!=P21_EMPTY ){ + int iStart, iPatch; + iStart = p21ParseAddNode(pParse, P21_RECORD, 2, 0); + p21ParseAddNode(pParse, P21_STRING, nKey, zKey); + iPatch = p21ParseAddNode(pParse, P21_TRUE, 0, 0); + if( pParse->oom ) return 0; + p21RemoveAllNulls(pPatch); + pTarget = &pParse->aNode[iTarget]; + pParse->aNode[iRoot].jnFlags |= PNODE_APPEND; + pParse->aNode[iRoot].u.iAppend = iStart - iRoot; + iRoot = iStart; + pParse->aNode[iPatch].jnFlags |= PNODE_PATCH; + pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; + } + } + return pTarget; +} + + +/* +** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a P21 +** object that is the result of running the RFC 7396 MergePatch() algorithm +** on the two arguments. +*/ +static void p21PatchFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse x; /* The P21 that is being patched */ + P21Parse y; /* The patch */ + P21Node *pResult; /* The result of the merge */ + + UNUSED_PARAM(argc); + if( p21Parse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + if( p21Parse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ + p21ParseReset(&x); + return; + } + pResult = p21MergePatch(&x, 0, y.aNode); + assert( pResult!=0 || x.oom ); + if( pResult ){ + p21ReturnP21(pResult, ctx, 0); + }else{ + sqlite3_result_error_nomem(ctx); + } + p21ParseReset(&x); + p21ParseReset(&y); +} +#endif + +/* +** Implementation of the p21_object(NAME,VALUE,...) function. Return a P21 +** object that contains all name/value given in arguments. Or if any name +** is not a string or if any value is a BLOB, throw an error. +*/ +static void p21ObjectFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + int i; + P21String jx; + const char *z; + u32 n; + + if( argc&1 ){ + sqlite3_result_error(ctx, "p21_object() requires an even number " + "of arguments", -1); + return; + } + p21Init(&jx, ctx); + p21AppendChar(&jx, '{'); + for(i=0; ijnFlags |= PNODE_REMOVE; + } + if( (x.aNode[0].jnFlags & PNODE_REMOVE)==0 ){ + p21ReturnP21(x.aNode, ctx, 0); + } +remove_done: + p21ParseReset(&x); +} + +/* +** p21_replace(P21, PATH, VALUE, ...) +** +** Replace the value at PATH with VALUE. If PATH does not already exist, +** this routine is a no-op. If P21 or PATH is malformed, throw an error. +*/ +static void p21ReplaceFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse x; /* The parse */ + P21Node *pNode; + const char *zPath; + u32 i; + + if( argc<1 ) return; + if( (argc&1)==0 ) { + p21WrongNumArgs(ctx, "replace"); + return; + } + if( p21Parse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + assert( x.nNode ); + for(i=1; i<(u32)argc; i+=2){ + zPath = (const char*)sqlite3_value_text(argv[i]); + pNode = p21Lookup(&x, zPath, 0, ctx); + if( x.nErr ) goto replace_err; + if( pNode ){ + pNode->jnFlags |= (u8)PNODE_REPLACE; + pNode->u.iReplace = i + 1; + } + } + if( x.aNode[0].jnFlags & PNODE_REPLACE ){ + sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); + }else{ + p21ReturnP21(x.aNode, ctx, argv); + } +replace_err: + p21ParseReset(&x); +} + +/* +** p21_set(P21, PATH, VALUE, ...) +** +** Set the value at PATH to VALUE. Create the PATH if it does not already +** exist. Overwrite existing values that do exist. +** If P21 or PATH is malformed, throw an error. +** +** p21_insert(P21, PATH, VALUE, ...) +** +** Create PATH and initialize it to VALUE. If PATH already exists, this +** routine is a no-op. If P21 or PATH is malformed, throw an error. +*/ +static void p21SetFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse x; /* The parse */ + P21Node *pNode; + const char *zPath; + u32 i; + int bApnd; + int bIsSet = *(int*)sqlite3_user_data(ctx); + + if( argc<1 ) return; + if( (argc&1)==0 ) { + p21WrongNumArgs(ctx, bIsSet ? "set" : "insert"); + return; + } + if( p21Parse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; + assert( x.nNode ); + for(i=1; i<(u32)argc; i+=2){ + zPath = (const char*)sqlite3_value_text(argv[i]); + bApnd = 0; + pNode = p21Lookup(&x, zPath, &bApnd, ctx); + if( x.oom ){ + sqlite3_result_error_nomem(ctx); + goto p21SetDone; + }else if( x.nErr ){ + goto p21SetDone; + }else if( pNode && (bApnd || bIsSet) ){ + pNode->jnFlags |= (u8)PNODE_REPLACE; + pNode->u.iReplace = i + 1; + } + } + if( x.aNode[0].jnFlags & PNODE_REPLACE ){ + sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]); + }else{ + p21ReturnP21(x.aNode, ctx, argv); + } +p21SetDone: + p21ParseReset(&x); +} + +/* +** p21_type(P21) +** p21_type(P21, PATH) +** +** Return the top-level "type" of a P21 string. Throw an error if +** either the P21 or PATH inputs are not well-formed. +*/ +static void p21TypeFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse *p; /* The parse */ + const char *zPath; + P21Node *pNode; + + p = p21ParseCached(ctx, argv, ctx); + if( p==0 ) return; + if( argc==2 ){ + zPath = (const char*)sqlite3_value_text(argv[1]); + pNode = p21Lookup(p, zPath, 0, ctx); + }else{ + pNode = p->aNode; + } + if( pNode ){ + sqlite3_result_text(ctx, p21Type[pNode->eType], -1, SQLITE_STATIC); + } +} + +/* +** p21_valid(P21) +** +** Return 1 if P21 is a well-formed P21 string according to RFC-7159. +** Return 0 otherwise. +*/ +static void p21ValidFunc( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21Parse *p; /* The parse */ + UNUSED_PARAM(argc); + p = p21ParseCached(ctx, argv, 0); + sqlite3_result_int(ctx, p!=0); +} + + +/**************************************************************************** +** Aggregate SQL function implementations +****************************************************************************/ +/* +** p21_group_array(VALUE) +** +** Return a P21 array composed of all values in the aggregate. +*/ +static void p21ArrayStep( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21String *pStr; + UNUSED_PARAM(argc); + pStr = (P21String*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); + if( pStr ){ + if( pStr->zBuf==0 ){ + p21Init(pStr, ctx); + p21AppendChar(pStr, '['); + }else if( pStr->nUsed>1 ){ + p21AppendChar(pStr, ','); + pStr->pCtx = ctx; + } + p21AppendValue(pStr, argv[0]); + } +} +static void p21ArrayCompute(sqlite3_context *ctx, int isFinal){ + P21String *pStr; + pStr = (P21String*)sqlite3_aggregate_context(ctx, 0); + if( pStr ){ + pStr->pCtx = ctx; + p21AppendChar(pStr, ']'); + if( pStr->bErr ){ + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); + assert( pStr->bStatic ); + }else if( isFinal ){ + sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, + pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic = 1; + }else{ + sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); + pStr->nUsed--; + } + }else{ + sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC); + } + sqlite3_result_subtype(ctx, P21_SUBTYPE); +} +static void p21ArrayValue(sqlite3_context *ctx){ + p21ArrayCompute(ctx, 0); +} +static void p21ArrayFinal(sqlite3_context *ctx){ + p21ArrayCompute(ctx, 1); +} + +#ifndef SQLITE_OMIT_WINDOWFUNC +/* +** This method works for both p21_group_array() and p21_group_object(). +** It works by removing the first element of the group by searching forward +** to the first comma (",") that is not within a string and deleting all +** text through that comma. +*/ +static void p21GroupInverse( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + unsigned int i; + int inStr = 0; + int nNest = 0; + char *z; + char c; + P21String *pStr; + UNUSED_PARAM(argc); + UNUSED_PARAM(argv); + pStr = (P21String*)sqlite3_aggregate_context(ctx, 0); +#ifdef NEVER + /* pStr is always non-NULL since p21ArrayStep() or p21ObjectStep() will + ** always have been called to initalize it */ + if( NEVER(!pStr) ) return; +#endif + z = pStr->zBuf; + for(i=1; (c = z[i])!=',' || inStr || nNest; i++){ + if( i>=pStr->nUsed ){ + pStr->nUsed = 1; + return; + } + if( c=='"' ){ + inStr = !inStr; + }else if( c=='\\' ){ + i++; + }else if( !inStr ){ + if( c=='{' || c=='[' ) nNest++; + if( c=='}' || c==']' ) nNest--; + } + } + pStr->nUsed -= i; + memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1); +} +#else +# define p21GroupInverse 0 +#endif + + +/* +** p21_group_obj(NAME,VALUE) +** +** Return a P21 object composed of all names and values in the aggregate. +*/ +static void p21ObjectStep( + sqlite3_context *ctx, + int argc, + sqlite3_value **argv +){ + P21String *pStr; + const char *z; + u32 n; + UNUSED_PARAM(argc); + pStr = (P21String*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); + if( pStr ){ + if( pStr->zBuf==0 ){ + p21Init(pStr, ctx); + p21AppendChar(pStr, '{'); + }else if( pStr->nUsed>1 ){ + p21AppendChar(pStr, ','); + pStr->pCtx = ctx; + } + z = (const char*)sqlite3_value_text(argv[0]); + n = (u32)sqlite3_value_bytes(argv[0]); + p21AppendString(pStr, z, n); + p21AppendChar(pStr, ':'); + p21AppendValue(pStr, argv[1]); + } +} +static void p21ObjectCompute(sqlite3_context *ctx, int isFinal){ + P21String *pStr; + pStr = (P21String*)sqlite3_aggregate_context(ctx, 0); + if( pStr ){ + p21AppendChar(pStr, '}'); + if( pStr->bErr ){ + if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx); + assert( pStr->bStatic ); + }else if( isFinal ){ + sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, + pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free); + pStr->bStatic = 1; + }else{ + sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT); + pStr->nUsed--; + } + }else{ + sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC); + } + sqlite3_result_subtype(ctx, P21_SUBTYPE); +} +static void p21ObjectValue(sqlite3_context *ctx){ + p21ObjectCompute(ctx, 0); +} +static void p21ObjectFinal(sqlite3_context *ctx){ + p21ObjectCompute(ctx, 1); +} + + + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/**************************************************************************** +** The p21_each virtual table +****************************************************************************/ +typedef struct P21EachCursor P21EachCursor; +struct P21EachCursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + u32 iRowid; /* The rowid */ + u32 iBegin; /* The first node of the scan */ + u32 i; /* Index in sParse.aNode[] of current row */ + u32 iEnd; /* EOF when i equals or exceeds this value */ + u8 eType; /* Type of top-level element */ + char *zP21; /* Input P21 */ + char *zRoot; /* Path by which to filter zP21 */ + P21Parse sParse; /* Parse of the input P21 */ +}; + +/* Constructor for the p21_each virtual table */ +static int p21EachConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + sqlite3_vtab *pNew; + int rc; + +/* Column numbers */ +#define PEACH_KEY 0 +#define PEACH_VALUE 1 +#define PEACH_TYPE 2 +#define PEACH_ATOM 3 +#define PEACH_ID 4 +#define PEACH_PARENT 5 +#define PEACH_FULLKEY 6 +#define PEACH_PATH 7 +/* The xBestIndex method assumes that the P21 and ROOT columns are +** the last two columns in the table. Should this ever changes, be +** sure to update the xBestIndex method. */ +#define PEACH_P21 8 +#define PEACH_ROOT 9 + + UNUSED_PARAM(pzErr); + UNUSED_PARAM(argv); + UNUSED_PARAM(argc); + UNUSED_PARAM(pAux); + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," + "p21 HIDDEN,root HIDDEN)"); + if( rc==SQLITE_OK ){ + pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS); + } + return rc; +} + +/* destructor for p21_each virtual table */ +static int p21EachDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* constructor for a P21EachCursor object for p21_each(). */ +static int p21EachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + P21EachCursor *pCur; + + UNUSED_PARAM(p); + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* Reset a P21EachCursor back to its original state. Free any memory +** held. */ +static void p21EachCursorReset(P21EachCursor *p){ + sqlite3_free(p->zP21); + sqlite3_free(p->zRoot); + p21ParseReset(&p->sParse); + p->iRowid = 0; + p->i = 0; + p->iEnd = 0; + p->eType = 0; + p->zP21 = 0; + p->zRoot = 0; +} + +/* Destructor for a p21EachCursor object */ +static int p21EachClose(sqlite3_vtab_cursor *cur){ + P21EachCursor *p = (P21EachCursor*)cur; + p21EachCursorReset(p); + sqlite3_free(cur); + return SQLITE_OK; +} + +/* Return TRUE if the p21EachCursor object has been advanced off the end +** of the P21 object */ +static int p21EachEof(sqlite3_vtab_cursor *cur){ + P21EachCursor *p = (P21EachCursor*)cur; + return p->i >= p->iEnd; +} + +/* Advance the cursor to the next element for p21_tree() */ +static int p21EachNext(sqlite3_vtab_cursor *cur){ + P21EachCursor *p = (P21EachCursor*)cur; + switch( p->eType ){ + case P21_RECORD: + case P21_LIST: { + p->i += p21NodeSize(&p->sParse.aNode[p->i]); + p->iRowid++; + break; + } + default: { + p->i = p->iEnd; + break; + } + } + return SQLITE_OK; +} + +/* Append the name of the path for element i to pStr +*/ +static void p21EachComputePath( + P21EachCursor *p, /* The cursor */ + P21String *pStr, /* Write the path here */ + u32 i /* Path to this element */ +){ + P21Node *pNode, *pUp; + u32 iUp; + if( i==0 ){ + p21AppendChar(pStr, '$'); + return; + } + iUp = p->sParse.aUp[i]; + p21EachComputePath(p, pStr, iUp); + pNode = &p->sParse.aNode[i]; + pUp = &p->sParse.aNode[iUp]; + if( pUp->eType==P21_LIST ){ + p21Printf(30, pStr, "[%d]", pUp->u.iKey); + }else{ + assert( pUp->eType==P21_RECORD ); + if( (pNode->jnFlags & PNODE_LABEL)==0 ) pNode--; + assert( pNode->eType==P21_STRING ); + assert( pNode->jnFlags & PNODE_LABEL ); + p21Printf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1); + } +} + +/* Return the value of a column */ +static int p21EachColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ +){ + P21EachCursor *p = (P21EachCursor*)cur; + P21Node *pThis = &p->sParse.aNode[p->i]; + switch( i ){ + case PEACH_KEY: { + if( p->i==0 ) break; + if( p->eType==P21_RECORD ){ + p21Return(pThis, ctx, 0); + }else if( p->eType==P21_LIST ){ + u32 iKey; + iKey = p->iRowid; + sqlite3_result_int64(ctx, (sqlite3_int64)iKey); + } + break; + } + case PEACH_VALUE: { + if( pThis->jnFlags & PNODE_LABEL ) pThis++; + p21Return(pThis, ctx, 0); + break; + } + case PEACH_TYPE: { + if( pThis->jnFlags & PNODE_LABEL ) pThis++; + sqlite3_result_text(ctx, p21Type[pThis->eType], -1, SQLITE_STATIC); + break; + } + case PEACH_ATOM: { + if( pThis->jnFlags & PNODE_LABEL ) pThis++; + if( pThis->eType>=P21_LIST ) break; + p21Return(pThis, ctx, 0); + break; + } + case PEACH_ID: { + sqlite3_result_int64(ctx, + (sqlite3_int64)p->i + ((pThis->jnFlags & PNODE_LABEL)!=0)); + break; + } + case PEACH_FULLKEY: { + P21String x; + p21Init(&x, ctx); + if( p->zRoot ){ + p21AppendRaw(&x, p->zRoot, (int)strlen(p->zRoot)); + }else{ + p21AppendChar(&x, '$'); + } + if( p->eType==P21_LIST ){ + p21Printf(30, &x, "[%d]", p->iRowid); + }else if( p->eType==P21_RECORD ){ + p21Printf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); + } + p21Result(&x); + break; + } + case PEACH_PATH: + default: { + const char *zRoot = p->zRoot; + if( zRoot==0 ) zRoot = "$"; + sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC); + break; + } + case PEACH_P21: { + assert( i==PEACH_P21 ); + sqlite3_result_text(ctx, p->sParse.zP21, -1, SQLITE_STATIC); + break; + } + } + return SQLITE_OK; +} + +/* Return the current rowid value */ +static int p21EachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + P21EachCursor *p = (P21EachCursor*)cur; + *pRowid = p->iRowid; + return SQLITE_OK; +} + +/* The query strategy is to look for an equality constraint on the p21 +** column. Without such a constraint, the table cannot operate. idxNum is +** 1 if the constraint is found, 3 if the constraint and zRoot are found, +** and 0 otherwise. +*/ +static int p21EachBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + int i; /* Loop counter or computed array index */ + int aIdx[2]; /* Index of constraints for P21 and ROOT */ + int unusableMask = 0; /* Mask of unusable P21 and ROOT constraints */ + int idxMask = 0; /* Mask of usable == constraints P21 and ROOT */ + const struct sqlite3_index_constraint *pConstraint; + + /* This implementation assumes that P21 and ROOT are the last two + ** columns in the table */ + assert( PEACH_ROOT == PEACH_P21+1 ); + UNUSED_PARAM(tab); + aIdx[0] = aIdx[1] = -1; + pConstraint = pIdxInfo->aConstraint; + for(i=0; inConstraint; i++, pConstraint++){ + int iCol; + int iMask; + if( pConstraint->iColumn < PEACH_P21 ) continue; + iCol = pConstraint->iColumn - PEACH_P21; + assert( iCol==0 || iCol==1 ); + iMask = 1 << iCol; + if( pConstraint->usable==0 ){ + unusableMask |= iMask; + }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + aIdx[iCol] = i; + idxMask |= iMask; + } + } + if( (unusableMask & ~idxMask)!=0 ){ + /* If there are any unusable constraints on P21 or ROOT, then reject + ** this entire plan */ + return SQLITE_CONSTRAINT; + } + if( aIdx[0]<0 ){ + /* No P21 input. Leave estimatedCost at the huge value that it was + ** initialized to to discourage the query planner from selecting this + ** plan. */ + pIdxInfo->idxNum = 0; + }else{ + pIdxInfo->estimatedCost = 1.0; + i = aIdx[0]; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; + pIdxInfo->aConstraintUsage[i].omit = 1; + if( aIdx[1]<0 ){ + pIdxInfo->idxNum = 1; /* Only P21 supplied. Plan 1 */ + }else{ + i = aIdx[1]; + pIdxInfo->aConstraintUsage[i].argvIndex = 2; + pIdxInfo->aConstraintUsage[i].omit = 1; + pIdxInfo->idxNum = 3; /* Both P21 and ROOT are supplied. Plan 3 */ + } + } + return SQLITE_OK; +} + +/* Start a search on a new P21 string */ +static int p21EachFilter( + sqlite3_vtab_cursor *cur, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + P21EachCursor *p = (P21EachCursor*)cur; + const char *z; + const char *zRoot = 0; + sqlite3_int64 n; + + UNUSED_PARAM(idxStr); + UNUSED_PARAM(argc); + p21EachCursorReset(p); + if( idxNum==0 ) return SQLITE_OK; + z = (const char*)sqlite3_value_text(argv[0]); + if( z==0 ) return SQLITE_OK; + n = sqlite3_value_bytes(argv[0]); + p->zP21 = sqlite3_malloc64( n+1 ); + if( p->zP21==0 ) return SQLITE_NOMEM; + memcpy(p->zP21, z, (size_t)n+1); + if( p21Parse(&p->sParse, 0, p->zP21) ){ + int rc = SQLITE_NOMEM; + if( p->sParse.oom==0 ){ + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = sqlite3_mprintf("malformed P21"); + if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR; + } + p21EachCursorReset(p); + return rc; + }else{ + P21Node *pNode = 0; + if( idxNum==3 ){ + const char *zErr = 0; + zRoot = (const char*)sqlite3_value_text(argv[1]); + if( zRoot==0 ) return SQLITE_OK; + n = sqlite3_value_bytes(argv[1]); + p->zRoot = sqlite3_malloc64( n+1 ); + if( p->zRoot==0 ) return SQLITE_NOMEM; + memcpy(p->zRoot, zRoot, (size_t)n+1); + if( zRoot[0]!='$' ){ + zErr = zRoot; + }else{ + pNode = p21LookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr); + } + if( zErr ){ + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = p21PathSyntaxError(zErr); + p21EachCursorReset(p); + return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; + }else if( pNode==0 ){ + return SQLITE_OK; + } + }else{ + pNode = p->sParse.aNode; + } + p->iBegin = p->i = (int)(pNode - p->sParse.aNode); + p->eType = pNode->eType; + if( p->eType>=P21_LIST ){ + pNode->u.iKey = 0; + p->iEnd = p->i + pNode->n + 1; + p->i++; + }else{ + p->iEnd = p->i+1; + } + } + return SQLITE_OK; +} + +/* The methods of the p21_each virtual table */ +static sqlite3_module p21EachModule = { + 0, /* iVersion */ + 0, /* xCreate */ + p21EachConnect, /* xConnect */ + p21EachBestIndex, /* xBestIndex */ + p21EachDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + p21EachOpenEach, /* xOpen - open a cursor */ + p21EachClose, /* xClose - close a cursor */ + p21EachFilter, /* xFilter - configure scan constraints */ + p21EachNext, /* xNext - advance a cursor */ + p21EachEof, /* xEof - check for end of scan */ + p21EachColumn, /* xColumn - read data */ + p21EachRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ +}; + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +/**************************************************************************** +** The following routines are the only publically visible identifiers in this +** file. Call the following routines in order to register the various SQL +** functions and the virtual table implemented by this file. +****************************************************************************/ + +int sqlite3P21sqlInit(sqlite3 *db){ + int rc = SQLITE_OK; + unsigned int i; + static const struct { + const char *zName; + int nArg; + int flag; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } aFunc[] = { + { "p21", 1, 0, p21RemoveFunc }, + { "p21_array", -1, 0, p21ArrayFunc }, + { "p21_array_length", 1, 0, p21ArrayLengthFunc }, + { "p21_array_length", 2, 0, p21ArrayLengthFunc }, + { "p21_extract", -1, 0, p21ExtractFunc }, + { "p21_insert", -1, 0, p21SetFunc }, + { "p21_object", -1, 0, p21ObjectFunc }, +#if 0 + { "p21_patch", 2, 0, p21PatchFunc }, +#endif + { "p21_quote", 1, 0, p21QuoteFunc }, + { "p21_remove", -1, 0, p21RemoveFunc }, + { "p21_replace", -1, 0, p21ReplaceFunc }, + { "p21_set", -1, 1, p21SetFunc }, + { "p21_type", 1, 0, p21TypeFunc }, + { "p21_type", 2, 0, p21TypeFunc }, + { "p21_valid", 1, 0, p21ValidFunc }, + +#if SQLITE_DEBUG + /* DEBUG and TESTING functions */ + { "p21_parse", 1, 0, p21ParseFunc }, + { "p21_test1", 1, 0, p21Test1Func }, +#endif + }; + static const struct { + const char *zName; + int nArg; + void (*xStep)(sqlite3_context*,int,sqlite3_value**); + void (*xFinal)(sqlite3_context*); + void (*xValue)(sqlite3_context*); + } aAgg[] = { + { "p21_group_array", 1, + p21ArrayStep, p21ArrayFinal, p21ArrayValue }, + { "p21_group_object", 2, + p21ObjectStep, p21ObjectFinal, p21ObjectValue }, + }; +#ifndef SQLITE_OMIT_VIRTUALTABLE + static const struct { + const char *zName; + sqlite3_module *pModule; + } aMod[] = { + { "p21_each", &p21EachModule }, + }; +#endif + static const int enc = + SQLITE_UTF8 | + SQLITE_DETERMINISTIC | + SQLITE_INNOCUOUS; + for(i=0; i 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 HOLDER 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. + +import unittest +from stepcode.Part21 import Parser + +ShapesSample =""" +ISO-10303-21; +HEADER; +FILE_DESCRIPTION(('simple example file'),'1'); +FILE_NAME('testfile.step','1997-10-06T16:15:42',('long forgotten'),('nist'),'0','1','2'); +FILE_SCHEMA(('example_schema')); +ENDSEC; +DATA; +#0=SQUARE('Square9',.BROWN.,13,15.,51.); +#1=CIRCLE('Circle8',.ORANGE.,19,12.); +#2=TRIANGLE('Triangle7',.BLACK.,67,84.,60.,25.); +#3=LINE(#6,#7); +#4=SHAPE('Shape4',.WHITE.,83); +#5=RECTANGLE('Rectangle8',.BROWN.,66,78.,95.); +#6=CARTESIAN_POINT(11.,67.,54.); +#7=CARTESIAN_POINT(1.,2.,3.); +ENDSEC; +END-ISO-10303-21; +""" + +class TestSample(unittest.TestCase): + def setUp(self): + self.parser = Parser() + def tearDown(self): + self.parser = None + + +class TestShapesParse(TestSample): + """ + Tests whether we're able to parse the shapes sample at all + """ + def test_parse(self): + model = self.parser.parse(ShapesSample) + self.assertIsNotNone(model) + + +class TestShapesHeader(TestSample): + """ + Test basic structure and payload of Header section + """ + def test_header_name(self): + model = self.parser.parse(ShapesSample) + self.assertEqual(model.header.file_name.params[0][0], "testfile.step") + + def test_header_schema(self): + model = self.parser.parse(ShapesSample) + self.assertEqual(model.header.file_schema.params[0][0][0], "example_schema") + + +class TestShapesData(TestSample): + """ + Test basic structure and shape of data section + """ + def test_data_section_form(self): + model = self.parser.parse(ShapesSample) + self.assertEqual(len(model.sections), 1) + self.assertEqual(len(model.sections[0].entities), 8) + + +class TestEntity(TestSample): + """ + Test structure and contents of several entities within the DATA section + """ + def test_line(self): + model = self.parser.parse(ShapesSample) + line = model.sections[0].entities[3] + self.assertEqual(line.type_name, "LINE") + self.assertEqual(line.ref, "#3") + self.assertEqual(line.params[0], ["#6", "#7"]) + + def test_rectangle8(self): + model = self.parser.parse(ShapesSample) + rect8 = model.sections[0].entities[5] + self.assertEqual(rect8.type_name, "RECTANGLE") + self.assertEqual(rect8.ref, "#5") + self.assertEqual(rect8.params[0], ['Rectangle8', '.BROWN.', 66, 78.0, 95.0]) + diff --git a/src/exp2python/test/test_unitary_schemas.py b/src/exp2python/python/tests/test_unitary_schemas.py similarity index 97% rename from src/exp2python/test/test_unitary_schemas.py rename to src/exp2python/python/tests/test_unitary_schemas.py index 6d5f7f23f..077644253 100644 --- a/src/exp2python/test/test_unitary_schemas.py +++ b/src/exp2python/python/tests/test_unitary_schemas.py @@ -1,7 +1,7 @@ # Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) # All rights reserved. -# This file is part StepClassLibrary (SCL). +# This file is part of the STEPCODE project. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -31,14 +31,16 @@ import unittest import sys -sys.path.append('../examples/unitary_schemas') - -from SCL.SCLBase import * -from SCL.SimpleDataTypes import * -from SCL.ConstructedDataTypes import * -from SCL.AggregationDataTypes import * -from SCL.TypeChecker import check_type -from SCL.Expr import * +import os + +here = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(here, "..", "..", "examples", "unitary_schemas")) + +from stepcode.SCLBase import * +from stepcode.SimpleDataTypes import * +from stepcode.ConstructedDataTypes import * +from stepcode.AggregationDataTypes import * +from stepcode.TypeChecker import check_type class TestSelectDataType(unittest.TestCase): ''' diff --git a/src/exp2python/src/classes_misc_python.c b/src/exp2python/src/classes_misc_python.c index a425f0d88..7c57c5257 100644 --- a/src/exp2python/src/classes_misc_python.c +++ b/src/exp2python/src/classes_misc_python.c @@ -1,5 +1,7 @@ #define CLASSES_MISC_C +#define _POSIX_C_SOURCE 200809L #include +#include #include "classes.h" /******************************************************************* ** FedEx parser output module for generating C++ class definitions @@ -111,7 +113,7 @@ ToUpper( char c ) { const char * StrToLower( const char * word ) { - static char newword [MAX_LEN]; + static char newword [MAX_LEN+1]; int i = 0; if( !word ) { return 0; @@ -126,7 +128,7 @@ StrToLower( const char * word ) { } const char * StrToUpper( const char * word ) { - static char newword [MAX_LEN]; + static char newword [MAX_LEN+1]; int i = 0; char ToUpper( char c ); @@ -140,7 +142,7 @@ const char * StrToUpper( const char * word ) { } const char * StrToConstant( const char * word ) { - static char newword [MAX_LEN]; + static char newword [MAX_LEN+1]; int i = 0; while( word [i] != '\0' ) { @@ -194,7 +196,7 @@ int isAggregateType( const Type t ) { */ const char * ClassName( const char * oldname ) { int i = 0, j = 0; - static char newname [BUFSIZ]; + static char newname [BUFSIZ+1]; if( !oldname ) { return ( "" ); } @@ -221,7 +223,7 @@ const char * ENTITYget_classname( Entity ent ) { /** returns a new capitalized name, in internal static buffer */ const char * PrettyTmpName( const char * oldname ) { int i = 0; - static char newname [BUFSIZ]; + static char newname [BUFSIZ+1]; newname [0] = '\0'; while( ( oldname [i] != '\0' ) && ( i < BUFSIZ ) ) { newname [i] = ToLower( oldname [i] ); @@ -242,7 +244,7 @@ const char * PrettyTmpName( const char * oldname ) { /** This function is out of date DAS */ const char * EnumName( const char * oldname ) { int j = 0; - static char newname [MAX_LEN]; + static char newname [MAX_LEN+1]; if( !oldname ) { return ( "" ); } @@ -258,7 +260,7 @@ const char * EnumName( const char * oldname ) { const char * SelectName( const char * oldname ) { int j = 0; - static char newname [MAX_LEN]; + static char newname [MAX_LEN+1]; if( !oldname ) { return ( "" ); } @@ -274,7 +276,7 @@ const char * SelectName( const char * oldname ) { } const char * FirstToUpper( const char * word ) { - static char newword [MAX_LEN]; + static char newword [MAX_LEN+1]; strncpy( newword, word, MAX_LEN ); newword[0] = ToUpper( newword[0] ); @@ -332,7 +334,7 @@ const char * FundamentalType( const Type t, int report_reftypes ) { * the dictionary. */ const char * TypeDescriptorName( Type t ) { - static char b [BUFSIZ]; + static char b [BUFSIZ+1]; Schema parent = t->superscope; /* NOTE - I corrected a prev bug here in which the *current* schema was ** passed to this function. Now we take "parent" - the schema in which @@ -345,7 +347,7 @@ const char * TypeDescriptorName( Type t ) { ** by following through the entity they reference, as above. */ } - sprintf( b, "%s%s%s", SCHEMAget_name( parent ), TYPEprefix( t ), + snprintf( b, sizeof(b), "%s%s%s", SCHEMAget_name( parent ), TYPEprefix( t ), TYPEget_name( t ) ); return b; } diff --git a/src/exp2python/src/classes_python.c b/src/exp2python/src/classes_python.c index 7a6eb6df6..74001dfcd 100644 --- a/src/exp2python/src/classes_python.c +++ b/src/exp2python/src/classes_python.c @@ -24,10 +24,11 @@ N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. /* this is used to add new dictionary calls */ /* #define NEWDICT */ +#define _POSIX_C_SOURCE 200809L #include +#include #include -#include "sc_memmgr.h" #include "classes.h" #include "expr.h" @@ -44,11 +45,6 @@ N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. #define PAD 1 #define NOPAD 0 -#if defined(_MSC_VER) && _MSC_VER < 1900 -# include "sc_stdio.h" -# define snprintf c99_snprintf -#endif - int isAggregateType( const Type t ); int isAggregate( Variable a ); Variable VARis_type_shifter( Variable a ); @@ -175,7 +171,7 @@ int Handle_FedPlus_Args( int i, char * arg ) { bool is_python_keyword( char * word ) { int i; - const char* keyword_list[] = {"class", "pass", NULL}; + const char* keyword_list[] = {"class", "pass", "property", NULL}; bool python_keyword = false; for( i = 0; keyword_list[i] != NULL; i++ ) { @@ -368,7 +364,7 @@ char* EXPRto_python( Expression e ) { char * temp; unsigned int bufsize = BIGBUFSIZ; - buf = ( char * )sc_malloc( bufsize ); + buf = ( char * )malloc( bufsize ); if( !buf ) { fprintf( stderr, "%s failed to allocate buffer: %s\n", __func__, strerror( errno ) ); abort(); @@ -429,7 +425,7 @@ char* EXPRto_python( Expression e ) { snprintf( buf, bufsize, "%s.%s", TYPEget_name(e->type), e->symbol.name ); break; case query_: - strcpy( buf, "# query_ NOT_IMPLEMENTED!" ); + strcpy( buf, "SCLBase.raise_(NotImplementedError('query_'))" ); break; case self_: strcpy( buf, "self" ); @@ -451,13 +447,13 @@ char* EXPRto_python( Expression e ) { break; } case op_: - strcpy( buf, "# op_ NOT_IMPLEMENTED!" ); + strcpy( buf, "SCLBase.raise_(NotImplementedError('op_'))" ); break; case aggregate_: - strcpy( buf, "# aggregate_ NOT_IMPLEMENTED!" ); + strcpy( buf, "SCLBase.raise_(NotImplementedError('aggregate_'))" ); break; case oneof_: { - strcpy( buf, "# oneof_ NOT_IMPLEMENTED!" ); + strcpy( buf, "SCLBase.raise_(NotImplementedError('oneof_'))" ); break; } default: @@ -465,7 +461,7 @@ char* EXPRto_python( Expression e ) { abort(); } - temp = ( char * )sc_realloc( buf, 1 + strlen(buf) ); + temp = ( char * )realloc( buf, 1 + strlen(buf) ); if( temp == 0 ) { fprintf( stderr, "%s failed to realloc buffer: %s\n", __func__, strerror( errno ) ); abort(); @@ -556,7 +552,7 @@ int cmp_python_mro( void * e1, void * e2 ) { void LIBdescribe_entity( Entity entity, FILE * file ) { int attr_count_tmp = attr_count; - char attrnm [BUFSIZ], parent_attrnm[BUFSIZ]; + char attrnm [BUFSIZ+1], parent_attrnm[BUFSIZ+1]; char * attr_type; bool generate_constructor = true; /*by default, generates a python constructor */ bool single_inheritance = false; @@ -762,7 +758,7 @@ LIBdescribe_entity( Entity entity, FILE * file ) { /* if the argument is not optional */ if( !VARget_optional( v ) ) { fprintf( file, "\t\t# Mandatory argument\n" ); - fprintf( file, "\t\tassert value != None, 'Argument \"value\" is mandatory and cannot be set to None'\n" ); + fprintf( file, "\t\tassert value is not None, 'Argument \"value\" is mandatory and cannot be set to None'\n" ); fprintf( file, "\t\tif not check_type(value," ); if( TYPEis_aggregate( t ) ) { process_aggregate( file, t ); @@ -773,7 +769,7 @@ LIBdescribe_entity( Entity entity, FILE * file ) { fprintf( file, "%s):\n", attr_type ); } } else { - fprintf( file, "\t\tif value != None: # OPTIONAL attribute\n\t" ); + fprintf( file, "\t\tif value is not None: # OPTIONAL attribute\n\t" ); fprintf( file, "\t\tif not check_type(value," ); if( TYPEis_aggregate( t ) ) { process_aggregate( file, t ); @@ -1104,6 +1100,7 @@ LOOPpyout( struct Loop_ *loop, int level, FILE * file ) { fprintf( file, "):\n" ); if( loop->while_expr ) { + python_indent( file, level + 1 ); fprintf( file, "if " ); EXPRESSION_out( loop->while_expr, 0 , file ); fprintf( file, ":\n"); @@ -1113,9 +1110,12 @@ LOOPpyout( struct Loop_ *loop, int level, FILE * file ) { } if( loop->until_expr ) { + python_indent( file, level + 1 ); fprintf( file, "if " ); EXPRESSION_out( loop->until_expr, 0 , file ); - fprintf( file, ":\n\tbreak\n"); + fprintf( file, ":\n" ); + python_indent( file, level + 2 ); + fprintf( file, "break\n" ); } } else if( loop->while_expr ) { fprintf( file, "while " ); @@ -1124,17 +1124,23 @@ LOOPpyout( struct Loop_ *loop, int level, FILE * file ) { STATEMENTlist_out( loop->statements, level + 1 , file ); if( loop->until_expr ) { + python_indent( file, level + 1 ); fprintf( file, "if " ); EXPRESSION_out( loop->until_expr, 0 , file ); - fprintf( file, ":\n\tbreak\n"); + fprintf( file, ":\n" ); + python_indent( file, level + 2 ); + fprintf( file, "break\n" ); } } else { fprintf( file, "while True:\n" ); STATEMENTlist_out( loop->statements, level + 1 , file ); + python_indent( file, level + 1 ); fprintf( file, "if " ); EXPRESSION_out( loop->until_expr, 0 , file ); - fprintf( file, ":\n\tbreak\n"); + fprintf( file, ":\n" ); + python_indent( file, level + 2 ); + fprintf( file, "break\n" ); } } @@ -1199,7 +1205,11 @@ ATTRIBUTE_INITIALIZER__out( Expression e, int paren, int previous_op , FILE * fi break; case entity_: case identifier_: - fprintf( file, "self.%s", e->symbol.name ); + if( previous_op == OP_DOT || previous_op == OP_GROUP ) { + fprintf( file, "%s", e->symbol.name ); + } else { + fprintf( file, "self.%s", e->symbol.name ); + } break; case attribute_: fprintf( file, "%s", e->symbol.name ); @@ -1419,8 +1429,8 @@ ATTRIBUTE_INITIALIZERop__out( struct Op_Subexpression* oe, int paren, Op_Code pr ATTRIBUTE_INITIALIZERop2_out( oe, " > ", paren, PAD, file ); break; case OP_IN: - /* EXPRESSIONop2_out( oe, " in ", paren, PAD, file ); */ - /* break; */ + ATTRIBUTE_INITIALIZERop2_out( oe, " in ", paren, PAD, file ); + break; case OP_INST_EQUAL: ATTRIBUTE_INITIALIZERop2_out( oe, " == ", paren, PAD, file ); break; @@ -1455,7 +1465,10 @@ ATTRIBUTE_INITIALIZERop__out( struct Op_Subexpression* oe, int paren, Op_Code pr ATTRIBUTE_INITIALIZERop2_out( oe, ".", paren, NOPAD, file ); break; case OP_GROUP: - ATTRIBUTE_INITIALIZERop2_out( oe, ".", paren, NOPAD, file ); + ATTRIBUTE_INITIALIZER_out(oe->op1, 1, file); + fprintf(file, "._scl_group("); + EXPRESSION_out(oe->op2, 0, file); + fprintf(file, ")"); break; case OP_NEGATE: ATTRIBUTE_INITIALIZERop1_out( oe, "-", paren, file ); @@ -1501,7 +1514,7 @@ EXPRESSIONop__out( struct Op_Subexpression* oe, int paren, Op_Code previous_op, EXPRESSIONop2_out( oe, " * ", paren, PAD, file ); break; case OP_XOR: - EXPRESSIONop2__out( oe, " != ", paren, PAD, previous_op, file ); + EXPRESSIONop2_out( oe, " != ", paren, PAD, file ); break; case OP_EXP: EXPRESSIONop2_out( oe, " ** ", paren, PAD, file ); @@ -1513,8 +1526,8 @@ EXPRESSIONop__out( struct Op_Subexpression* oe, int paren, Op_Code previous_op, EXPRESSIONop2_out( oe, " > ", paren, PAD, file ); break; case OP_IN: - /* EXPRESSIONop2_out( oe, " in ", paren, PAD, file ); */ - /* break; */ + EXPRESSIONop2_out( oe, " in ", paren, PAD, file ); + break; case OP_INST_EQUAL: EXPRESSIONop2_out( oe, " == ", paren, PAD, file ); break; @@ -1532,8 +1545,7 @@ EXPRESSIONop__out( struct Op_Subexpression* oe, int paren, Op_Code previous_op, EXPRESSIONop2_out( oe, " % ", paren, PAD, file ); break; case OP_NOT_EQUAL: - /*EXPRESSIONop2_out( oe, ( char * )0, paren, PAD ,file); */ - EXPRESSIONop2_out( oe, " != ", paren, PAD , file ); + EXPRESSIONop2_out( oe, " != ", paren, PAD, file ); break; case OP_NOT: EXPRESSIONop1_out( oe, " not ", paren, file ); @@ -1549,7 +1561,10 @@ EXPRESSIONop__out( struct Op_Subexpression* oe, int paren, Op_Code previous_op, EXPRESSIONop2_out( oe, ".", paren, NOPAD, file ); break; case OP_GROUP: - EXPRESSIONop2_out( oe, ".", paren, NOPAD, file ); + EXPRESSION_out(oe->op1, 1, file); + fprintf(file, "._scl_group("); + EXPRESSION_out(oe->op2, 0, file); + fprintf(file, ")"); break; case OP_NEGATE: EXPRESSIONop1_out( oe, "-", paren, file ); @@ -1578,7 +1593,7 @@ EXPRESSIONop2__out( struct Op_Subexpression * eo, char * opcode, int paren, int if( pad && paren && ( eo->op_code != previous_op ) ) { fprintf( file, "(" ); } - EXPRESSION__out( eo->op1, 1, eo->op_code , file ); + EXPRESSION__out( eo->op1, 1, OP_UNKNOWN, file ); if( pad ) { fprintf( file, " " ); } @@ -1597,7 +1612,7 @@ ATTRIBUTE_INITIALIZERop2__out( struct Op_Subexpression * eo, char * opcode, int if( pad && paren && ( eo->op_code != previous_op ) ) { fprintf( file, "(" ); } - ATTRIBUTE_INITIALIZER__out( eo->op1, 1, eo->op_code , file ); + ATTRIBUTE_INITIALIZER__out( eo->op1, 1, OP_UNKNOWN, file ); if( pad ) { fprintf( file, " " ); } @@ -1658,8 +1673,8 @@ WHEREPrint( Linked_List wheres, int level , FILE * file ) { fprintf( file, "\tdef unnamed_wr_%i(self):\n", where_rule_number ); fprintf( file, "\t\teval_unnamed_wr_%i = ", where_rule_number ); } - /*EXPRESSION_out( w->expr, level+1 , file ); */ - ATTRIBUTE_INITIALIZER_out( w->expr, level + 1 , file ); + + ATTRIBUTE_INITIALIZER_out( w->expr, level + 1, file ); /* raise exception if rule violated */ if( strcmp( w->label->name, "" ) ) { fprintf( file, "\n\t\tif not eval_%s_wr:\n", w->label->name ); @@ -1755,7 +1770,7 @@ void strcat_expr( Expression e, char * buf ) { strcat( buf, TYPEget_name( e ) ); } else if( TYPEget_body( e->type )->type == integer_ ) { char tmpbuf[30]; - sprintf( tmpbuf, "%d", e->u.integer ); + snprintf( tmpbuf, sizeof(tmpbuf), "%d", e->u.integer ); strcat( buf, tmpbuf ); } else { strcat( buf, "??" ); @@ -1951,10 +1966,10 @@ int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ) { void TYPEprint_descriptions( const Type type, FILES * files, Schema schema ) { - char tdnm [BUFSIZ], - typename_buf [MAX_LEN], - base [BUFSIZ], - nm [BUFSIZ]; + char tdnm [BUFSIZ+1], + typename_buf [MAX_LEN+1], + base [BUFSIZ+1], + nm [BUFSIZ+1]; Type i; int where_rule_number = 0; @@ -1993,22 +2008,26 @@ TYPEprint_descriptions( const Type type, FILES * files, Schema schema ) { } else { fprintf( files->lib, "%s):\n", output ); } - fprintf( files->lib, "\tdef __init__(self,*kargs):\n" ); - fprintf( files->lib, "\t\tpass\n" ); - /* call the where / rules */ - LISTdo( type->where, w, Where ) - if( strcmp( w->label->name, "" ) ) { - /* define a function with the name 'label' */ - fprintf( files->lib, "\t\tself.%s()\n", w->label->name ); - } else { - /* no label */ - fprintf( files->lib, "\t\tself.unnamed_wr_%i()\n", where_rule_number ); - where_rule_number ++; + + if (LISTempty(type->where)) { + fprintf( files->lib, "\tpass\n" ); + } else { + fprintf( files->lib, "\tdef __init__(self, *args):\n" ); + /* call the where / rules */ + LISTdo( type->where, w, Where ) + if( strcmp( w->label->name, "" ) ) { + /* define a function with the name 'label' */ + fprintf( files->lib, "\t\tself.%s()\n", w->label->name ); + } else { + /* no label */ + fprintf( files->lib, "\t\tself.unnamed_wr_%i()\n", where_rule_number ); + where_rule_number ++; + } + LISTod + fprintf( files->lib, "\n" ); + /* then we process the where rules */ + WHEREPrint( type->where, 0, files->lib ); } - LISTod - fprintf( files->lib, "\n" ); - /* then we process the where rules */ - WHEREPrint( type->where, 0, files->lib ); } } else { /* TODO: cleanup, currently this is deadcode */ switch( TYPEget_body( type )->type ) { diff --git a/src/exp2python/src/classes_wrapper_python.cc b/src/exp2python/src/classes_wrapper_python.cc index ef039f828..266f650e7 100644 --- a/src/exp2python/src/classes_wrapper_python.cc +++ b/src/exp2python/src/classes_wrapper_python.cc @@ -29,30 +29,31 @@ void SCOPEPrint( Scope scope, FILES * files, Schema schema ) { DictionaryEntry de; Type i; int redefs = 0;// index = 0; + int skipped; - /* Defined Types based on SIMPLE types */ - SCOPEdo_types( scope, t, de ) - if ( ( t->search_id == CANPROCESS ) - && !( TYPEis_enumeration( t ) || TYPEis_select( t ) || TYPEis_aggregate( t ) ) - && ( TYPEget_ancestor( t ) == NULL) ) { - TYPEprint_descriptions( t, files, schema ); - t->search_id = PROCESSED; - } - SCOPEod + while( 1 ) { + skipped = 0; - /* Defined Types with defined ancestor head - * TODO: recursive approach - */ - SCOPEdo_types( scope, t, de ) - if ( ( t->search_id == CANPROCESS ) - && !( TYPEis_enumeration( t ) || TYPEis_select( t ) || TYPEis_aggregate( t ) ) - && ( ( i = TYPEget_head( t ) ) != NULL ) ) { - if (i->search_id == PROCESSED) { + SCOPEdo_types( scope, t, de ) + if( TYPEis_enumeration( t ) || TYPEis_select( t ) || TYPEis_aggregate( t ) ) { + continue; + } + + i = TYPEget_head( t ); + if( ( !i || i->search_id == PROCESSED ) + && t->search_id == CANPROCESS ) { TYPEprint_descriptions( t, files, schema ); t->search_id = PROCESSED; + } else if( t->search_id == CANPROCESS ) { + skipped++; + } + + SCOPEod + + if( !skipped ) { + break; } } - SCOPEod /* fill in the values for the type descriptors */ /* and print the enumerations */ @@ -74,14 +75,15 @@ void SCOPEPrint( Scope scope, FILES * files, Schema schema ) { SCOPEod SCOPEdo_types( scope, t, de ) + if( TYPEis_select( t ) || TYPEis_aggregate( t ) ) { + continue; + } + // Do the non-redefined enumerations: if( ( t->search_id == CANPROCESS ) && !( TYPEis_enumeration( t ) && TYPEget_head( t ) ) ) { TYPEprint_descriptions( t, files, schema ); - if( !TYPEis_select( t ) ) { - // Selects have a lot more processing and are done below. - t->search_id = PROCESSED; - } + t->search_id = PROCESSED; } SCOPEod; @@ -101,11 +103,13 @@ void SCOPEPrint( Scope scope, FILES * files, Schema schema ) { // we don't have to worry about printing B before A. This is checked in // TYPEselect_print(). SCOPEdo_types( scope, t, de ) - if( t->search_id == CANPROCESS ) { + if( t->search_id == CANPROCESS && TYPEis_select( t ) ) { // Only selects haven't been processed yet and may still be set to // CANPROCESS. //FIXME this function is not implemented! // TYPEselect_print( t, files, schema ); + // TODO: due to conditional error we were previously executing this above without realising + TYPEprint_descriptions( t, files, schema ); t->search_id = PROCESSED; } SCOPEod; @@ -131,6 +135,14 @@ void SCOPEPrint( Scope scope, FILES * files, Schema schema ) { LISTod; LISTfree( rule_list ); + // TODO: check dependencies + SCOPEdo_types( scope, t, de ) + if( t->search_id == CANPROCESS && TYPEis_aggregate( t ) ) { + TYPEprint_descriptions( t, files, schema ); + t->search_id = PROCESSED; + } + SCOPEod + } @@ -152,15 +164,15 @@ void SCOPEPrint( Scope scope, FILES * files, Schema schema ) { void SCHEMAprint( Schema schema, FILES * files, int suffix ) { int ocnt = 0; - char schnm[MAX_LEN], sufnm[MAX_LEN], fnm[MAX_LEN], *np; + char schnm[MAX_LEN+1], sufnm[MAX_LEN+1], fnm[MAX_LEN+1], *np; /* sufnm = schema name + suffix */ FILE * libfile; /********** create files based on name of schema ***********/ /* return if failure */ /* 1. header file */ - sprintf( schnm, "%s", SCHEMAget_name( schema ) ); + snprintf( schnm, sizeof(schnm), "%s", SCHEMAget_name( schema ) ); if( suffix == 0 ) { - sprintf( sufnm, "%s", schnm ); + snprintf( sufnm, sizeof(sufnm), "%s", schnm ); } else { ocnt = snprintf( sufnm, MAX_LEN, "%s_%d", schnm, suffix ); if( ocnt > MAX_LEN ) { @@ -173,14 +185,16 @@ void SCHEMAprint( Schema schema, FILES * files, int suffix ) { } np = fnm + strlen( fnm ) - 1; /* point to end of constant part of string */ + size_t remaining = (size_t)(fnm + sizeof(fnm) - np); /* 2. class source file */ - sprintf( np, "py" ); + snprintf( np, remaining, "py" ); if( !( libfile = ( files -> lib ) = FILEcreate( fnm ) ) ) { return; } fprintf( libfile, "import sys\n" ); fprintf( libfile, "\n" ); + fprintf( libfile, "from SCL import SCLBase\n" ); fprintf( libfile, "from SCL.SCLBase import *\n" ); fprintf( libfile, "from SCL.SimpleDataTypes import *\n" ); fprintf( libfile, "from SCL.ConstructedDataTypes import *\n" ); @@ -272,7 +286,7 @@ getMCPrint( Express express, FILE * schema_h, FILE * schema_cc ) { ******************************************************************/ void EXPRESSPrint( Express express, FILES * files ) { - char fnm [MAX_LEN]; + char fnm [MAX_LEN+1]; const char * schnm; /* schnm is really "express name" */ FILE * libfile; /* new */ @@ -283,10 +297,11 @@ EXPRESSPrint( Express express, FILES * files ) { /********** create files based on name of schema ***********/ /* return if failure */ /* 1. header file */ - sprintf( fnm, "%s.h", schnm = ClassName( EXPRESSget_basename( express ) ) ); + snprintf( fnm, sizeof(fnm), "%s.h", schnm = ClassName( EXPRESSget_basename( express ) ) ); /* 2. class source file */ - //sprintf( np, "cc" ); + //size_t remaining = (size_t)(fnm + sizeof(fnm) - np); + //snprintf( np, remaining, "cc" ); if( !( libfile = ( files -> lib ) = FILEcreate( fnm ) ) ) { return; } diff --git a/src/exp2python/src/complexSupport.h b/src/exp2python/src/complexSupport.h index 7cd781a37..7a478bbb8 100644 --- a/src/exp2python/src/complexSupport.h +++ b/src/exp2python/src/complexSupport.h @@ -116,7 +116,7 @@ class EntNode { private: MarkType mark; - char name[BUFSIZ]; + char name[BUFSIZ+1]; int multSupers; // do I correspond to an entity with >1 supertype? }; @@ -225,7 +225,7 @@ class SimpleList : public EntList { void write( ostream & ); private: - char name[BUFSIZ]; // Name of entity we correspond to. + char name[BUFSIZ+1]; // Name of entity we correspond to. MarkType I_marked; // Did I mark, and with what type of mark. }; diff --git a/src/exp2python/src/multpass_python.c b/src/exp2python/src/multpass_python.c index ece7e6617..a4204c1c8 100644 --- a/src/exp2python/src/multpass_python.c +++ b/src/exp2python/src/multpass_python.c @@ -150,7 +150,7 @@ void print_schemas_separate( Express express, FILES * files ) // which hasn't been closed yet. (That's done on 2nd line below.)) * / //fprintf( files->initall, "\t reg.SetCompCollect( gencomplex() );\n" ); //fprintf( files->initall, "}\n\n" ); - //fprintf( files->incall, "\n#include \n" ); + //fprintf( files->incall, "\n#include \"core/complexSupport.h\"\n" ); //fprintf( files->incall, "ComplexCollect *gencomplex();\n" ); */ /* Function GetModelContents() is printed at the end of the schema.xx @@ -623,7 +623,7 @@ static void addUseRefNames( Schema schema, FILE * create ) Dictionary useRefDict; DictionaryEntry de; Rename * rnm; - char * oldnm, schNm[BUFSIZ]; + char * oldnm, schNm[BUFSIZ+1]; static int firsttime = TRUE; if( ( useRefDict = schema->u.schema->usedict ) != NULL ) { diff --git a/src/exp2python/src/selects_python.c b/src/exp2python/src/selects_python.c index b44abab95..2bc45d151 100644 --- a/src/exp2python/src/selects_python.c +++ b/src/exp2python/src/selects_python.c @@ -23,7 +23,7 @@ extern int multiple_inheritance; **************************************************************************/ #include #include "classes.h" -#include +#include bool is_python_keyword( char * word ); int isAggregateType( const Type t ); @@ -146,7 +146,7 @@ compareOrigTypes( Type a, Type b ) { *******************/ const char * utype_member( const Linked_List list, const Type check, int rename ) { - static char r [BUFSIZ]; + static char r [BUFSIZ+1]; LISTdo( list, t, Type ) strncpy( r, TYPEget_utype( t ), BUFSIZ ); @@ -246,7 +246,7 @@ determines if the given "link's" C++ representation is used again in the list. *******************/ int duplicate_utype_member( const Linked_List list, const Type check ) { - char b [BUFSIZ]; + char b [BUFSIZ+1]; if( TYPEis_entity( check ) ) { return FALSE; @@ -414,7 +414,7 @@ non_unique_types_string( const Type type ) { non_unique_types_vector( type, tvec ); /* build type string from vector */ - typestr = ( char * )malloc( BUFSIZ ); + typestr = ( char * )malloc( BUFSIZ+1 ); typestr[0] = '\0'; strcat( typestr, ( char * )"(" ); for( i = 0; i <= tnumber; i++ ) { @@ -475,8 +475,8 @@ non_unique_types_string( const Type type ) { Variable ATTR_LISTmember( Linked_List l, Variable check ) { - char nm [BUFSIZ]; - char cur [BUFSIZ]; + char nm [BUFSIZ+1]; + char cur [BUFSIZ+1]; generate_attribute_name( check, nm ); LISTdo( l, a, Variable ) diff --git a/src/exppp/CMakeLists.txt b/src/exppp/CMakeLists.txt index 0d1fb9649..7b8d87c51 100644 --- a/src/exppp/CMakeLists.txt +++ b/src/exppp/CMakeLists.txt @@ -3,7 +3,7 @@ set(LIBEXPPP_SOURCES pretty_alg.c pretty_case.c pretty_entity.c - pretty_expr.c + pretty_expr.cc pretty_express.c pretty_func.c pretty_loop.c @@ -26,12 +26,11 @@ SET(EXPPP_SOURCES include_directories( ${SC_SOURCE_DIR}/include ${SC_SOURCE_DIR}/include/exppp - ${SC_SOURCE_DIR}/src/base ${SC_SOURCE_DIR}/src/express ) if(BUILD_SHARED_LIBS) - SC_ADDLIB(libexppp SHARED SOURCES ${LIBEXPPP_SOURCES} LINK_LIBRARIES express base) + SC_ADDLIB(libexppp SHARED SOURCES ${LIBEXPPP_SOURCES} LINK_LIBRARIES express) set_target_properties(libexppp PROPERTIES PREFIX "") if(WIN32) target_compile_definitions(libexppp PRIVATE SC_EXPPP_DLL_EXPORTS) @@ -39,11 +38,15 @@ if(BUILD_SHARED_LIBS) endif() if(BUILD_STATIC_LIBS) - SC_ADDLIB(libexppp-static STATIC SOURCES ${LIBEXPPP_SOURCES} LINK_LIBRARIES express-static base-static) + SC_ADDLIB(libexppp-static STATIC SOURCES ${LIBEXPPP_SOURCES} LINK_LIBRARIES express-static) set_target_properties(libexppp-static PROPERTIES PREFIX "") endif() -SC_ADDEXEC(exppp SOURCES ${EXPPP_SOURCES} LINK_LIBRARIES libexppp express base) +if(BUILD_SHARED_LIBS) + SC_ADDEXEC(exppp SOURCES ${EXPPP_SOURCES} LINK_LIBRARIES libexppp express) +else() + SC_ADDEXEC(exppp SOURCES ${EXPPP_SOURCES} LINK_LIBRARIES libexppp-static express-static) +endif() if(SC_ENABLE_TESTING) add_subdirectory(test) diff --git a/src/exppp/exppp.c b/src/exppp/exppp.c index e40ffaee9..dd236066a 100644 --- a/src/exppp/exppp.c +++ b/src/exppp/exppp.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -13,12 +12,6 @@ #include "pp.h" #include "exppp.h" - -#if defined(_MSC_VER) && _MSC_VER < 1900 -# include "sc_stdio.h" -# define snprintf c99_snprintf -#endif - /* PP_SMALL_BUF_SZ is a macro used in a few places where const int causes * "warning: ISO C90 forbids variable length array 'buf' [-Wvla]" * @@ -161,7 +154,7 @@ void wrap( const char * fmt, ... ) { || ( ( exppp_linelength == indent2 ) && ( curpos > indent2 ) ) ) { /* move to new continuation line */ char line[1000]; - sprintf( line, "\n%*s", indent2, "" ); + snprintf( line, sizeof(line), "\n%*s", indent2, "" ); exp_output( line, 1 + indent2 ); curpos = indent2; /* reset current position */ @@ -435,7 +428,7 @@ int prep_string() { } string_func_in_use = true; - exppp_buf = exppp_bufp = ( char * )sc_malloc( BIGBUFSIZ ); + exppp_buf = exppp_bufp = ( char * )malloc( BIGBUFSIZ + 1 ); if( !exppp_buf ) { fprintf( stderr, "failed to allocate exppp buffer\n" ); return 1; @@ -453,7 +446,7 @@ int prep_string() { } char * finish_string() { - char * b = ( char * )sc_realloc( exppp_buf, 1 + exppp_maxbuflen - exppp_buflen ); + char * b = ( char * )realloc( exppp_buf, 1 + exppp_maxbuflen - exppp_buflen ); if( b == 0 ) { fprintf( stderr, "failed to reallocate exppp buffer\n" ); diff --git a/src/exppp/pp.h b/src/exppp/pp.h index 89825de6a..a441fece9 100644 --- a/src/exppp/pp.h +++ b/src/exppp/pp.h @@ -4,7 +4,7 @@ #ifndef PP_H #define PP_H -#include +#include #include extern int indent2; /**< where continuation lines start */ diff --git a/src/exppp/pretty_expr.c b/src/exppp/pretty_expr.cc similarity index 77% rename from src/exppp/pretty_expr.c rename to src/exppp/pretty_expr.cc index 60a1c2ded..2db7267b0 100644 --- a/src/exppp/pretty_expr.c +++ b/src/exppp/pretty_expr.cc @@ -4,14 +4,19 @@ */ #include -#include +#include #include +#include +#include +#include + +extern "C" { #include "exppp.h" #include "pp.h" #include "pretty_expr.h" - +} /** print array bounds */ void EXPRbounds_out( TypeBody tb ) { @@ -224,7 +229,7 @@ void EXPRop__out( struct Op_Subexpression * oe, int paren, unsigned int previous } } -void EXPRop2__out( struct Op_Subexpression * eo, char * opcode, int paren, int pad, unsigned int previous_op ) { +void EXPRop2__out( struct Op_Subexpression * eo, const char * opcode, int paren, int pad, unsigned int previous_op ) { if( pad && paren && ( eo->op_code != previous_op ) ) { wrap( "( " ); } @@ -245,7 +250,7 @@ void EXPRop2__out( struct Op_Subexpression * eo, char * opcode, int paren, int p /** Print out a one-operand operation. If there were more than two of these * I'd generalize it to do padding, but it's not worth it. */ -void EXPRop1_out( struct Op_Subexpression * eo, char * opcode, int paren ) { +void EXPRop1_out( struct Op_Subexpression * eo, const char * opcode, int paren ) { if( paren ) { wrap( "( " ); } @@ -268,89 +273,124 @@ int EXPRop_length( struct Op_Subexpression * oe ) { return 0; } -/** returns printable representation of expression rather than printing it - * originally only used for general references, now being expanded to handle - * any kind of expression - * contains fragment of string, adds to it - */ -void EXPRstring( char * buffer, Expression e ) { +/* ---- C++ string-based builder (replaces unsafe EXPRstring/EXPRop_string) ---- */ + +static void appendf( std::string & out, const char * fmt, ... ) { + va_list ap; + va_start( ap, fmt ); + + va_list ap2; + va_copy( ap2, ap ); + + int n = std::vsnprintf( NULL, 0, fmt, ap ); + va_end( ap ); + + if( n > 0 ) { + size_t old = out.size(); + out.resize( old + ( size_t )n ); + std::vsnprintf( &out[0] + old, ( size_t )n + 1, fmt, ap2 ); + } + + va_end( ap2 ); +} + +static void EXPRstring_cpp( std::string & out, Expression e ); + +static void EXPRop_string_cpp( std::string & out, struct Op_Subexpression * oe ) { + EXPRstring_cpp( out, oe->op1 ); + switch( oe->op_code ) { + case OP_DOT: + out.push_back( '.' ); + break; + case OP_GROUP: + out.push_back( '\\' ); + break; + default: + out.append( "(* unknown op-expression *)" ); + } + EXPRstring_cpp( out, oe->op2 ); +} + +static void EXPRstring_cpp( std::string & out, Expression e ) { int i; switch( TYPEis( e->type ) ) { case integer_: if( e == LITERAL_INFINITY ) { - strcpy( buffer, "?" ); + out.append( "?" ); } else { - sprintf( buffer, "%d", e->u.integer ); + appendf( out, "%d", e->u.integer ); } break; case real_: if( e == LITERAL_PI ) { - strcpy( buffer, "PI" ); + out.append( "PI" ); } else if( e == LITERAL_E ) { - strcpy( buffer, "E" ); + out.append( "E" ); } else { - sprintf( buffer, "%s", real2exp( e->u.real ) ); + appendf( out, "%s", real2exp( e->u.real ) ); } break; case binary_: - sprintf( buffer, "%%%s", e->u.binary ); /* put "%" back */ + appendf( out, "%%%s", e->u.binary ); /* put "%" back */ break; case logical_: case boolean_: switch( e->u.logical ) { case Ltrue: - strcpy( buffer, "TRUE" ); + out.append( "TRUE" ); break; case Lfalse: - strcpy( buffer, "FALSE" ); + out.append( "FALSE" ); break; default: - strcpy( buffer, "UNKNOWN" ); + out.append( "UNKNOWN" ); break; } break; case string_: if( TYPEis_encoded( e->type ) ) { - sprintf( buffer, "\"%s\"", e->symbol.name ); + appendf( out, "\"%s\"", e->symbol.name ); } else { - sprintf( buffer, "%s", e->symbol.name ); + appendf( out, "%s", e->symbol.name ); } break; case entity_: case identifier_: case attribute_: case enumeration_: - strcpy( buffer, e->symbol.name ); + if( e->symbol.name ) { + out.append( e->symbol.name ); + } break; case query_: - sprintf( buffer, "QUERY ( %s <* ", e->u.query->local->name->symbol.name ); - EXPRstring( buffer + strlen( buffer ), e->u.query->aggregate ); - strcat( buffer, " | " ); - EXPRstring( buffer + strlen( buffer ), e->u.query->expression ); - strcat( buffer, " )" ); + appendf( out, "QUERY ( %s <* ", e->u.query->local->name->symbol.name ); + EXPRstring_cpp( out, e->u.query->aggregate ); + out.append( " | " ); + EXPRstring_cpp( out, e->u.query->expression ); + out.append( " )" ); break; case self_: - strcpy( buffer, "SELF" ); + out.append( "SELF" ); break; case funcall_: - sprintf( buffer, "%s( ", e->symbol.name ); + appendf( out, "%s( ", e->symbol.name ); i = 0; LISTdo( e->u.funcall.list, arg, Expression ) i++; if( i != 1 ) { - strcat( buffer, ", " ); + out.append( ", " ); } - EXPRstring( buffer + strlen( buffer ), arg ); + EXPRstring_cpp( out, arg ); LISTod - strcat( buffer, " )" ); + out.append( " )" ); break; case op_: - EXPRop_string( buffer, &e->e ); + EXPRop_string_cpp( out, &e->e ); break; case aggregate_: - strcpy( buffer, "[" ); + out.append( "[" ); i = 0; LISTdo( e->u.list, arg, Expression ) { bool repeat = arg->type->u.type->body->flags.repeat; @@ -358,48 +398,33 @@ void EXPRstring( char * buffer, Expression e ) { i++; if( i != 1 ) { if( repeat ) { - strcat( buffer, " : " ); + out.append( " : " ); } else { - strcat( buffer, ", " ); + out.append( ", " ); } } - EXPRstring( buffer + strlen( buffer ), arg ); + EXPRstring_cpp( out, arg ); } LISTod - strcat( buffer, "]" ); + out.append( "]" ); break; case oneof_: - strcpy( buffer, "ONEOF ( " ); + out.append( "ONEOF ( " ); i = 0; LISTdo( e->u.list, arg, Expression ) { i++; if( i != 1 ) { - strcat( buffer, ", " ); + out.append( ", " ); } - EXPRstring( buffer + strlen( buffer ), arg ); + EXPRstring_cpp( out, arg ); } LISTod - strcat( buffer, " )" ); - break; - default: - sprintf( buffer, "EXPRstring: unknown expression, type %d", TYPEis( e->type ) ); - fprintf( stderr, "%s", buffer ); - } -} - -void EXPRop_string( char * buffer, struct Op_Subexpression * oe ) { - EXPRstring( buffer, oe->op1 ); - switch( oe->op_code ) { - case OP_DOT: - strcat( buffer, "." ); - break; - case OP_GROUP: - strcat( buffer, "\\" ); + out.append( " )" ); break; default: - strcat( buffer, "(* unknown op-expression *)" ); + appendf( out, "EXPRstring: unknown expression, type %d", TYPEis( e->type ) ); + fprintf( stderr, "%s", out.c_str() ); } - EXPRstring( buffer + strlen( buffer ), oe->op2 ); } /** returns length of printable representation of expression w.o. printing it @@ -407,10 +432,10 @@ void EXPRop_string( char * buffer, struct Op_Subexpression * oe ) { * WARNING this *does* change the global 'curpos'! */ int EXPRlength( Expression e ) { - char buffer[10000]; - *buffer = '\0'; - EXPRstring( buffer, e ); - return( strlen( buffer ) ); + std::string out; + out.reserve( 256 ); + EXPRstring_cpp( out, e ); + return( ( int )out.size() ); } char * EXPRto_string( Expression e ) { diff --git a/src/exppp/pretty_expr.h b/src/exppp/pretty_expr.h index 633bdf3f1..6769780fa 100644 --- a/src/exppp/pretty_expr.h +++ b/src/exppp/pretty_expr.h @@ -1,36 +1,27 @@ #ifndef PRETTY_EXPR_H #define PRETTY_EXPR_H +#ifdef __cplusplus +extern "C" { +#endif + #include "../express/expbasic.h" #include "../express/express.h" - #define EXPR_out(e,p) EXPR__out(e,p,OP_UNKNOWN) #define EXPRop2_out(oe,string,paren,pad) \ EXPRop2__out(oe,string,paren,pad,OP_UNKNOWN) #define EXPRop_out(oe,paren) EXPRop__out(oe,paren,OP_UNKNOWN) void EXPRop__out( struct Op_Subexpression * oe, int paren, unsigned int previous_op ); -void EXPRop_string( char * buffer, struct Op_Subexpression * oe ); -void EXPRop1_out( struct Op_Subexpression * eo, char * opcode, int paren ); -void EXPRop2__out( struct Op_Subexpression * eo, char * opcode, int paren, int pad, unsigned int previous_op ); +void EXPRop1_out( struct Op_Subexpression * eo, const char * opcode, int paren ); +void EXPRop2__out( struct Op_Subexpression * eo, const char * opcode, int paren, int pad, unsigned int previous_op ); void EXPR__out( Expression e, int paren, unsigned int previous_op ); void EXPRbounds_out( TypeBody tb ); -int EXPRlength( Expression e ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif #endif /* PRETTY_EXPR_H */ -/* -char * EXPRto_string( Expression e ); -void EXPR__out( Expression e, int paren, unsigned int previous_op ); -void EXPRbounds_out( TypeBody tb ); -int EXPRlength( Expression e ); -void EXPRop1_out( struct Op_Subexpression * eo, char * opcode, int paren ); -void EXPRop2__out( struct Op_Subexpression * eo, char * opcode, int paren, int pad, unsigned int previous_op ); -void EXPRop__out( struct Op_Subexpression * oe, int paren, unsigned int previous_op ); -int EXPRop_length( struct Op_Subexpression * oe ); -void EXPRop_string( char * buffer, struct Op_Subexpression * oe ); -void EXPRout( Expression e ); -void EXPRstring( char * buffer, Expression e ); -int EXPRto_buffer( Expression e, char * buffer, int length ); -*/ diff --git a/src/exppp/pretty_schema.c b/src/exppp/pretty_schema.c index c17ebe5be..ae2ad2d7c 100644 --- a/src/exppp/pretty_schema.c +++ b/src/exppp/pretty_schema.c @@ -69,7 +69,7 @@ char * SCHEMAout( Schema s ) { /* since we have to generate a filename, make sure we don't */ /* overwrite a valuable file */ - sprintf( exppp_filename_buffer, "%s.exp", s->symbol.name ); + snprintf( exppp_filename_buffer, sizeof(exppp_filename_buffer), "%s.exp", s->symbol.name ); if( 0 != ( f = fopen( exppp_filename_buffer, "r" ) ) ) { char * result = fgets( buf, PP_SMALL_BUF_SZ, f ); diff --git a/src/exppp/pretty_subtype.c b/src/exppp/pretty_subtype.c index d47298e49..f21d6c620 100644 --- a/src/exppp/pretty_subtype.c +++ b/src/exppp/pretty_subtype.c @@ -2,8 +2,6 @@ * split out of exppp.c 9/21/13 */ -#include - #include "exppp.h" #include "pp.h" diff --git a/src/exppp/pretty_type.c b/src/exppp/pretty_type.c index d18402ddc..678d2b87a 100644 --- a/src/exppp/pretty_type.c +++ b/src/exppp/pretty_type.c @@ -5,7 +5,6 @@ #include #include -#include #include "exppp.h" #include "pp.h" @@ -151,7 +150,7 @@ void TYPE_body_out( Type t, int level ) { while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) { count++; } - names = ( char ** )sc_malloc( count * sizeof( char * ) ); + names = ( char ** )calloc( count, sizeof( char * ) ); DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION ); while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) { names[expr->u.integer - 1] = expr->symbol.name; @@ -175,7 +174,7 @@ void TYPE_body_out( Type t, int level ) { raw( names[i] ); } raw( " )" ); - sc_free( ( char * )names ); + free( ( char * )names ); } break; case select_: diff --git a/src/exppp/test/CMakeLists.txt b/src/exppp/test/CMakeLists.txt index 0d911e590..e13a480e0 100644 --- a/src/exppp/test/CMakeLists.txt +++ b/src/exppp/test/CMakeLists.txt @@ -14,7 +14,7 @@ add_test(NAME build_exppp ) # this executable doesn't really check the results, just ensures no segfaults. ought to improve it... -SC_ADDEXEC(tst_breakLongStr SOURCES ${breakLongStr_SRCS} LINK_LIBRARIES express base TESTABLE) +SC_ADDEXEC(tst_breakLongStr SOURCES ${breakLongStr_SRCS} LINK_LIBRARIES express TESTABLE) add_test(NAME build_tst_breakLongStr WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND ${CMAKE_COMMAND} --build . diff --git a/src/exppp/test/exppp_supertype_andor.cmake b/src/exppp/test/exppp_supertype_andor.cmake index 547ad70a5..5c03a02a5 100644 --- a/src/exppp/test/exppp_supertype_andor.cmake +++ b/src/exppp/test/exppp_supertype_andor.cmake @@ -1,5 +1,5 @@ -cmake_minimum_required( VERSION 2.8 ) +cmake_minimum_required( VERSION 3.12 ) # executable is ${EXPPP}, input file is ${INFILE} diff --git a/src/express/CMakeLists.txt b/src/express/CMakeLists.txt index 2a3aa4299..e5c0dfe04 100644 --- a/src/express/CMakeLists.txt +++ b/src/express/CMakeLists.txt @@ -1,7 +1,6 @@ include_directories( ${CMAKE_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR} - ${SC_SOURCE_DIR}/src/base ) # Depending on whether we're using pre-generated sources or building them on @@ -19,6 +18,7 @@ if(SC_GENERATE_LP_SOURCES) add_library(objlib_expparse_c OBJECT ${LEMON_ExpParser_OUTPUTS}) set_property(TARGET objlib_expparse_c PROPERTY POSITION_INDEPENDENT_CODE ON) + set_source_files_properties(${LEMON_ExpParser_OUTPUTS} PROPERTIES OBJECT_DEPENDS "${PERPLEX_ExpScanner_HDR}") else(SC_GENERATE_LP_SOURCES) add_subdirectory(generated) @@ -93,7 +93,6 @@ endif() if(BUILD_SHARED_LIBS OR NOT BUILD_STATIC_LIBS) add_library(express SHARED ${EXPRESS_OBJS}) - target_link_libraries(express base) if(OPENBSD) set_target_properties(express PROPERTIES VERSION ${SC_VERSION_MAJOR}.${SC_VERSION_MINOR}) else(OPENBSD) @@ -137,9 +136,9 @@ set(CHECK_EXPRESS_SOURCES add_executable(check-express ${CHECK_EXPRESS_SOURCES}) if(BUILD_SHARED_LIBS OR NOT BUILD_STATIC_LIBS) - target_link_libraries(check-express express base) + target_link_libraries(check-express express) else() - target_link_libraries(check-express express-static base-static) + target_link_libraries(check-express express-static) endif() install(TARGETS check-express RUNTIME DESTINATION ${BIN_DIR} diff --git a/src/express/alloc.c b/src/express/alloc.c index e20cfa943..2a3979ba2 100644 --- a/src/express/alloc.c +++ b/src/express/alloc.c @@ -76,7 +76,7 @@ Freelist * create_freelist( struct freelist_head * flh, int bytes ) { } void -_ALLOCinitialize() { +_ALLOCinitialize(void) { #ifdef DEBUG_MALLOC malloc_debug( 2 ); #endif diff --git a/src/express/entity.c b/src/express/entity.c index 507b2c23f..7b26a7833 100644 --- a/src/express/entity.c +++ b/src/express/entity.c @@ -292,7 +292,7 @@ Entity ENTITYcopy( Entity e ) { } /** Initialize the Entity module. */ -void ENTITYinitialize() { +void ENTITYinitialize(void) { } /** diff --git a/src/express/error.c b/src/express/error.c index 04bcc4154..9367f0629 100644 --- a/src/express/error.c +++ b/src/express/error.c @@ -24,7 +24,7 @@ * Revision 1.11 1997/10/22 16:10:26 sauderd * This would #include stdarg.h if __STDC__ was defined otherwise it would * #include vararg.h. I changed it to check the configure generated config file - * named sc_cf.h (if HAVE_CONFIG_H is defined - it's also defined by + * named config.h (if HAVE_CONFIG_H is defined - it's also defined by * configure) to see if HAVE_STDARG_H is defined. If it is it #includes stdarg.h * otherwise it #includes vararg.h. If HAVE_CONFIG_H isn't defined then it works * like it used to. @@ -58,17 +58,11 @@ #include #include -#include "sc_memmgr.h" #include "express/express.h" #include "express/error.h" #include "express/info.h" #include "express/linklist.h" -#if defined(_MSC_VER) && _MSC_VER < 1900 -# include "sc_stdio.h" -# define vsnprintf c99_vsnprintf -#endif - static struct Error_ LibErrors[] = { /* dict.c */ [DUPLICATE_DECL] = {SEVERITY_ERROR, "Redeclaration of %s. Previous declaration was on line %d.", NULL, false}, @@ -224,7 +218,7 @@ static int ERROR_printf( const char *format, ... ) { return result; } -static void ERROR_nexterror() { +static void ERROR_nexterror(void) { if( ERROR_string == ERROR_string_end ) { return; } @@ -233,7 +227,7 @@ static void ERROR_nexterror() { /** Initialize the Error module */ void ERRORinitialize( void ) { - ERROR_string_base = ( char * )sc_malloc( ERROR_MAX_SPACE ); + ERROR_string_base = ( char * )malloc( ERROR_MAX_SPACE ); ERROR_string_end = ERROR_string_base + ERROR_MAX_SPACE; ERROR_start_message_buffer(); @@ -253,7 +247,7 @@ void ERRORinitialize( void ) { /** Clean up the Error module */ void ERRORcleanup( void ) { - sc_free( ERROR_string_base ); + free( ERROR_string_base ); } void ERRORset_warning(char * name, bool warn_only) { @@ -296,7 +290,7 @@ char * ERRORget_warnings_help(const char* prefix, const char *eol) { clen = strlen(prefix) + strlen(eol) + 1; - buf = sc_malloc(sz); + buf = malloc(sz); if (!buf) { fprintf(error_file, "failed to allocate memory for warnings help!\n"); } @@ -308,7 +302,7 @@ char * ERRORget_warnings_help(const char* prefix, const char *eol) { len = strlen(buf) + strlen(err->name) + clen; if (len > sz) { sz *= 2; - nbuf = sc_realloc(buf, sz); + nbuf = realloc(buf, sz); if (!nbuf) { fprintf(error_file, "failed to reallocate / grow memory for warnings help!\n"); } @@ -461,7 +455,7 @@ ERRORreport_with_symbol( enum ErrorCode errnum, Symbol * sym, ... ) { va_end( args ); } -void ERRORnospace() { +void ERRORnospace(void) { fprintf( stderr, "%s: out of space\n", EXPRESSprogram_name ); ERRORabort( 0 ); } @@ -542,6 +536,6 @@ void ERRORsafe( jmp_buf env ) { memcpy( ERROR_safe_env, env, sizeof( jmp_buf ) ); } -void ERRORunsafe() { +void ERRORunsafe(void) { ERROR_unsafe = true; } diff --git a/src/express/expparse.y b/src/express/expparse.y index f6bc296c2..92a9bfcca 100644 --- a/src/express/expparse.y +++ b/src/express/expparse.y @@ -51,7 +51,7 @@ YYSTYPE yylval; Express yyexpresult; /* hook to everything built by parser */ Symbol *interface_schema; /* schema of interest in use/ref clauses */ - void (*interface_func)(); /* func to attach rename clauses */ + void (*interface_func)(struct Scope_ *, Symbol *, Symbol *, Symbol *); /* func to attach rename clauses */ /* record schemas found in a single parse here, allowing them to be */ /* differentiated from other schemas parsed earlier */ @@ -106,7 +106,7 @@ YYSTYPE yylval; #define ERROR(code) ERRORreport(code, yylineno) -void parserInitState() +void parserInitState( void ) { scope = scopes; /* no need to define scope->this */ @@ -402,8 +402,7 @@ aggregate_type(A) ::= TOK_AGGREGATE TOK_OF parameter_type(B). Symbol sym; sym.line = yylineno; sym.filename = current_filename; - ERRORreport_with_symbol(UNLABELLED_PARAM_TYPE, &sym, - CURRENT_SCOPE_NAME); + ERRORreport_with_symbol(UNLABELLED_PARAM_TYPE, &sym, CURRENT_SCOPE_NAME); } } aggregate_type(A) ::= TOK_AGGREGATE TOK_COLON TOK_IDENTIFIER(B) TOK_OF diff --git a/src/express/expr.c b/src/express/expr.c index 19ab0af91..c48ec5909 100644 --- a/src/express/expr.c +++ b/src/express/expr.c @@ -85,7 +85,7 @@ Expression LITERAL_PI = EXPRESSION_NULL; Expression LITERAL_ZERO = EXPRESSION_NULL; Expression LITERAL_ONE; -void EXPop_init(); +void EXPop_init(void); static inline int OPget_number_of_operands( Op_Code op ) { if( ( op == OP_NEGATE ) || ( op == OP_NOT ) ) { @@ -760,7 +760,7 @@ void EXPop_create( int token_number, char * string, Resolve_expr_func * resolve_ EXPop_table[token_number].resolve = resolve_func; } -void EXPop_init() { +void EXPop_init(void) { EXPop_create( OP_AND, "AND", EXPresolve_op_logical ); EXPop_create( OP_ANDOR, "ANDOR", EXPresolve_op_logical ); EXPop_create( OP_ARRAY_ELEMENT, "[array element]", EXPresolve_op_array_like ); diff --git a/src/express/express.c b/src/express/express.c index 82e7b7889..f8f4c4fc8 100644 --- a/src/express/express.c +++ b/src/express/express.c @@ -73,7 +73,6 @@ #include #include -#include "sc_memmgr.h" #include "express/memory.h" #include "express/basic.h" #include "express/express.h" @@ -107,7 +106,7 @@ bool EXPRESSignore_duplicate_schemas = false; Function funcdef(char *name, int pcount, Type ret_typ); void procdef(char *name, int pcount); -void BUILTINSinitialize(); +void BUILTINSinitialize(void); Dictionary EXPRESSbuiltins; /* procedures/functions */ @@ -144,20 +143,20 @@ int EXPRESS_succeed( Express model ) { return 0; } -Express EXPRESScreate() { +Express EXPRESScreate(void) { Express model = SCOPEcreate( OBJ_EXPRESS ); - model->u.express = ( struct Express_ * )sc_calloc( 1, sizeof( struct Express_ ) ); + model->u.express = ( struct Express_ * )calloc( 1, sizeof( struct Express_ ) ); return model; } void EXPRESSdestroy( Express model ) { if( model->u.express->basename ) { - sc_free( model->u.express->basename ); + free( model->u.express->basename ); } if( model->u.express->filename ) { - sc_free( model->u.express->filename ); + free( model->u.express->filename ); } - sc_free( model->u.express ); + free( model->u.express ); SCOPEdestroy( model ); } @@ -167,7 +166,7 @@ typedef struct Dir { char * leaf; } Dir; -static void EXPRESS_PATHinit() { +static void EXPRESS_PATHinit(void) { char * p; Dir * dir; @@ -175,7 +174,7 @@ static void EXPRESS_PATHinit() { p = getenv( "EXPRESS_PATH" ); if( !p ) { /* if no EXPRESS_PATH, search current directory anyway */ - dir = ( Dir * )sc_malloc( sizeof( Dir ) ); + dir = ( Dir * )malloc( sizeof( Dir ) ); dir->leaf = dir->full; LISTadd_last( EXPRESS_path, dir ); } else { @@ -208,7 +207,7 @@ static void EXPRESS_PATHinit() { } p++; /* leave p after terminating null */ - dir = ( Dir * )sc_malloc( sizeof( Dir ) ); + dir = ( Dir * )malloc( sizeof( Dir ) ); /* if it's just ".", make it as if it was */ /* just "" to make error messages cleaner */ @@ -228,7 +227,7 @@ static void EXPRESS_PATHinit() { strcpy( dir->full, start ); dir->leaf = dir->full + length; } else { - sprintf( dir->full, "%s/", start ); + snprintf( dir->full, sizeof(dir->full), "%s/", start ); dir->leaf = dir->full + length + 1; } LISTadd_last( EXPRESS_path, dir ); @@ -240,13 +239,13 @@ static void EXPRESS_PATHinit() { static void EXPRESS_PATHfree( void ) { LISTdo( EXPRESS_path, dir, Dir * ) - sc_free( dir ); + free( dir ); LISTod LISTfree( EXPRESS_path ); } /** inform object system about bit representation for handling pass diagnostics */ -void PASSinitialize() { +void PASSinitialize(void) { } /** Initialize the Express package. */ @@ -312,7 +311,9 @@ void EXPRESSparse( Express model, FILE * fp, char * filename ) { if( !fp ) { /* go down path looking for file */ LISTdo( EXPRESS_path, dir, Dir * ) - sprintf( dir->leaf, "%s", filename ); + + size_t rem = (size_t)( dir->full + sizeof( dir->full ) - dir->leaf ); + snprintf( dir->leaf, rem, "%s", filename ); if( 0 != ( fp = fopen( dir->full, "r" ) ) ) { filename = dir->full; break; @@ -339,7 +340,7 @@ void EXPRESSparse( Express model, FILE * fp, char * filename ) { length -= 4; } - model->u.express->basename = ( char * )sc_malloc( length + 1 ); + model->u.express->basename = ( char * )malloc( length + 1 ); memcpy( model->u.express->basename, filename, length ); model->u.express->basename[length] = '\0'; @@ -354,7 +355,7 @@ void EXPRESSparse( Express model, FILE * fp, char * filename ) { } /* TODO LEMON ought to put this in expparse.h */ -void parserInitState(); +void parserInitState(void); /** start parsing a new schema file */ static Express PARSERrun( char * filename, FILE * fp ) { @@ -531,7 +532,9 @@ Schema EXPRESSfind_schema( Dictionary modeldict, char * name ) { /* go down path looking for file */ LISTdo( EXPRESS_path, dir, Dir * ) - sprintf( dir->leaf, "%s.exp", lower ); + + size_t rem = (size_t)( dir->full + sizeof( dir->full ) - dir->leaf ); + snprintf( dir->leaf, rem, "%s.exp", lower ); if( print_objects_while_running & OBJ_SCHEMA_BITS ) { fprintf( stderr, "pass %d: %s (schema file?)\n", EXPRESSpass, dir->full ); @@ -799,7 +802,7 @@ void procdef(char *name, int pcount) { DICTdefine(EXPRESSbuiltins, name, p, 0, OBJ_PROCEDURE); } -void BUILTINSinitialize() { +void BUILTINSinitialize(void) { EXPRESSbuiltins = DICTcreate( 35 ); procdef("INSERT", 3 ); procdef("REMOVE", 2 ); diff --git a/src/express/expscan.l b/src/express/expscan.l index cbd56c535..755e21fc1 100644 --- a/src/express/expscan.l +++ b/src/express/expscan.l @@ -98,9 +98,12 @@ * * Revision 4.1 90/09/13 16:29:00 clark * BPR 2.1 alpha - * + * */ - +#include +#if !defined(isascii) && defined(__isascii) +# define isascii __isascii +#endif #include "express/basic.h" #include "express/error.h" #include "express/lexact.h" diff --git a/src/express/factory.c b/src/express/factory.c index daf6ee7d3..3e8a6727b 100644 --- a/src/express/factory.c +++ b/src/express/factory.c @@ -34,7 +34,7 @@ Type Type_Set_Of_String; Type Type_Set_Of_Generic; Type Type_Bag_Of_Generic; -void FACTORYinitialize() { +void FACTORYinitialize(void) { /* Very commonly-used read-only types */ Type_Unknown = TYPEcreate( unknown_ ); Type_Dont_Care = TYPEcreate( special_ ); diff --git a/src/express/fedex.c b/src/express/fedex.c index c32989616..efca9ddd1 100644 --- a/src/express/fedex.c +++ b/src/express/fedex.c @@ -74,10 +74,8 @@ #include #include -#include "sc_cf.h" -#include "sc_memmgr.h" +#include "config.h" #include "sc_export.h" -#include "sc_getopt.h" #include "express/error.h" #include "express/express.h" #include "express/resolve.h" @@ -87,6 +85,68 @@ extern int exp_yydebug; #endif /*YYDEBUG*/ +char * sc_optarg; // global argument pointer +int sc_optind = 0; // global argv index + +int sc_getopt( int argc, char * argv[], char * optstring ) { + static char * next = NULL; + if( sc_optind == 0 ) { + next = NULL; + } + + sc_optarg = NULL; + + if( next == NULL || *next == '\0' ) { + if( sc_optind == 0 ) { + sc_optind++; + } + + if( sc_optind >= argc || argv[sc_optind][0] != '-' || argv[sc_optind][1] == '\0' ) { + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + if( strcmp( argv[sc_optind], "--" ) == 0 ) { + sc_optind++; + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + next = argv[sc_optind]; + next++; // skip past - + sc_optind++; + } + + char c = *next++; + char * cp = strchr( optstring, c ); + + if( cp == NULL || c == ':' ) { + return '?'; + } + + cp++; + if( *cp == ':' ) { + if( *next != '\0' ) { + sc_optarg = next; + next = NULL; + } else if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + sc_optind++; + } else { + return '?'; + } + } + + return c; +} + + char EXPRESSgetopt_options[256] = "Bbd:e:i:w:p:rvz"; /* larger than the string because exp2cxx, exppp, etc may append their own options */ static int no_need_to_work = 0; /* TRUE if we can exit gracefully without doing any work */ diff --git a/src/express/generated/expparse.c b/src/express/generated/expparse.c index 217c349d6..393d5c303 100644 --- a/src/express/generated/expparse.c +++ b/src/express/generated/expparse.c @@ -57,7 +57,7 @@ YYSTYPE yylval; Express yyexpresult; /* hook to everything built by parser */ Symbol *interface_schema; /* schema of interest in use/ref clauses */ - void (*interface_func)(); /* func to attach rename clauses */ + void (*interface_func)(struct Scope_ *, Symbol *, Symbol *, Symbol *); /* func to attach rename clauses */ /* record schemas found in a single parse here, allowing them to be */ /* differentiated from other schemas parsed earlier */ @@ -112,7 +112,7 @@ YYSTYPE yylval; #define ERROR(code) ERRORreport(code, yylineno) -void parserInitState() +void parserInitState( void ) { scope = scopes; /* no need to define scope->this */ @@ -2348,8 +2348,7 @@ static void yy_reduce( Symbol sym; sym.line = yylineno; sym.filename = current_filename; - ERRORreport_with_symbol(UNLABELLED_PARAM_TYPE, &sym, - CURRENT_SCOPE_NAME); + ERRORreport_with_symbol(UNLABELLED_PARAM_TYPE, &sym, CURRENT_SCOPE_NAME); } } #line 2356 "expparse.c" diff --git a/src/express/generated/expscan.c b/src/express/generated/expscan.c index b78b863a5..86893459a 100644 --- a/src/express/generated/expscan.c +++ b/src/express/generated/expscan.c @@ -99,6 +99,10 @@ * Revision 4.1 90/09/13 16:29:00 clark * BPR 2.1 alpha * */ +#include +#if !defined(isascii) && defined(__isascii) +# define isascii __isascii +#endif #include "express/basic.h" #include "express/error.h" #include "express/lexact.h" @@ -275,8 +279,9 @@ buf_prints(struct Buf *buf, const char *fmt, const char *s) { char *t; - t = (char*)malloc(strlen(fmt) + strlen(s) + 1); - sprintf(t, fmt, s); + size_t len = strlen(fmt) + strlen(s) + 1; + t = (char*)malloc(len); + snprintf(t, len, fmt, s); buf = buf_strappend(buf, t); free(t); return buf; @@ -311,9 +316,10 @@ buf_linedir(struct Buf *buf, const char* filename, int lineno) { char *t; const char fmt[] = "#line %d \"%s\"\n"; - - t = (char*)malloc(strlen(fmt) + strlen(filename) + numDigits(lineno) + 1); - sprintf(t, fmt, lineno, filename); + + size_t len = strlen(fmt) + strlen(filename) + numDigits(lineno) + 1; + t = (char*)malloc(len); + snprintf(t, len, fmt, lineno, filename); buf = buf_strappend(buf, t); free(t); return buf; @@ -378,9 +384,11 @@ buf_m4_define(struct Buf *buf, const char* def, const char* val) char *str; val = val ? val : ""; - str = (char*)malloc(strlen(fmt) + strlen(def) + strlen(val) + 2); - sprintf(str, fmt, def, val); + size_t len = strlen(fmt) + strlen(def) + strlen(val) + 2; + str = (char*)malloc(len); + + snprintf(str, len, fmt, def, val); buf_append(buf, &str, 1); return buf; } @@ -396,9 +404,9 @@ buf_m4_undefine(struct Buf *buf, const char* def) const char *fmt = "m4_undefine( [[%s]])m4_dnl\n"; char *str; - str = (char*)malloc(strlen(fmt) + strlen(def) + 2); - - sprintf(str, fmt, def); + size_t len = strlen(fmt) + strlen(def) + 2; + str = (char*)malloc(len); + snprintf(str, len, fmt, def); buf_append(buf, &str, 1); return buf; } @@ -617,7 +625,7 @@ getTokenText(perplex_t scanner) #define yyextra scanner->extra static perplex_t -newScanner() +newScanner(void) { perplex_t scanner; scanner = (perplex_t)calloc(1, sizeof(struct perplex)); diff --git a/src/express/hash.c b/src/express/hash.c index 5556ade92..fabe6ba0f 100644 --- a/src/express/hash.c +++ b/src/express/hash.c @@ -109,7 +109,6 @@ #include #include -#include "sc_memmgr.h" #include "express/hash.h" /* @@ -132,7 +131,7 @@ static long HashAccesses, HashCollisions; */ void -HASHinitialize() { +HASHinitialize(void) { } Hash_Table @@ -293,7 +292,7 @@ HASHdestroy( Hash_Table table ) { p = q; } } - sc_free( table->Directory[i] ); + free( table->Directory[i] ); } } HASH_Table_destroy( table ); diff --git a/src/express/lexact.c b/src/express/lexact.c index abcde3176..3f521850c 100644 --- a/src/express/lexact.c +++ b/src/express/lexact.c @@ -55,7 +55,6 @@ #include #include -#include "sc_memmgr.h" #include "express/lexact.h" #include "express/linklist.h" #include "stack.h" @@ -221,7 +220,7 @@ static void SCANpush_buffer( char * filename, FILE * fp ) { SCANbuffer.filename = current_filename = filename; } -static void SCANpop_buffer() { +static void SCANpop_buffer(void) { if( SCANbuffer.file != NULL ) { fclose( SCANbuffer.file ); } @@ -273,7 +272,7 @@ int SCANprocess_logical_literal( char * string ) { break; /* default will actually be triggered by 'UNKNOWN' keyword */ } - sc_free( string ); + free( string ); return TOK_LOGICAL_LITERAL; } @@ -285,7 +284,7 @@ int SCANprocess_identifier_or_keyword( const char * yytext ) { /* make uppercase copy */ len = strlen( yytext ); - dest = test_string = ( char * )sc_malloc( len + 1 ); + dest = test_string = ( char * )malloc( len + 1 ); for( src = yytext; *src; src++, dest++ ) { *dest = ( islower( *src ) ? toupper( *src ) : *src ); } @@ -301,7 +300,7 @@ int SCANprocess_identifier_or_keyword( const char * yytext ) { case TOK_LOGICAL_LITERAL: return SCANprocess_logical_literal( test_string ); default: - sc_free( test_string ); + free( test_string ); return k->token; } } @@ -474,7 +473,7 @@ void SCANupperize( char * s ) { } char * SCANstrdup( const char * s ) { - char * s2 = ( char * )sc_malloc( strlen( s ) + 1 ); + char * s2 = ( char * )malloc( strlen( s ) + 1 ); if( !s2 ) { return 0; } @@ -483,6 +482,6 @@ char * SCANstrdup( const char * s ) { return s2; } -long SCANtell() { +long SCANtell(void) { return yylineno; } diff --git a/src/express/linklist.c b/src/express/linklist.c index 7089dd81d..6acbea90d 100644 --- a/src/express/linklist.c +++ b/src/express/linklist.c @@ -29,7 +29,7 @@ void LISTinitialize( void ) { void LISTcleanup( void ) { } -Linked_List LISTcreate() { +Linked_List LISTcreate(void) { Linked_List list = LIST_new(); list->mark = LINK_new(); list->mark->next = list->mark->prev = list->mark; diff --git a/src/express/memory.c b/src/express/memory.c index da4db3751..6c3b1c5b6 100644 --- a/src/express/memory.c +++ b/src/express/memory.c @@ -47,7 +47,7 @@ struct freelist_head PCALL_fl; struct freelist_head RET_fl; struct freelist_head INCR_fl; -void MEMORYinitialize() { +void MEMORYinitialize(void) { _ALLOCinitialize(); ALLOCinitialize( &HASH_Table_fl, sizeof( struct Hash_Table_ ), 50, 50 ); diff --git a/src/express/resolve.c b/src/express/resolve.c index fa5797917..157529a5f 100644 --- a/src/express/resolve.c +++ b/src/express/resolve.c @@ -1203,7 +1203,7 @@ int WHEREresolve( Linked_List list, Scope scope, int need_self ) { } } -struct tag * TAGcreate_tags() { +struct tag * TAGcreate_tags(void) { extern int tag_count; return( ( struct tag * )calloc( tag_count, sizeof( struct tag ) ) ); diff --git a/src/express/test/CMakeLists.txt b/src/express/test/CMakeLists.txt index 6d2615a9b..413761fd3 100644 --- a/src/express/test/CMakeLists.txt +++ b/src/express/test/CMakeLists.txt @@ -74,8 +74,8 @@ add_test(NAME test_plib_parse_err set_tests_properties( test_plib_parse_err PROPERTIES DEPENDS "build_check_express;$" ) set_tests_properties( test_plib_parse_err build_check_express PROPERTIES LABELS parser ) -sc_addexec(print_schemas SOURCES ../fedex.c print_schemas.c LINK_LIBRARIES express base) -sc_addexec(print_attrs SOURCES ../fedex.c print_attrs.c LINK_LIBRARIES express base) +sc_addexec(print_schemas SOURCES ../fedex.c print_schemas.c LINK_LIBRARIES express) +sc_addexec(print_attrs SOURCES ../fedex.c print_attrs.c LINK_LIBRARIES express) # Local Variables: # tab-width: 8 diff --git a/src/express/test/print_attrs.c b/src/express/test/print_attrs.c index 881ada059..6729a70ce 100644 --- a/src/express/test/print_attrs.c +++ b/src/express/test/print_attrs.c @@ -6,7 +6,7 @@ * print_attrs -a */ -#include "sc_cf.h" +#include "config.h" #include #ifdef HAVE_SYS_PARAM_H # include diff --git a/src/express/test/print_schemas.c b/src/express/test/print_schemas.c index 40bb0a1e0..b0cba2f71 100644 --- a/src/express/test/print_schemas.c +++ b/src/express/test/print_schemas.c @@ -2,7 +2,7 @@ /* prints names of schemas used in an EXPRESS file */ /* symlink.c author: Don Libes, NIST, 20-Mar-1993 */ -#include "sc_cf.h" +#include "config.h" #include #ifdef HAVE_SYS_PARAM_H # include diff --git a/src/express/type.c b/src/express/type.c index ffcba5915..c4b6a7104 100644 --- a/src/express/type.c +++ b/src/express/type.c @@ -220,7 +220,7 @@ return( false ); #endif /** Initialize the Type module */ -void TYPEinitialize() { +void TYPEinitialize(void) { } /** Clean up the Type module */ diff --git a/src/express/variable.c b/src/express/variable.c index b3ec9f88a..c15a41706 100644 --- a/src/express/variable.c +++ b/src/express/variable.c @@ -90,7 +90,7 @@ char * opcode_print( Op_Code o ); /** Initialize the Variable module. */ -void VARinitialize() { +void VARinitialize(void) { } /** VARget_simple_name diff --git a/src/test/p21read/p21read.cc b/src/test/p21read/p21read.cc index cbdbcaa02..cf96b86dd 100644 --- a/src/test/p21read/p21read.cc +++ b/src/test/p21read/p21read.cc @@ -13,12 +13,12 @@ */ extern void SchemaInit( class Registry & ); -#include -#include -#include -#include -#include -#include +#include "cleditor/STEPfile.h" +#include "clstepcore/sdai.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/Registry.h" +#include "clutils/errordesc.h" #include #include #include "sc_benchmark.h" @@ -26,7 +26,66 @@ extern void SchemaInit( class Registry & ); # include #endif -#include +char * sc_optarg; // global argument pointer +int sc_optind = 0; // global argv index + +int sc_getopt( int argc, char * argv[], char * optstring ) { + static char * next = NULL; + if( sc_optind == 0 ) { + next = NULL; + } + + sc_optarg = NULL; + + if( next == NULL || *next == '\0' ) { + if( sc_optind == 0 ) { + sc_optind++; + } + + if( sc_optind >= argc || argv[sc_optind][0] != '-' || argv[sc_optind][1] == '\0' ) { + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + if( strcmp( argv[sc_optind], "--" ) == 0 ) { + sc_optind++; + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + next = argv[sc_optind]; + next++; // skip past - + sc_optind++; + } + + char c = *next++; + char * cp = strchr( optstring, c ); + + if( cp == NULL || c == ':' ) { + return '?'; + } + + cp++; + if( *cp == ':' ) { + if( *next != '\0' ) { + sc_optarg = next; + next = NULL; + } else if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + sc_optind++; + } else { + return '?'; + } + } + + return c; +} /** * Compare the schema names from the lib (generated by exp2cxx) and diff --git a/src/test/p21read/sc_benchmark.cc b/src/test/p21read/sc_benchmark.cc new file mode 100644 index 000000000..2f00cd5a4 --- /dev/null +++ b/src/test/p21read/sc_benchmark.cc @@ -0,0 +1,149 @@ +/// \file sc_benchmark.cc memory info, timers, etc for benchmarking + +#include "./sc_benchmark.h" + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +/// mem values in kb, times in ms (granularity may be higher than 1ms) +benchVals getMemAndTime( ) { + benchVals vals; +#ifdef __linux__ + // adapted from http://stackoverflow.com/questions/669438/how-to-get-memory-usage-at-run-time-in-c + std::ifstream stat_stream( "/proc/self/stat", std::ios_base::in ); + + // dummy vars for leading entries in stat that we don't care about + std::string pid, comm, state, ppid, pgrp, session, tty_nr; + std::string tpgid, flags, minflt, cminflt, majflt, cmajflt; + std::string /*utime, stime,*/ cutime, cstime, priority, nice; + std::string O, itrealvalue, starttime; + + // the fields we want + unsigned long utime, stime, vsize; + long rss; + + stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr + >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt + >> utime >> stime >> cutime >> cstime >> priority >> nice + >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest + + long page_size_kb = sysconf( _SC_PAGE_SIZE ) / 1024; // in case x86-64 is configured to use 2MB pages + vals.physMemKB = rss * page_size_kb; + vals.virtMemKB = ( vsize / 1024 ) - vals.physMemKB; + vals.userMilliseconds = ( utime * 1000 ) / sysconf( _SC_CLK_TCK ); + vals.sysMilliseconds = ( stime * 1000 ) / sysconf( _SC_CLK_TCK ); +#elif defined(__APPLE__) + // http://stackoverflow.com/a/1911863/382458 +#elif defined(_WIN32) + // http://stackoverflow.com/a/282220/382458 and http://stackoverflow.com/a/64166/382458 + PROCESS_MEMORY_COUNTERS MemoryCntrs; + FILETIME CreationTime, ExitTime, KernelTime, UserTime; + long page_size_kb = 1024; + ULARGE_INTEGER kTime, uTime; + + if( GetProcessMemoryInfo( GetCurrentProcess(), &MemoryCntrs, sizeof( MemoryCntrs ) ) ) { + vals.physMemKB = MemoryCntrs.PeakWorkingSetSize / page_size_kb; + vals.virtMemKB = MemoryCntrs.PeakPagefileUsage / page_size_kb; + } else { + vals.physMemKB = 0; + vals.virtMemKB = 0; + } + + if( GetProcessTimes( GetCurrentProcess(), &CreationTime, &ExitTime, &KernelTime, &UserTime ) ) { + assert( sizeof( FILETIME ) == sizeof( ULARGE_INTEGER ) ); + memcpy( &kTime, &KernelTime, sizeof( FILETIME ) ); + memcpy( &uTime, &UserTime, sizeof( FILETIME ) ); + vals.userMilliseconds = ( long )( uTime.QuadPart / 100000L ); + vals.sysMilliseconds = ( long )( kTime.QuadPart / 100000L ); + } else { + vals.userMilliseconds = 0; + vals.sysMilliseconds = 0; + } +#else +#warning Unknown platform! +#endif // __linux__ + return vals; +} + +// --------------------- benchmark class --------------------- + +benchmark::benchmark( std::string description, bool debugMessages, std::ostream & o_stream ): ostr( o_stream ), + descr( description ), debug( debugMessages ), stopped( false ) { + initialVals = getMemAndTime( ); +} + +benchmark::~benchmark() { + if( !stopped ) { + stop( ); + if( debug ) { + ostr << "benchmark::~benchmark(): stop was not called before destructor!" << std::endl; + } + out( ); + } +} + +void benchmark::stop( ) { + if( stopped ) { + std::cerr << "benchmark::stop(): tried to stop a benchmark that was already stopped!" << std::endl; + } else { + laterVals = getMemAndTime( ); + stopped = true; + } +} + +benchVals benchmark::get( ) { + if( !stopped ) { + laterVals = getMemAndTime( ); + } + benchVals delta; + delta.physMemKB = laterVals.physMemKB - initialVals.physMemKB; + delta.virtMemKB = laterVals.virtMemKB - initialVals.virtMemKB; + delta.sysMilliseconds = laterVals.sysMilliseconds - initialVals.sysMilliseconds; + delta.userMilliseconds = laterVals.userMilliseconds - initialVals.userMilliseconds; + + //If vm is negative, the memory had been requested before initialVals was set. Don't count it + if( delta.virtMemKB < 0 ) { + delta.physMemKB -= delta.virtMemKB; + delta.virtMemKB = 0; + } + return delta; +} + +void benchmark::reset( std::string description ) { + descr = description; + reset(); +} +void benchmark::reset( ) { + stopped = false; + initialVals = getMemAndTime(); +} + +std::string benchmark::str( ) { + return str( get( ) ); +} + +void benchmark::out() { + ostr << str( ) << std::endl; +} + +std::string benchmark::str( const benchVals & bv ) { + std::stringstream ss; + ss << descr << " Physical memory: " << bv.physMemKB << "kb; Virtual memory: " << bv.virtMemKB; + ss << "kb; User CPU time: " << bv.userMilliseconds << "ms; System CPU time: " << bv.sysMilliseconds << "ms"; + return ss.str(); +} + diff --git a/src/test/p21read/sc_benchmark.h b/src/test/p21read/sc_benchmark.h new file mode 100644 index 000000000..5b77317c4 --- /dev/null +++ b/src/test/p21read/sc_benchmark.h @@ -0,0 +1,74 @@ +#ifndef SC_BENCHMARK_H +#define SC_BENCHMARK_H +/// \file sc_benchmark.h memory info, timers, etc for benchmarking + +#ifdef __cplusplus +#include +#include +#include + +extern "C" { +#endif + + typedef struct { + long virtMemKB, physMemKB, userMilliseconds, sysMilliseconds; + } benchVals; + + /** return a benchVals struct with four current statistics for this process: + * virtual and physical memory use in kb, + * user and system cpu time in ms + * + * not yet implemented for OSX or Windows. + */ + benchVals getMemAndTime( ); + +#ifdef __cplusplus +} + + +/** reports the difference in memory and cpu use between when the + * constructor is called and when stop() or the destructor is called. + * + * if the destructor is called and stop() had not previously been + * called, the results are printed to the ostream given in the + * constructor, prefixed by the description. + * + * depends on getMemAndTime() above - may not work on all platforms. + */ + +class benchmark { + protected: + benchVals initialVals, laterVals; +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable: 4251 ) +#endif + std::ostream & ostr; + std::string descr; +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + bool debug, stopped; + public: + benchmark( std::string description = "", bool debugMessages = true, std::ostream & o_stream = std::cout ); + + /// if 'stopped' is false, uses str(true) to print to ostream + ~benchmark( ); + void reset( ); + void reset( std::string description ); + benchVals get( ); + void stop( ); + + /// converts data member 'laterVals' into a string and returns it + std::string str( ); + + /// outputs result of str() on ostream 'ostr' + void out( ); + + /// converts 'bv' into a string, prefixed by data member 'descr' + std::string str( const benchVals & bv ); +}; + + +#endif //__cplusplus +#endif //SC_BENCHMARK_H diff --git a/src/test/scl2html/scl2html.cc b/src/test/scl2html/scl2html.cc index f597b36e4..afe65b11f 100644 --- a/src/test/scl2html/scl2html.cc +++ b/src/test/scl2html/scl2html.cc @@ -49,7 +49,7 @@ void PrintAttrTypeWithAnchor( const TypeDescriptor * typeDesc, ofstream & outhtml ) { std::string buf; - // The type. See src/clstepcore/baseType.h for info + // The type. See clstepcore/baseType.h for info PrimitiveType base = typeDesc->Type(); // the type descriptor for the "referent type," if any. diff --git a/src/test/tests.h b/src/test/tests.h index 52fcb3a59..0494b55d2 100644 --- a/src/test/tests.h +++ b/src/test/tests.h @@ -16,10 +16,10 @@ #include /* General SCL stuff */ -#include -#include -#include -#include +#include "clstepcore/ExpDict.h" +#include "cleditor/STEPfile.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/sdai.h" /* Stuff more or less specifically for the Example schema */ /* The only program that needs this is tstatic. Since the other programs */ diff --git a/test/cpp/schema_specific/CMakeLists.txt b/test/cpp/schema_specific/CMakeLists.txt index 44fa4e5bc..e1bd06e10 100644 --- a/test/cpp/schema_specific/CMakeLists.txt +++ b/test/cpp/schema_specific/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.12) #c++ tests that depend on a particular schema include_directories( ${SC_SOURCE_DIR}/src/cldai ${SC_SOURCE_DIR}/src/cleditor ${SC_SOURCE_DIR}/src/clutils - ${SC_SOURCE_DIR}/src/clstepcore ${SC_SOURCE_DIR}/src/base ) + ${SC_SOURCE_DIR}/src/clstepcore ) # helper function for add_schema_dependent_test # given an sdai target, set out_path_var to the include dir @@ -92,7 +92,7 @@ set_tests_properties( test_aggregate_bound_runtime_FAIL1 PROPERTIES add_schema_dependent_test( "inverse_attr1" "inverse_attr" "${SC_SOURCE_DIR}/test/p21/test_inverse_attr.p21" ) add_schema_dependent_test( "inverse_attr2" "inverse_attr" "${SC_SOURCE_DIR}/test/p21/test_inverse_attr.p21" ) add_schema_dependent_test( "inverse_attr3" "inverse_attr" "${SC_SOURCE_DIR}/test/p21/test_inverse_attr.p21" - "${SC_SOURCE_DIR}/src/cllazyfile;${SC_SOURCE_DIR}/src/base/judy/src" "" "steplazyfile" ) + "${SC_SOURCE_DIR}/src/cllazyfile;${SC_SOURCE_DIR}/src/cllazyfile/judy/src" "" "steplazyfile" ) add_schema_dependent_test( "attribute" "inverse_attr" "${SC_SOURCE_DIR}/test/p21/test_inverse_attr.p21" ) if(HAVE_STD_THREAD) diff --git a/test/cpp/schema_specific/aggregate_bound_runtime.cc b/test/cpp/schema_specific/aggregate_bound_runtime.cc index fe103ab8e..f459697e6 100644 --- a/test/cpp/schema_specific/aggregate_bound_runtime.cc +++ b/test/cpp/schema_specific/aggregate_bound_runtime.cc @@ -1,10 +1,10 @@ -#include -#include -#include -#include -#include -#include +#include "cleditor/STEPfile.h" +#include "clstepcore/sdai.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/Registry.h" +#include "clutils/errordesc.h" #include #include #ifdef HAVE_UNISTD_H diff --git a/test/cpp/schema_specific/attribute.cc b/test/cpp/schema_specific/attribute.cc index a74cee078..4fab32933 100644 --- a/test/cpp/schema_specific/attribute.cc +++ b/test/cpp/schema_specific/attribute.cc @@ -2,22 +2,80 @@ * 1-Jul-2012 * Test attribute access; uses a tiny schema similar to a subset of IFC2x3 */ -#include -#include -#include -#include -#include -#include -#include +#include "config.h" +#include "cleditor/STEPfile.h" +#include "clstepcore/sdai.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/Registry.h" +#include "clutils/errordesc.h" #include #include #ifdef HAVE_UNISTD_H # include #endif -#include #include "schema.h" +char * sc_optarg; // global argument pointer +int sc_optind = 0; // global argv index +int sc_getopt( int argc, char * argv[], char * optstring ) { + static char * next = NULL; + if( sc_optind == 0 ) { + next = NULL; + } + + sc_optarg = NULL; + + if( next == NULL || *next == '\0' ) { + if( sc_optind == 0 ) { + sc_optind++; + } + + if( sc_optind >= argc || argv[sc_optind][0] != '-' || argv[sc_optind][1] == '\0' ) { + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + if( strcmp( argv[sc_optind], "--" ) == 0 ) { + sc_optind++; + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + next = argv[sc_optind]; + next++; // skip past - + sc_optind++; + } + + char c = *next++; + char * cp = strchr( optstring, c ); + + if( cp == NULL || c == ':' ) { + return '?'; + } + + cp++; + if( *cp == ':' ) { + if( *next != '\0' ) { + sc_optarg = next; + next = NULL; + } else if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + sc_optind++; + } else { + return '?'; + } + } + + return c; +} int main( int argc, char * argv[] ) { Registry registry( SchemaInit ); InstMgr instance_list; diff --git a/test/cpp/schema_specific/inverse_attr1.cc b/test/cpp/schema_specific/inverse_attr1.cc index c06177b1c..9f776a37a 100644 --- a/test/cpp/schema_specific/inverse_attr1.cc +++ b/test/cpp/schema_specific/inverse_attr1.cc @@ -3,22 +3,82 @@ ** Test inverse attributes; uses a tiny schema similar to a subset of IFC2x3 ** */ -#include -#include "SubSuperIterators.h" -#include -#include -#include -#include -#include -#include +#include "config.h" +#include "clstepcore/SubSuperIterators.h" +#include "cleditor/STEPfile.h" +#include "clstepcore/sdai.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/Registry.h" +#include "clutils/errordesc.h" #include #include #ifdef HAVE_UNISTD_H # include #endif -#include #include "schema.h" +char * sc_optarg; // global argument pointer +int sc_optind = 0; // global argv index + +int sc_getopt( int argc, char * argv[], char * optstring ) { + static char * next = NULL; + if( sc_optind == 0 ) { + next = NULL; + } + + sc_optarg = NULL; + + if( next == NULL || *next == '\0' ) { + if( sc_optind == 0 ) { + sc_optind++; + } + + if( sc_optind >= argc || argv[sc_optind][0] != '-' || argv[sc_optind][1] == '\0' ) { + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + if( strcmp( argv[sc_optind], "--" ) == 0 ) { + sc_optind++; + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + next = argv[sc_optind]; + next++; // skip past - + sc_optind++; + } + + char c = *next++; + char * cp = strchr( optstring, c ); + + if( cp == NULL || c == ':' ) { + return '?'; + } + + cp++; + if( *cp == ':' ) { + if( *next != '\0' ) { + sc_optarg = next; + next = NULL; + } else if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + sc_optind++; + } else { + return '?'; + } + } + + return c; +} + ///first way of finding inverse attrs bool findInverseAttrs1( InverseAItr iai, InstMgr & instList ) { const Inverse_attribute * ia; diff --git a/test/cpp/schema_specific/inverse_attr2.cc b/test/cpp/schema_specific/inverse_attr2.cc index 2f3fdf233..cdf8dbbd0 100644 --- a/test/cpp/schema_specific/inverse_attr2.cc +++ b/test/cpp/schema_specific/inverse_attr2.cc @@ -3,21 +3,80 @@ ** Test inverse attributes; uses a tiny schema similar to a subset of IFC2x3 ** */ -#include -#include -#include -#include -#include -#include -#include +#include "config.h" +#include "cleditor/STEPfile.h" +#include "clstepcore/sdai.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/Registry.h" +#include "clutils/errordesc.h" #include #include #ifdef HAVE_UNISTD_H # include #endif -#include #include "schema.h" +char * sc_optarg; // global argument pointer +int sc_optind = 0; // global argv index + +int sc_getopt( int argc, char * argv[], char * optstring ) { + static char * next = NULL; + if( sc_optind == 0 ) { + next = NULL; + } + + sc_optarg = NULL; + + if( next == NULL || *next == '\0' ) { + if( sc_optind == 0 ) { + sc_optind++; + } + + if( sc_optind >= argc || argv[sc_optind][0] != '-' || argv[sc_optind][1] == '\0' ) { + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + if( strcmp( argv[sc_optind], "--" ) == 0 ) { + sc_optind++; + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + next = argv[sc_optind]; + next++; // skip past - + sc_optind++; + } + + char c = *next++; + char * cp = strchr( optstring, c ); + + if( cp == NULL || c == ':' ) { + return '?'; + } + + cp++; + if( *cp == ':' ) { + if( *next != '\0' ) { + sc_optarg = next; + next = NULL; + } else if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + sc_optind++; + } else { + return '?'; + } + } + + return c; +} ///second way of finding inverse attrs bool findInverseAttrs2( InverseAItr iai, InstMgr & instList, Registry & reg ) { const Inverse_attribute * ia; diff --git a/test/cpp/schema_specific/inverse_attr3.cc b/test/cpp/schema_specific/inverse_attr3.cc index 866801dbf..bb4ce0929 100644 --- a/test/cpp/schema_specific/inverse_attr3.cc +++ b/test/cpp/schema_specific/inverse_attr3.cc @@ -4,14 +4,14 @@ * * This test originally used STEPfile, which didn't work. Fixing STEPfile would have been very difficult, it uses lazyInstMgr now. */ -#include -#include +#include "config.h" +#include "cllazyfile/lazyInstMgr.h" #include -#include -#include -#include -#include -#include +#include "clstepcore/sdai.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/Registry.h" +#include "clutils/errordesc.h" #include #include #include @@ -19,9 +19,70 @@ #ifdef HAVE_UNISTD_H # include #endif -#include #include "schema.h" +char * sc_optarg; // global argument pointer +int sc_optind = 0; // global argv index + +int sc_getopt( int argc, char * argv[], char * optstring ) { + static char * next = NULL; + if( sc_optind == 0 ) { + next = NULL; + } + + sc_optarg = NULL; + + if( next == NULL || *next == '\0' ) { + if( sc_optind == 0 ) { + sc_optind++; + } + + if( sc_optind >= argc || argv[sc_optind][0] != '-' || argv[sc_optind][1] == '\0' ) { + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + if( strcmp( argv[sc_optind], "--" ) == 0 ) { + sc_optind++; + sc_optarg = NULL; + if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + } + return EOF; + } + + next = argv[sc_optind]; + next++; // skip past - + sc_optind++; + } + + char c = *next++; + char * cp = strchr( optstring, c ); + + if( cp == NULL || c == ':' ) { + return '?'; + } + + cp++; + if( *cp == ':' ) { + if( *next != '\0' ) { + sc_optarg = next; + next = NULL; + } else if( sc_optind < argc ) { + sc_optarg = argv[sc_optind]; + sc_optind++; + } else { + return '?'; + } + } + + return c; +} + + int main( int argc, char * argv[] ) { int exitStatus = EXIT_SUCCESS; if( argc != 2 ) { diff --git a/test/cpp/schema_specific/stepfile_rw_progress.cc b/test/cpp/schema_specific/stepfile_rw_progress.cc index e007c7f37..1fe5cb0dc 100644 --- a/test/cpp/schema_specific/stepfile_rw_progress.cc +++ b/test/cpp/schema_specific/stepfile_rw_progress.cc @@ -1,10 +1,10 @@ -#include -#include -#include -#include -#include -#include +#include "cleditor/STEPfile.h" +#include "clstepcore/sdai.h" +#include "clstepcore/STEPattribute.h" +#include "clstepcore/ExpDict.h" +#include "clstepcore/Registry.h" +#include "clutils/errordesc.h" #include #include