Compare commits

..
Author SHA1 Message Date
Chris HORLER e5d6a9d81f (rework) compile fixes to be integrated by rebase 2021-08-07 10:00:54 +01:00
Chris HORLER 3e7efdc741 clean-up some compiler warnings 2021-08-07 10:00:54 +01:00
Chris HORLER 7872408f74 make Symbol name const char * 2021-08-07 10:00:54 +01:00
Chris HORLER 4fa37b0b10 fix a ref / use typo 2021-08-07 10:00:54 +01:00
Chris HORLER 301af992fe fix some type issues introduced when factoring out DICT_type 2021-08-07 10:00:54 +01:00
Chris HORLER 439ae24705 move SYMBOL_new / SYMBOL_destroy to memory.c 2021-08-07 10:00:54 +01:00
Chris HORLER 04112340a0 update libexpress tests for DICT to HASH refactoring 2021-08-07 10:00:54 +01:00
Chris HORLER c4470046b3 integrate new parser / lexer into build 2021-08-07 10:00:54 +01:00
Chris HORLER 11aa1a5f5b use sc_alloc / sc_free more widely, and change #defines so they work as function pointers - for use with Lemon / RE2C 2021-08-07 10:00:54 +01:00
Chris HORLER f84a72aa37 initial steps towards using HASH as the ubiquitous Symbol table 2021-08-07 10:00:54 +01:00
Chris HORLER 9b606a9004 Parser tests
- fix lexer scope types
- fix resolve_symbol to return T_SIMPLE_REF by default (this is what the parser expects)
2021-08-07 10:00:54 +01:00
Chris HORLER 92cb70de2b CMake changes
- simplify the Lemon and RE2C modules
2021-08-07 10:00:54 +01:00
Chris HORLER 0d63c63d4c move everything scope related from expscan.l to lexsupport.[ch] 2021-08-07 10:00:54 +01:00
Chris HORLER bb0008f941 update tests to invoke scanner_test for all *.exp 2021-08-07 10:00:54 +01:00
Chris HORLER 91046817b1 update the scanner to use Hash_Table, add first scanner test 2021-08-07 10:00:54 +01:00
Chris HORLER c15d8d7336 migrate HASH memory macro definitions to implementation file 2021-08-07 10:00:54 +01:00
Chris HORLER 9b3d014c3e refactor HASH to work directly with Symbols 2021-08-07 10:00:54 +01:00
Chris HORLER 9e261a8ffc HASHdelete tests, slight changes to HASHsearch 2021-08-07 10:00:54 +01:00
Chris HORLER 3957f970eb fix HASHdo 2021-08-07 10:00:54 +01:00
Chris HORLER 0ad0cdef14 rewrite of the hash implementation
* first test case (all ids, insert, find)
* simplified / improved implementation
* added a HASHdelete method to have a consistent API
* explained the implementation and the benefits / drawbacks
* renamed the HASHlist interface to HASHdo, and Hash_Iterator
2021-08-07 10:00:54 +01:00
Chris HORLER b1844be9cc update build system
- CMake 3.3 required
- Simplify RE2C detection and add a version check capability
- add missing build option
- make some dependencies conditional (temporary solution)
2021-08-07 10:00:54 +01:00
Chris HORLER f744ba3265 update the refactoring scope struct to reflect integration requirements 2021-08-07 10:00:54 +01:00
Chris HORLER 089762d84a add ref_typ field to struct Symbol_ in order to drive lex token types 2021-08-07 10:00:54 +01:00
Chris HORLER 317c9173ec clean up the HASHlist interface 2021-08-07 10:00:54 +01:00
Chris HORLER 0510de8634 rename DICT_define to DICTdefine_enum 2021-08-07 10:00:54 +01:00
Chris HORLER 9f29353db3 clean up the DICT interface a little bit 2021-08-07 10:00:54 +01:00
Chris HORLER 469a6e45d4 initial commit for p11 parser / lexer rewrite 2021-08-07 10:00:54 +01:00
521 changed files with 79284 additions and 150679 deletions
+65
View File
@@ -0,0 +1,65 @@
version: '{build}'
# for Appveyor CI (windows)
branches:
only:
- master
os: Windows Server 2012 R2
clone_folder: c:\projects\STEPcode
#grab zip instead of git clone
shallow_clone: true
platform: x64
configuration: Debug
# errors or couldn't be found by cmake
# - GENERATOR: "Visual Studio 9 2008"
# ARCH: 32
# - GENERATOR: "Visual Studio 10"
# ARCH: 32
#no point in these without artifact support...
# - GENERATOR: "Visual Studio 11"
#ARCH: 32
#- GENERATOR: "Visual Studio 12"
#ARCH: 32
environment:
matrix:
- GENERATOR: "Visual Studio 12 Win64"
ARCH: 64
# build:
# parallel: true
# project: ALL_BUILD.vcxproj
#appveyor limits compile/test to 30 minutes
# to reduce time, only test schemas with files: ifc2x3, ap214e3, ap209
build_script:
- ps: |
cd c:\projects\STEPcode
mkdir build
cd build
cmake -version
grep --version
cmake .. -DSC_ENABLE_TESTING=ON -G"$env:GENERATOR" -DSC_BUILD_SCHEMAS="ifc2x3;ap214e3;ap209"
echo "filtering build output with grep"
cmake --build . --config Debug | grep -ve "CMake does not need to re-run because" -e "ZERO_CHECK.ZERO_CHECK" -e "^ Creating directory"
#msbuld seems to provide no benefits, and I can't filter its output...
#msbuild SC.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" /p:Configuration=Debug /p:Platform=x64
# /toolsversion:14.0 /p:PlatformToolset=v140
test_script:
- cmd: echo Running CTest...
- cmd: cd c:\projects\STEPcode\build
- cmd: echo excluding test_inverse_attr3, which hangs
- cmd: ctest -j1 . -C Debug --output-on-failure
# - cmd: grep -niB20 "Test Failed" Testing/Temporary/LastTest.log
# we could upload a compiled zip somewhere (see Appveyor artifact documentation)
-286
View File
@@ -1,286 +0,0 @@
name: STEPCODE
on:
workflow_dispatch:
pull_request:
jobs:
windows:
name: Windows Latest MSVC
runs-on: windows-latest
strategy:
fail-fast: true
steps:
- name: Setup - CMake
uses: lukka/get-cmake@latest
- name: Setup - Ninja
uses: seanmiddleditch/gha-setup-ninja@master
- name: Checkout
uses: actions/checkout@v2
- 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
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
- name: Add cl.exe to PATH
uses: ilammy/msvc-dev-cmd@v1
- name: Configure
run: |
cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER="cl.exe" -DCMAKE_CXX_COMPILER="cl.exe" -DSC_ENABLE_TESTING=ON
# 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
- name: Build
run: cd build && ninja -j1 -v
- name: Test
run: |
cd build && ctest --verbose -j1 .
linux:
name: Ubuntu Latest GCC
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
# TODO - we will want this when the new parser work comes in,
# as we won't need perplex and the system tools should suffice
# to exercise the generator logic:
#
# - name: Setup - System
# env:
# DEBIAN_FRONTEND: noninteractive
# run: |
# sudo apt-get update
# # Install dev tools
# sudo apt-get install re2c lemon
# sudo apt-get clean
- name: Checkout
uses: actions/checkout@v2
- name: Configure
run: |
export PATH=$ENV{GITHUB_WORKSPACE}:$PATH
cmake -S . -G Ninja -B build -D ENABLE_ALL=ON -D CMAKE_BUILD_TYPE=Release -DSC_ENABLE_TESTING=ON
- name: Build
run: |
export PATH=$ENV{GITHUB_WORKSPACE}:$PATH
cmake --build build --config Release
- name: Test
run: |
cd build && ctest --verbose -j1 . -C Release
linux_clang:
name: Ubuntu Latest Clang
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
# TODO - we will want this when the new parser work comes in,
# as we won't need perplex and the system tools should suffice
# to exercise the generator logic:
#
# - name: Setup - System
# env:
# DEBIAN_FRONTEND: noninteractive
# run: |
# sudo apt-get update
# # Install dev tools
# sudo apt-get install re2c lemon
# sudo apt-get clean
- name: Checkout
uses: actions/checkout@v2
- name: Configure
run: |
export PATH=$ENV{GITHUB_WORKSPACE}:$PATH
CC=clang CXX=clang++ cmake -S . -G Ninja -B build -D ENABLE_ALL=ON -D CMAKE_BUILD_TYPE=Release -DSC_ENABLE_TESTING=ON
- name: Build
run: |
export PATH=$ENV{GITHUB_WORKSPACE}:$PATH
CC=clang CXX=clang++ cmake --build build --config Release
- name: Test
run: |
cd build && ctest --verbose -j1 . -C Release
osx:
name: macOS Latest Clang
runs-on: macos-latest
strategy:
fail-fast: true
steps:
- name: Setup - CMake
uses: lukka/get-cmake@latest
- name: Setup - Ninja
uses: seanmiddleditch/gha-setup-ninja@master
- name: Checkout
uses: actions/checkout@v2
- name: Configure
run: |
export PATH=$ENV{GITHUB_WORKSPACE}:$PATH
export CC=clang
export CXX=clang++
cmake -S . -G Ninja -B build -D CMAKE_BUILD_TYPE=Release -DSC_ENABLE_TESTING=ON
- name: Build
run: |
export PATH=$ENV{GITHUB_WORKSPACE}:$PATH
cd build && ninja -j1
- name: Test
run: |
cd build && ctest --verbose -j1 . -C Release
brlcad_linux:
name: BRL-CAD Linux step-g Test
runs-on: ubuntu-latest
strategy:
fail-fast: true
steps:
- name: Setup - CMake
uses: lukka/get-cmake@latest
- name: Setup - System
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo apt-get update
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: 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: |
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: |
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: |
cd brlcad_build
cmake --build . --target step-g
cd ..
- name: Test
run: |
cd brlcad_build
./bin/step-g ../brlcad/db/nist/NIST_MBE_PMI_3.stp -o nist3.g
cd ..
brlcad_windows:
name: BRL-CAD Windows step-g Test
runs-on: windows-latest
strategy:
fail-fast: true
steps:
- name: Setup - CMake
uses: lukka/get-cmake@latest
- 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
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
- name: Add cl.exe to PATH
uses: ilammy/msvc-dev-cmd@v1
- 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
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: |
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
cmake --build . --config Release --target step-g
cd ..
- name: Test
run: |
cd brlcad_build
./bin/step-g.exe ../brlcad/db/nist/NIST_MBE_PMI_3.stp -o nist3.g
cd ..
-22
View File
@@ -1,25 +1,3 @@
# Common build directories used in the source tree
/build
/build-*
/.build
# Temporary files
*~
\#*\#
.\#*
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
**/__pycache__/
# OS specific files
.DS_Store
.DS_Store?
# Tool specific patterns
*.kdev4
.kdev_include_paths
# Parser generator intermediate files
*.out
+16
View File
@@ -0,0 +1,16 @@
sudo: false
language: cpp
compiler:
- clang
script: mkdir build && cd build && cmake .. -DSC_ENABLE_TESTING=ON && make -j3 && ctest -j2 --output-on-failure
branches:
only:
- master
notifications:
irc: "chat.freenode.net#stepcode"
email: scl-dev@groups.google.com
on_success: change
on_failure: always
os:
- linux
- osx
-1
View File
@@ -19,7 +19,6 @@ 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)
+50 -235
View File
@@ -40,248 +40,57 @@
project(SC)
# Minimum required version of CMake
cmake_minimum_required(VERSION 3.12)
if (POLICY CMP0077)
cmake_policy(SET CMP0077 OLD)
endif (POLICY CMP0077)
# SC version
set(SC_VERSION_MAJOR 0)
set(SC_VERSION_MINOR 9)
set(SC_VERSION_PATCH 1)
set(SC_VERSION ${SC_VERSION_MAJOR}.${SC_VERSION_MINOR}.${SC_VERSION_PATCH})
set(SC_VERSION_MINOR 8-dev)
set(SC_VERSION ${SC_VERSION_MAJOR}.${SC_VERSION_MINOR})
# Set language standards
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# SC ABI version. SC_ABI_SOVERSION should be incremented
# for each release introducing API incompatibilities
set(SC_ABI_SOVERSION 2)
set(SC_ABI_VERSION ${SC_ABI_SOVERSION}.0.0)
# Minimum required version of CMake
cmake_minimum_required(VERSION 3.6.3)
cmake_policy(SET CMP0003 NEW)
cmake_policy(SET CMP0026 NEW)
cmake_policy(SET CMP0057 NEW)
# CMake derives much of its functionality from modules, typically
# stored in one directory - let CMake know where to find them.
set(SC_CMAKE_DIR "${SC_SOURCE_DIR}/cmake")
list(APPEND CMAKE_MODULE_PATH "${SC_CMAKE_DIR}")
if(NOT SC_IS_SUBBUILD)
set(CMAKE_MODULE_PATH "${SC_CMAKE_DIR};${CMAKE_MODULE_PATH}")
else(NOT SC_IS_SUBBUILD)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${SC_CMAKE_DIR}")
endif(NOT SC_IS_SUBBUILD)
# OpenBSD has its own naming conventions. Set a platform variable based on
# the OS name so we can test for it succinctly.
if ("${CMAKE_SYSTEM}" MATCHES ".*OpenBSD.*")
set(OPENBSD ON)
endif ("${CMAKE_SYSTEM}" MATCHES ".*OpenBSD.*")
#---------------------------------------------------------------------
# Set up various relative path variables and build output directories
include(Path_Setup)
#---------------------------------------------------------------------
# The following logic is what allows binaries to run successfully in
# the build directory AND install directory. Thanks to plplot for
# identifying the necessity of setting CMAKE_INSTALL_NAME_DIR on OSX.
# Documentation of these options is available at
# http://www.cmake.org/Wiki/CMake_RPATH_handling
# use, i.e. don't skip the full RPATH for the build tree
if(NOT DEFINED CMAKE_SKIP_BUILD_RPATH)
set(CMAKE_SKIP_BUILD_RPATH FALSE)
endif()
# when building, don't use the install RPATH already
# (but later on when installing)
if(NOT DEFINED CMAKE_BUILD_WITH_INSTALL_RPATH)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
endif()
# the RPATH/INSTALL_NAME_DIR to be used when installing
if (NOT APPLE)
if(NOT DEFINED CMAKE_INSTALL_RPATH)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib:\$ORIGIN/../lib")
endif()
endif(NOT APPLE)
# On OSX, we need to set INSTALL_NAME_DIR instead of RPATH
# http://www.cmake.org/cmake/help/cmake-2-8-docs.html#variable:CMAKE_INSTALL_NAME_DIR
if(NOT DEFINED CMAKE_INSTALL_NAME_DIR)
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
endif()
# add the automatically determined parts of the RPATH which point to
# directories outside the build tree to the install RPATH
if(NOT DEFINED CMAKE_INSTALL_RPATH_USE_LINK_PATH)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
endif()
#---------------------------------------------------------------------
# Build options
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(BUILD_STATIC_LIBS "Build static libraries" OFF)
option(SC_PYTHON_GENERATOR "Compile exp2python" ON)
option(SC_CPP_GENERATOR "Compile exp2cxx" ON)
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)
if (SC_ENABLE_COVERAGE AND ${CMAKE_C_COMPILER_ID} STREQUAL "GNU")
set(CMAKE_C_FLAGS_DEBUG "-O0 -g -fprofile-arcs -ftest-coverage" CACHE STRING "Extra compile flags required by code coverage" FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -fprofile-arcs -ftest-coverage" CACHE STRING "Extra compile flags required by code coverage" FORCE)
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "-fprofile-arcs -ftest-coverage" CACHE STRING "Extra linker flags required by code coverage" FORCE)
endif (SC_ENABLE_COVERAGE AND ${CMAKE_C_COMPILER_ID} STREQUAL "GNU")
option(SC_ENABLE_ADDRESS_SANITIZER "Enable AddressSanitizer instrumentation" OFF)
option(SC_ENABLE_UNDEFINED_SANITIZER "Enable UndefinedBehaviorSanitizer instrumentation" OFF)
option(SC_ENABLE_THREAD_SANITIZER "Enable ThreadSanitizer instrumentation" OFF)
if(SC_ENABLE_THREAD_SANITIZER AND
(SC_ENABLE_ADDRESS_SANITIZER OR SC_ENABLE_UNDEFINED_SANITIZER))
message(FATAL_ERROR
"SC_ENABLE_THREAD_SANITIZER must use a separate build from "
"AddressSanitizer and UndefinedBehaviorSanitizer"
)
endif()
option(SC_BUILD_EXPRESS_ONLY "Only build express parser." OFF)
mark_as_advanced(SC_BUILD_EXPRESS_ONLY)
option(SC_ENABLE_TESTING "Enable unittesting framework" OFF)
if(SC_ENABLE_TESTING)
if(NOT "${SC_BUILD_EXPRESS_ONLY}" AND NOT DEFINED SC_BUILD_SCHEMAS)
set(SC_BUILD_SCHEMAS "ALL") #test all schemas, unless otherwise specified
endif()
include(CTest)
endif(SC_ENABLE_TESTING)
# testing and compilation options, build output dirs, install dirs, uninstall, package creation, etc
include(${SC_CMAKE_DIR}/SC_Build_opts.cmake)
# SC_ADDEXEC and SC_ADDLIB macros, dllimport/export, etc
include(SC_Targets)
include(${SC_CMAKE_DIR}/SC_Targets.cmake)
# Macros related to paths
include(SC_Paths)
include(${SC_CMAKE_DIR}/SC_Paths.cmake)
# locale stuff
include(SC_Locale)
include(${SC_CMAKE_DIR}/SC_Locale.cmake)
# logic related to regenerating the lexer and parser source code
include(SC_Regenerate)
# create config.h header
include(SC_Config_Headers)
# Apply sanitizer instrumentation after configure-time feature tests so their
# try-compile executables do not depend on sanitizer runtime behavior. Keep
# link flags explicit for CMake 3.12 compatibility (add_link_options was added
# in CMake 3.13).
if(SC_ENABLE_ADDRESS_SANITIZER OR
SC_ENABLE_UNDEFINED_SANITIZER OR
SC_ENABLE_THREAD_SANITIZER)
if(MSVC)
message(FATAL_ERROR "STEPcode sanitizer builds are not yet supported with MSVC")
endif()
include(CMakePushCheckState)
include(CheckCSourceCompiles)
include(CheckCXXSourceCompiles)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
set(_sc_sanitizer_compile_options)
set(_sc_sanitizer_link_options)
function(sc_require_sanitizer FLAG RESULT_PREFIX)
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
list(APPEND CMAKE_REQUIRED_LIBRARIES "${FLAG}")
check_c_source_compiles("int main(void) { return 0; }" ${RESULT_PREFIX}_C_SUPPORTED)
check_cxx_source_compiles("int main() { return 0; }" ${RESULT_PREFIX}_CXX_SUPPORTED)
cmake_pop_check_state()
if(NOT ${RESULT_PREFIX}_C_SUPPORTED OR NOT ${RESULT_PREFIX}_CXX_SUPPORTED)
message(FATAL_ERROR
"STEPcode sanitizer mode was requested, but the C/C++ compiler and "
"linker do not support ${FLAG}"
)
endif()
endfunction()
if(SC_ENABLE_ADDRESS_SANITIZER)
sc_require_sanitizer("-fsanitize=address" SC_ASAN)
list(APPEND _sc_sanitizer_compile_options -fsanitize=address)
list(APPEND _sc_sanitizer_link_options -fsanitize=address)
# exp2cxx is executed during the build to generate schema bindings. It
# remains address-instrumented, but leak checking a short-lived build
# tool is both outside the test scope and unsupported under common build
# tracers/sandboxes. Limit this environment to schema generation; CTest
# and installed tools retain the user's normal ASan settings.
set(SC_SCHEMA_GENERATOR_ENVIRONMENT "ASAN_OPTIONS=detect_leaks=0")
endif()
if(SC_ENABLE_UNDEFINED_SANITIZER)
sc_require_sanitizer("-fsanitize=undefined" SC_UBSAN)
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "-fsanitize=undefined")
list(APPEND CMAKE_REQUIRED_LIBRARIES "-fsanitize=undefined")
check_c_compiler_flag(
"-fno-sanitize-recover=undefined"
SC_UBSAN_C_NO_RECOVER_SUPPORTED
)
check_cxx_compiler_flag(
"-fno-sanitize-recover=undefined"
SC_UBSAN_CXX_NO_RECOVER_SUPPORTED
)
cmake_pop_check_state()
if(NOT SC_UBSAN_C_NO_RECOVER_SUPPORTED OR
NOT SC_UBSAN_CXX_NO_RECOVER_SUPPORTED)
message(FATAL_ERROR
"STEPcode's fail-fast UndefinedBehaviorSanitizer mode was requested, "
"but the C/C++ compiler does not support "
"-fno-sanitize-recover=undefined"
)
endif()
list(APPEND _sc_sanitizer_compile_options
-fsanitize=undefined
-fno-sanitize-recover=undefined
)
list(APPEND _sc_sanitizer_link_options -fsanitize=undefined)
endif()
if(SC_ENABLE_THREAD_SANITIZER)
sc_require_sanitizer("-fsanitize=thread" SC_TSAN)
list(APPEND _sc_sanitizer_compile_options -fsanitize=thread)
list(APPEND _sc_sanitizer_link_options -fsanitize=thread)
endif()
check_c_compiler_flag("-fno-omit-frame-pointer" SC_SANITIZER_C_FRAME_POINTER_SUPPORTED)
check_cxx_compiler_flag("-fno-omit-frame-pointer" SC_SANITIZER_CXX_FRAME_POINTER_SUPPORTED)
if(SC_SANITIZER_C_FRAME_POINTER_SUPPORTED)
list(APPEND _sc_sanitizer_compile_options
$<$<COMPILE_LANGUAGE:C>:-fno-omit-frame-pointer>
)
endif()
if(SC_SANITIZER_CXX_FRAME_POINTER_SUPPORTED)
list(APPEND _sc_sanitizer_compile_options
$<$<COMPILE_LANGUAGE:CXX>:-fno-omit-frame-pointer>
)
endif()
add_compile_options(${_sc_sanitizer_compile_options})
string(JOIN " " _sc_sanitizer_link_flags ${_sc_sanitizer_link_options})
foreach(_sc_link_type EXE SHARED MODULE)
set(
CMAKE_${_sc_link_type}_LINKER_FLAGS
"${CMAKE_${_sc_link_type}_LINKER_FLAGS} ${_sc_sanitizer_link_flags}"
)
endforeach()
endif()
include(${SC_CMAKE_DIR}/SC_Regenerate.cmake)
if(NOT DEFINED SC_SDAI_ADDITIONAL_EXES_SRCS)
set(SC_SDAI_ADDITIONAL_EXES_SRCS "" CACHE STRING "Source files for additional executables to be linked with SDAI libs")
endif(NOT DEFINED SC_SDAI_ADDITIONAL_EXES_SRCS)
if(NOT "${SC_BUILD_EXPRESS_ONLY}" AND NOT DEFINED SC_BUILD_SCHEMAS)
if(NOT DEFINED SC_BUILD_SCHEMAS)
list(APPEND CONFIG_END_MESSAGES
"** Note: CMake variable SC_BUILD_SCHEMAS was not set - defaults to building ALL schemas")
# this makes SC_BUILD_SCHEMAS show up in cmake-gui
set(SC_BUILD_SCHEMAS "ALL" CACHE STRING "Semicolon-separated list of paths to EXPRESS schemas to be built")
endif()
"** CMake variable SC_BUILD_SCHEMAS was not set. Defaults to building ALL schemas, which will take a"
" while; see http://stepcode.org/mw/index.php?title=STEPcode_CMake_variables#SC_BUILD_SCHEMAS")
#this makes SC_BUILD_SCHEMAS show up in cmake-gui
set(SC_BUILD_SCHEMAS "ALL" CACHE string "Semicolon-separated list of paths to EXPRESS schemas to be built")
endif(NOT DEFINED SC_BUILD_SCHEMAS)
if(NOT SC_IS_SUBBUILD)
list(APPEND CONFIG_END_MESSAGES
@@ -290,14 +99,23 @@ 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 and sc_version_string.h
include(${SC_CMAKE_DIR}/SC_Config_Headers.cmake)
################
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)
if(MSVC)
# Disable warning for preferred usage of secure functions (example strcpy should be strcpy_s, ...)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
endif()
if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
else()
add_definitions(-pedantic -W -Wall -Wundef -Wfloat-equal -Wshadow -Winline -Wno-long-long)
if(HAVE_NULLPTR)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif(HAVE_NULLPTR)
endif()
include_directories(
@@ -305,6 +123,8 @@ include_directories(
${SC_BINARY_DIR}/include
)
add_subdirectory(src/auxlib)
add_subdirectory(src/base)
add_subdirectory(src/express)
add_subdirectory(src/exppp)
add_subdirectory(src/exp2cxx)
@@ -321,19 +141,13 @@ if(SC_ENABLE_TESTING)
endif(SC_ENABLE_TESTING)
add_subdirectory(doc)
if(NOT SC_IS_SUBBUILD)
#-----------------------------------------------------------------------------
# SC Packaging
# $make package
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "STEPcode")
set(CPACK_SET_DESTDIR "ON")
set(CPACK_PACKAGE_VERSION_MAJOR ${SC_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${SC_VERSION_MINOR})
set(CPACK_PACKAGE_NAME SC)
set(CPACK_PACKAGE_CONTACT "SC Developers <scl-dev@googlegroups.com>")
include(CPack)
endif(NOT SC_IS_SUBBUILD)
# 'make core' builds everything that isn't generated. for devs.
add_custom_target(core)
if($CACHE{SC_BUILD_SHARED_LIBS})
add_dependencies(core stepdai stepeditor exp2cxx check-express)
else()
add_dependencies(core stepdai-static stepeditor-static exp2cxx check-express)
endif()
# CONFIG_END_MESSAGES - list of messages to be printed after everything else is done.
# THIS MUST BE LAST to ensure that they are visible to the user without scrolling.
@@ -347,3 +161,4 @@ endforeach(_msg ${CONFIG_END_MESSAGES})
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+1 -4
View File
@@ -11,12 +11,9 @@ 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.
- 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`.
* 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`.
## Coding Standards
+1 -1
View File
@@ -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:
https://github.com/BRL-CAD/brlcad/tree/158beae4556d94821938368951546384cba53107/src/other/ext/stepcode
http://brlcad.svn.sourceforge.net/viewvc/brlcad/brlcad/trunk/src/other/step/?view=log
Pre-BRL-CAD changes:
************************************************************************
+1 -7
View File
@@ -51,13 +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_EXP2CXX_API_VERSION=2
- opts in to compact descriptor-driven SELECTs and dependency-bounded
entity headers in the generated C++ API.
- clients include the entity headers they use (for example,
entity/SdaiProduct.h); schema.h no longer expands every entity class.
- version 1 remains the default for source compatibility.
-DCMAKE_BUILD_TYPE=Release
-DSC_BUILD_TYPE=Release
- this causes binaries to be built without debugging information
- without this, cmake defaults to a Debug build
+1 -4
View File
@@ -1,8 +1,5 @@
STEPcode -- http://github.com/stepcode/stepcode -- http://stepcode.org
************************************************************************
STEPcode
http://github.com/stepcode/stepcode
************************************************************************
Release 0.8 (December, 2014)
New since v0.7:
+5 -2
View File
@@ -1,7 +1,10 @@
![Build Status](https://github.com/stepcode/stepcode/actions/workflows/build.yml/badge.svg?branch=develop)
Travis-CI | AppVeyor CI
:-------------:|:---------------:
Linux, OSX (LLVM) | Windows (MSVC)
[![Build Status](https://travis-ci.org/stepcode/stepcode.svg?branch=master)](https://travis-ci.org/stepcode/stepcode) | [![Build status](https://ci.appveyor.com/api/projects/status/3fbr9t9gfa812oqu?svg=true)](https://ci.appveyor.com/project/mpictor/stepcode)
***********************************************************************
STEPcode v0.8 -- github.com/stepcode/stepcode
STEPcode v0.8 -- stepcode.org, github.com/stepcode/stepcode
* What is STEPcode? SC reads ISO10303-11 EXPRESS schemas and generates
C++ source code that can read and write Part 21 files conforming
+1
View File
@@ -0,0 +1 @@
0.8
+94 -115
View File
@@ -48,132 +48,111 @@ find_program(LEMON_EXECUTABLE lemon DOC "path to the lemon executable")
mark_as_advanced(LEMON_EXECUTABLE)
if (LEMON_EXECUTABLE)
if(NOT LEMON_TEMPLATE)
# look for the template, if we've not already been told where it is
if (DATA_DIR AND EXISTS "${DATA_DIR}/lemon/lempar.c")
find_file(LEMON_TEMPLATE lempar.c
PATHS "${DATA_DIR}/lemon/lempar.c"
NO_DEFAULT_PATH)
endif ()
# If the above did not succeed, check standard locations
get_filename_component(lemon_dir ${LEMON_EXECUTABLE} DIRECTORY)
find_file(LEMON_TEMPLATE lempar.c
PATHS "${lemon_dir}" "/usr/share/lemon"
NO_DEFAULT_PATH)
find_file(LEMON_TEMPLATE lempar.c
PATHS "${lemon_dir}" "/usr/share/lemon"
NO_DEFAULT_PATH)
mark_as_advanced(LEMON_TEMPLATE)
endif()
if(NOT LEMON_TEMPLATE)
message(SEND_ERROR "failed to find lemon template (lempar.c)")
endif()
# We need a template to be able to use lemon correctly
if(NOT LEMON_TEMPLATE)
message(FATAL_ERROR "Failed to find lemon template file (lempar.c) - need to set LEMON_TEMPLATE")
endif()
# Define the macro
# LEMON_TARGET(<Name> <LemonInput> <LemonSource> <LemonHeader>
# [<ArgString>])
# which will create a custom rule to generate a parser. <LemonInput> is
# the path to a lemon file. <LemonSource> is the desired name for the
# generated source file. <LemonHeader> is the desired name for the
# generated header which contains the token list. Anything in the optional
# <ArgString> parameter is appended to the lemon command line.
#
# ====================================================================
# Example:
#
# find_package(LEMON)
# LEMON_TARGET(MyParser parser.y parser.c parser.h)
# add_executable(Foo main.cpp ${LEMON_MyParser_OUTPUTS})
# ====================================================================
# Define the function
# LEMON_TARGET(<Name> <LemonInput> <LemonSource> <LemonHeader>
# [<ArgString>])
# which will create a custom rule to generate a parser. <LemonInput> is
# the path to a lemon file. <LemonSource> is the desired name for the
# generated source file. <LemonHeader> is the desired name for the
# generated header which contains the token list. Anything in the optional
# <ArgString> parameter is appended to the lemon command line.
#
# ====================================================================
# Example:
#
# find_package(LEMON)
# LEMON_TARGET(MyParser parser.y parser.c parser.h)
# add_executable(Foo main.cpp ${LEMON_MyParser_OUTPUTS})
# ====================================================================
include(CMakeParseArguments)
include(CMakeParseArguments)
if(NOT COMMAND LEMON_TARGET)
macro(LEMON_TARGET Name LemonInput LemonOutput)
set(LT_ARGS DEFINES_FILE COMPILE_FLAGS)
CMAKE_PARSE_ARGUMENTS(LEMON_TARGET_ARG "" "${LT_ARGS}" "" ${ARGN})
if(NOT COMMAND LEMON_TARGET)
function(LEMON_TARGET Name LemonInput LemonOutput)
set(LT_ARGS DEFINES_FILE COMPILE_FLAGS)
cmake_parse_arguments(LEMON_TARGET_ARG "" "${LT_ARGS}" "" ${ARGN})
if(NOT "${LEMON_TARGET_ARG_COMPILE_FLAGS}" STREQUAL "")
set(LEMON_EXECUTABLE_opts "${LEMON_TARGET_ARG_COMPILE_FLAGS}")
separate_arguments(LEMON_EXECUTABLE_opts)
else()
set(LEMON_EXECUTABLE_opts "")
endif()
if(NOT "${LEMON_TARGET_ARG_COMPILE_FLAGS}" STREQUAL "")
set(LEMON_EXECUTABLE_opts "${LEMON_TARGET_ARG_COMPILE_FLAGS}")
separate_arguments(LEMON_EXECUTABLE_opts)
else()
set(LEMON_EXECUTABLE_opts "")
endif()
# check for LemonOutput
get_filename_component(_basename ${LemonOutput} NAME_WE)
get_filename_component(_out_src_file ${LemonOutput} NAME)
get_filename_component(_out_dir ${LemonOutput} PATH)
if(NOT "${_out_dir}" STREQUAL "")
message(WARNING "Full path specified for LemonOutput - should be filename only")
endif()
# set report file
set(_out_rpt_file "${_basename}.out")
# check for DEFINES_FILE
if ("${LEMON_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
set(_out_hdr_file "${_basename}.h")
else()
get_filename_component(_out_dir ${LEMON_TARGET_ARG_DEFINES_FILE} PATH)
get_filename_component(_out_hdr_file ${LEMON_TARGET_ARG_DEFINES_FILE} NAME)
if(NOT "${_out_dir}" STREQUAL "")
message(WARNING "Full path specified for DEFINES_FILE - should be filename only")
endif()
endif()
# input file
get_filename_component(_in_y_path ${LemonInput} ABSOLUTE)
get_filename_component(_in_y_file ${LemonInput} NAME)
# check for LemonOutput
get_filename_component(_basename ${LemonOutput} NAME_WE)
get_filename_component(_out_src_file ${LemonOutput} NAME)
get_filename_component(_out_dir ${LemonOutput} PATH)
if(NOT "${_out_dir}" STREQUAL "")
message(WARNING "Full path specified for LemonOutput - should be filename only")
endif()
# TODO: is this really necessary?
add_custom_command(
OUTPUT ${_in_y_file}
COMMAND ${CMAKE_COMMAND} -E copy ${_in_y_path} ${CMAKE_CURRENT_BINARY_DIR}
)
# execute lemon
add_custom_command(
OUTPUT ${_out_src_file}
COMMAND ${LEMON_EXECUTABLE} -T${LEMON_TEMPLATE} ${LEMON_EXECUTABLE_opts} ${_in_y_file}
DEPENDS ${_in_y_file}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "[LEMON][${Name}] Building parser with ${LEMON_EXECUTABLE}"
)
# rename the header
add_custom_command(
OUTPUT ${_out_hdr_file}
COMMAND ${CMAKE_COMMAND} ARGS -E rename ${_basename}.h ${_out_hdr_file}
DEPENDS ${_out_src_file}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
# set the return values
# TODO: for generated sources even headers should be target dependencies
set(LEMON_${Name}_DEFINED TRUE)
set(LEMON_${Name}_OUTPUT_HEADER "${CMAKE_CURRENT_BINARY_DIR}/${_out_hdr_file}")
set(LEMON_${Name}_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(LEMON_${Name}_OUTPUTS "${_out_src_file}")
# set report file
set(_out_rpt_file "${_basename}.out")
# make sure we clean up generated output and copied input
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${LEMON_${Name}_OUTPUTS}")
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/${_in_y_file}")
# check for DEFINES_FILE
if ("${LEMON_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
set(_out_hdr_file "${_basename}.h")
else()
get_filename_component(_out_dir ${LEMON_TARGET_ARG_DEFINES_FILE} PATH)
get_filename_component(_out_hdr_file ${LEMON_TARGET_ARG_DEFINES_FILE} NAME)
if(NOT "${_out_dir}" STREQUAL "")
message(WARNING "Full path specified for DEFINES_FILE - should be filename only")
endif()
endif()
endmacro(LEMON_TARGET)
endif(NOT COMMAND LEMON_TARGET)
# input file
get_filename_component(_in_y_path ${LemonInput} ABSOLUTE)
get_filename_component(_in_y_file ${LemonInput} NAME)
# Stage the source file in the binary directory for lemon. We need to make
# sure it's fully copied, so use a sentinel guard
add_custom_command(
OUTPUT ${_in_y_file}
COMMAND ${CMAKE_COMMAND} -E copy ${_in_y_path} ${CMAKE_CURRENT_BINARY_DIR}
)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_in_y_file}.sentinel
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${_in_y_file}.sentinel
DEPENDS ${_in_y_file}
)
add_custom_target(${Name}_input_cpy DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${_in_y_file}.sentinel)
# execute lemon
add_custom_command(
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}
COMMENT "[LEMON][${Name}] Building parser with ${LEMON_EXECUTABLE}"
)
# rename the header
add_custom_command(
OUTPUT ${_out_hdr_file}
COMMAND ${CMAKE_COMMAND} ARGS -E rename ${_basename}.h ${_out_hdr_file}
DEPENDS ${_out_src_file} ${_basename}.h
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
# set the return values
# TODO: for generated sources even headers should be target dependencies
set(LEMON_${Name}_DEFINED TRUE PARENT_SCOPE)
set(LEMON_${Name}_OUTPUT_HEADER "${CMAKE_CURRENT_BINARY_DIR}/${_out_hdr_file}" PARENT_SCOPE)
set(LEMON_${Name}_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}" PARENT_SCOPE)
set(LEMON_${Name}_OUTPUTS "${_out_src_file}" PARENT_SCOPE)
# TODO - remove once perplex goes away...
add_custom_target(${Name} DEPENDS ${_out_hdr_file})
# make sure we clean up generated output and copied input
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${_out_src_file}")
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/${_in_y_file}")
endfunction(LEMON_TARGET)
endif(NOT COMMAND LEMON_TARGET)
endif(LEMON_EXECUTABLE)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LEMON REQUIRED_VARS LEMON_EXECUTABLE LEMON_TEMPLATE)
+2 -10
View File
@@ -227,14 +227,6 @@ if(NOT COMMAND PERPLEX_TARGET)
set(PERPLEX_${Name}_SRC ${${PVAR_PREFIX}_OUT_SRC_FILE})
set(PERPLEX_${Name}_HDR ${${PVAR_PREFIX}_OUT_HDR_FILE})
set(PERPLEX_${Name}_INCLUDE_DIR ${${PVAR_PREFIX}_WORKING_DIR})
add_custom_command(
OUTPUT ${${PVAR_PREFIX}_WORKING_DIR}/${Name}.sentinel
COMMAND ${CMAKE_COMMAND} -E touch ${${PVAR_PREFIX}_WORKING_DIR}/${Name}.sentinel
DEPENDS ${${PVAR_PREFIX}_OUT_SRC_FILE} ${${PVAR_PREFIX}_OUT_HDR_FILE}
)
add_custom_target(${Name} DEPENDS ${${PVAR_PREFIX}_WORKING_DIR}/${Name}.sentinel)
endmacro(PERPLEX_TARGET)
endif(NOT COMMAND PERPLEX_TARGET)
@@ -248,12 +240,12 @@ if(NOT COMMAND ADD_PERPLEX_LEMON_DEPENDENCY)
message(SEND_ERROR "PERPLEX target `${PERPLEXTarget}' does not exists.")
endif()
if(NOT TARGET ${LemonTarget})
if(NOT LEMON_${LemonTarget}_HDR)
message(SEND_ERROR "Lemon target `${LemonTarget}' does not exists.")
endif()
set_source_files_properties(${PERPLEX_${PERPLEXTarget}_SRC}
PROPERTIES OBJECT_DEPENDS ${LEMON_${LemonTarget}_OUTPUT_HEADER})
PROPERTIES OBJECT_DEPENDS ${LEMON_${LemonTarget}_HDR})
endmacro(ADD_PERPLEX_LEMON_DEPENDENCY)
endif(NOT COMMAND ADD_PERPLEX_LEMON_DEPENDENCY)
+138 -138
View File
@@ -8,161 +8,161 @@ mark_as_advanced(RE2C_EXECUTABLE)
if(RE2C_EXECUTABLE)
execute_process(COMMAND ${RE2C_EXECUTABLE} -v
OUTPUT_VARIABLE RE2C_version_output
ERROR_VARIABLE RE2C_version_error
RESULT_VARIABLE RE2C_version_result
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT ${RE2C_version_result} EQUAL 0)
execute_process(COMMAND ${RE2C_EXECUTABLE} -v
OUTPUT_VARIABLE RE2C_version_output
ERROR_VARIABLE RE2C_version_error
RESULT_VARIABLE RE2C_version_result
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT ${RE2C_version_result} EQUAL 0)
message(SEND_ERROR
"Command \"${RE2C_EXECUTABLE} -v\" failed with output:\n${RE2C_version_output}\n${RE2C_version_error}")
else()
"Command \"${RE2C_EXECUTABLE} -v\" failed with output:\n${RE2C_version_output}\n${RE2C_version_error}")
else()
string(REGEX REPLACE "^re2c ([0-9]+[^ ]*)( .*)?$" "\\1" RE2C_VERSION "${RE2C_version_output}")
endif()
endif()
# Provide a macro to generate custom build rules:
# Provide a macro to generate custom build rules:
# RE2C_TARGET(Name RE2CInput RE2COutput [COMPILE_FLAGS <string>])
# which creates a custom command to generate the <RE2COutput> file from
# the <RE2CInput> file. If COMPILE_FLAGS option is specified, the next
# parameter is added to the re2c command line. Name is an alias used to
# get details of this custom command.
# RE2C_TARGET(Name RE2CInput RE2COutput [COMPILE_FLAGS <string>])
# which creates a custom command to generate the <RE2COutput> file from
# the <RE2CInput> file. If COMPILE_FLAGS option is specified, the next
# parameter is added to the re2c command line. Name is an alias used to
# get details of this custom command.
# This module also defines a macro:
# ADD_RE2C_LEMON_DEPENDENCY(RE2CTarget LemonTarget)
# which adds the required dependency between a scanner and a parser
# where <RE2CTarget> and <LemonTarget> are the first parameters of
# respectively RE2C_TARGET and LEMON_TARGET macros.
#
# ====================================================================
# Example:
#
# find_package(LEMON)
# find_package(RE2C)
#
# LEMON_TARGET(MyParser parser.y "${CMAKE_CURRENT_BINARY_DIR}/parser.cpp")
# RE2C_TARGET(MyScanner scanner.re "${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp")
# ADD_RE2C_LEMON_DEPENDENCY(MyScanner MyParser)
#
# include_directories("${CMAKE_CURRENT_BINARY_DIR}")
# add_executable(Foo
# Foo.cc
# ${LEMON_MyParser_OUTPUTS}
# ${RE2C_MyScanner_OUTPUTS}
# )
# ====================================================================
#
#=============================================================================
# Copyright (c) 2010-2016 United States Government as represented by
# the U.S. Army Research Laboratory.
# Copyright 2009 Kitware, Inc.
# Copyright 2006 Tristan Carel
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * The names of the authors may not 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.
#=============================================================================
# This module also defines a macro:
# ADD_RE2C_LEMON_DEPENDENCY(RE2CTarget LemonTarget)
# which adds the required dependency between a scanner and a parser
# where <RE2CTarget> and <LemonTarget> are the first parameters of
# respectively RE2C_TARGET and LEMON_TARGET macros.
#
# ====================================================================
# Example:
#
# find_package(LEMON)
# find_package(RE2C)
#
# LEMON_TARGET(MyParser parser.y "${CMAKE_CURRENT_BINARY_DIR}/parser.cpp")
# RE2C_TARGET(MyScanner scanner.re "${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp")
# ADD_RE2C_LEMON_DEPENDENCY(MyScanner MyParser)
#
# include_directories("${CMAKE_CURRENT_BINARY_DIR}")
# add_executable(Foo
# Foo.cc
# ${LEMON_MyParser_OUTPUTS}
# ${RE2C_MyScanner_OUTPUTS}
# )
# ====================================================================
#
#=============================================================================
# Copyright (c) 2010-2016 United States Government as represented by
# the U.S. Army Research Laboratory.
# Copyright 2009 Kitware, Inc.
# Copyright 2006 Tristan Carel
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * The names of the authors may not 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.
#=============================================================================
#============================================================
# RE2C_TARGET (public macro)
#============================================================
#
if(NOT COMMAND RE2C_TARGET)
function(RE2C_TARGET Name RE2CInput RE2COutput)
set(_re2c_args COMPILE_FLAGS DEFINES_FILE)
cmake_parse_arguments(RE2C_TARGET_ARG "" "${_re2c_args}" "" ${ARGN})
#============================================================
# RE2C_TARGET (public macro)
#============================================================
#
if(NOT COMMAND RE2C_TARGET)
macro(RE2C_TARGET Name RE2CInput RE2COutput)
set(_re2c_args COMPILE_FLAGS DEFINES_FILE)
cmake_parse_arguments(RE2C_TARGET_ARG "" "${_re2c_args}" "" ${ARGN})
if(NOT "${RE2C_TARGET_ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
message(SEND_ERROR "RE2C_TARGET(<Name> <RE2CInput> <RE2COutput>
[COMPILE_FLAGS <string>]
[DEFINES_FILE <string>])")
else()
if(NOT "${RE2C_TARGET_ARG_COMPILE_FLAGS}" STREQUAL "")
set(RE2C_EXECUTABLE_opts "${RE2C_TARGET_ARG_COMPILE_FLAGS}")
separate_arguments(RE2C_EXECUTABLE_opts)
else()
set(RE2C_EXECUTABLE_opts "")
endif()
if(NOT "${RE2C_TARGET_ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
message(SEND_ERROR "RE2C_TARGET(<Name> <RE2CInput> <RE2COutput>
[COMPILE_FLAGS <string>]
[DEFINES_FILE <string>])")
else()
if(NOT "${RE2C_TARGET_ARG_COMPILE_FLAGS}" STREQUAL "")
set(RE2C_EXECUTABLE_opts "${RE2C_TARGET_ARG_COMPILE_FLAGS}")
separate_arguments(RE2C_EXECUTABLE_opts)
else()
set(RE2C_EXECUTABLE_opts "")
endif()
if(NOT "${RE2C_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
list(APPEND RE2C_EXECUTABLE_opts -t ${RE2C_TARGET_ARG_DEFINES_FILE})
endif()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${RE2COutput}
COMMAND ${RE2C_EXECUTABLE}
ARGS ${RE2C_EXECUTABLE_opts} -o ${RE2COutput} ${CMAKE_CURRENT_SOURCE_DIR}/${RE2CInput}
DEPENDS ${RE2CInput}
COMMENT "[RE2C][${Name}] Building scanner with ${RE2C_EXECUTABLE}"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
if(NOT "${RE2C_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
list(APPEND RE2C_EXECUTABLE_opts -t ${RE2C_TARGET_ARG_DEFINES_FILE})
endif()
# TODO: check, for generated sources headers should be included in outputs
set(RE2C_${Name}_DEFINED TRUE)
set(RE2C_${Name}_OUTPUTS ${RE2COutput})
if("${RE2C_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
set(RE2C_${Name}_OUTPUT_HEADER "")
else()
set(RE2C_${Name}_OUTPUT_HEADER "${RE2C_TARGET_ARG_DEFINES_FILE}")
endif()
set(RE2C_${Name}_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
endif()
endmacro(RE2C_TARGET)
endif(NOT COMMAND RE2C_TARGET)
#============================================================
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${RE2COutput}
COMMAND ${RE2C_EXECUTABLE}
ARGS ${RE2C_EXECUTABLE_opts} -o ${RE2COutput} ${CMAKE_CURRENT_SOURCE_DIR}/${RE2CInput}
DEPENDS ${RE2CInput}
COMMENT "[RE2C][${Name}] Building scanner with ${RE2C_EXECUTABLE}"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
#============================================================
# ADD_RE2C_LEMON_DEPENDENCY (public macro)
#============================================================
#
if(NOT COMMAND ADD_RE2C_LEMON_DEPENDENCY)
macro(ADD_RE2C_LEMON_DEPENDENCY RE2CTarget LemonTarget)
# TODO: check, for generated sources headers should be included in outputs
set(RE2C_${Name}_DEFINED TRUE PARENT_SCOPE)
set(RE2C_${Name}_OUTPUTS ${RE2COutput} PARENT_SCOPE)
if("${RE2C_TARGET_ARG_DEFINES_FILE}" STREQUAL "")
set(RE2C_${Name}_OUTPUT_HEADER "" PARENT_SCOPE)
else()
set(RE2C_${Name}_OUTPUT_HEADER "${RE2C_TARGET_ARG_DEFINES_FILE}" PARENT_SCOPE)
endif()
set(RE2C_${Name}_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}" PARENT_SCOPE)
endif()
if(NOT RE2C_${RE2CTarget}_OUTPUTS)
message(SEND_ERROR "RE2C target `${RE2CTarget}' does not exists.")
endif()
endfunction(RE2C_TARGET)
endif(NOT COMMAND RE2C_TARGET)
#============================================================
if(NOT LEMON_${LemonTarget}_OUTPUT_HEADER)
message(SEND_ERROR "Lemon target `${LemonTarget}' does not exists.")
endif()
#============================================================
# ADD_RE2C_LEMON_DEPENDENCY (public macro)
#============================================================
#
if(NOT COMMAND ADD_RE2C_LEMON_DEPENDENCY)
function(ADD_RE2C_LEMON_DEPENDENCY RE2CTarget LemonTarget)
if(NOT RE2C_${RE2CTarget}_OUTPUTS)
message(SEND_ERROR "RE2C target `${RE2CTarget}' does not exists.")
endif()
if(NOT LEMON_${LemonTarget}_OUTPUT_HEADER)
message(SEND_ERROR "Lemon target `${LemonTarget}' does not exists.")
endif()
set_source_files_properties(${RE2C_${RE2CTarget}_OUTPUTS}
PROPERTIES OBJECT_DEPENDS ${LEMON_${LemonTarget}_OUTPUT_HEADER})
endfunction(ADD_RE2C_LEMON_DEPENDENCY)
endif(NOT COMMAND ADD_RE2C_LEMON_DEPENDENCY)
#============================================================
set_source_files_properties(${RE2C_${RE2CTarget}_OUTPUTS}
PROPERTIES OBJECT_DEPENDS ${LEMON_${LemonTarget}_OUTPUT_HEADER})
endmacro(ADD_RE2C_LEMON_DEPENDENCY)
endif(NOT COMMAND ADD_RE2C_LEMON_DEPENDENCY)
#============================================================
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(RE2C REQUIRED_VARS RE2C_EXECUTABLE
VERSION_VAR RE2C_VERSION)
VERSION_VAR RE2C_VERSION)
# RE2C_Util.cmake ends here
+67
View File
@@ -0,0 +1,67 @@
# Utility routines for managing generated files with CMake
macro(MD5 filename md5sum)
file(READ "${filename}" RAW_MD5_FILE)
string(REGEX REPLACE "\r" "" STRIPPED_MD5_FILE "${RAW_MD5_FILE}")
string(MD5 ${md5sum} "${STRIPPED_MD5_FILE}")
endmacro(MD5)
macro(FILEVAR filename var)
string(REGEX REPLACE "[^a-zA-Z0-9]" "_" ${var} ${filename})
endmacro(FILEVAR)
macro(VERIFY_FILES filelist warn resultvar)
set(${resultvar} 1)
foreach(fileitem ${filelist})
# Deal with absolute and relative paths a bit differently
get_filename_component(ITEM_ABS_PATH "${fileitem}" ABSOLUTE)
if("${fileitem}" STREQUAL "${ITEM_ABS_PATH}")
set(filefullname "${fileitem}")
else("${fileitem}" STREQUAL "${ITEM_ABS_PATH}")
set(filefullname "${CURRENT_SOURCE_DIR}/${fileitem}")
endif("${fileitem}" STREQUAL "${ITEM_ABS_PATH}")
get_filename_component(filename "${fileitem}" NAME)
# Got filename components sorted - proceed
if(NOT EXISTS ${filefullname})
message(FATAL_ERROR "Attempted to verify non-existant file ${filefullname}")
endif(NOT EXISTS ${filefullname})
FILEVAR(${filename} filevar)
if(NOT baseline_${filevar}_md5)
message(FATAL_ERROR "No baseline MD5 available for ${filename} - baseline_${filevar}_md5 is not defined")
endif(NOT baseline_${filevar}_md5)
MD5(${filefullname} ${filevar}_md5)
if(NOT "${${filevar}_md5}" STREQUAL "${baseline_${filevar}_md5}")
if("${warn}" STREQUAL "1")
message("\n${filename} differs from baseline: baseline md5 hash is ${baseline_${filevar}_md5} and current hash is ${${filevar}_md5}\n")
endif("${warn}" STREQUAL "1")
set(${resultvar} 0)
endif(NOT "${${filevar}_md5}" STREQUAL "${baseline_${filevar}_md5}")
endforeach(fileitem ${filelist})
endmacro(VERIFY_FILES filelist resultvar)
macro(WRITE_MD5_SUMS filelist outfile)
foreach(fileitem ${filelist})
# Deal with absolute and relative paths a bit differently
get_filename_component(ITEM_ABS_PATH "${fileitem}" ABSOLUTE)
if("${fileitem}" STREQUAL "${ITEM_ABS_PATH}")
set(filefullname "${fileitem}")
else("${fileitem}" STREQUAL "${ITEM_ABS_PATH}")
set(filefullname "${CURRENT_SOURCE_DIR}/${fileitem}")
endif("${fileitem}" STREQUAL "${ITEM_ABS_PATH}")
get_filename_component(filename "${fileitem}" NAME)
# Got filename components sorted - proceed
if(NOT EXISTS ${filefullname})
message(FATAL_ERROR "Attempted to get MD5 sum of non-existant file ${filefullname}")
endif(NOT EXISTS ${filefullname})
FILEVAR(${filename} filevar)
MD5(${filefullname} ${filevar}_md5)
file(APPEND ${outfile} "set(baseline_${filevar}_md5 ${${filevar}_md5})\n")
endforeach(fileitem ${filelist})
endmacro(WRITE_MD5_SUMS)
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
-164
View File
@@ -1,164 +0,0 @@
# Copyright (c) 2010-2020 United States Government as represented by
# the U.S. Army Research Laboratory.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. 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.
#
# 3. The name of the author may not be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
#---------------------------------------------------------------------
# Define relative install locations. Don't set these if they have already
# been set by some other means (like a higher level CMakeLists.txt file
# including this one).
# The location in which to install BRL-CAD executables.
if(NOT BIN_DIR)
set(BIN_DIR bin)
endif(NOT BIN_DIR)
# Define a relative path that will "reset" a path back to
# the point before BIN_DIR was appended. This is primarily
# useful when working with generator expressions
unset(RBIN_DIR CACHE)
set(LBIN_DIR "${BIN_DIR}")
while (NOT "${LBIN_DIR}" STREQUAL "")
get_filename_component(LBDIR "${LBIN_DIR}" DIRECTORY)
set(LBIN_DIR "${LBDIR}")
if ("${RBIN_DIR}" STREQUAL "")
set(RBIN_DIR "..")
else ("${RBIN_DIR}" STREQUAL "")
set(RBIN_DIR "../${RBIN_DIR}")
endif ("${RBIN_DIR}" STREQUAL "")
endwhile (NOT "${LBIN_DIR}" STREQUAL "")
# The location in which to install BRL-CAD libraries.
if(NOT LIB_DIR)
set(LIB_DIR lib)
endif(NOT LIB_DIR)
if(NOT LIBEXEC_DIR)
set(LIBEXEC_DIR libexec)
endif(NOT LIBEXEC_DIR)
# The location in which to install BRL-CAD header files.
if(NOT INCLUDE_DIR)
set(INCLUDE_DIR include)
endif(NOT INCLUDE_DIR)
# The location in which to install BRL-CAD data files
if(NOT DATA_DIR)
set(DATA_DIR share)
endif(NOT DATA_DIR)
# The location in which to install BRL-CAD documentation files
if(NOT DOC_DIR)
set(DOC_DIR ${DATA_DIR}/doc)
endif(NOT DOC_DIR)
# The location in which to install BRL-CAD Manual pages
if(NOT MAN_DIR)
set(MAN_DIR ${DATA_DIR}/man)
endif(NOT MAN_DIR)
# Make sure no absolute paths have been supplied to these variables
set(INSTALL_DIRS BIN INCLUDE LIB LIBEXEC DATA MAN DOC)
foreach(instdir ${INSTALL_DIRS})
get_filename_component(instdir_full ${${instdir}_DIR} ABSOLUTE)
if("${${instdir}_DIR}" STREQUAL "${instdir_full}")
message(FATAL_ERROR "Error - absolute path supplied for ${instdir}_DIR. This path must be relative - e.g. \"bin\" instead of \"/usr/bin\"")
set(HAVE_INSTALL_DIR_FULL_PATH 1)
endif("${${instdir}_DIR}" STREQUAL "${instdir_full}")
endforeach(instdir ${INSTALL_DIRS})
#---------------------------------------------------------------------
# Output directories - this is where built library and executable
# files will be placed after building but prior to install. The
# necessary variables change between single and multi configuration
# build systems, so it is necessary to handle both cases on a
# conditional basis.
if(NOT CMAKE_CONFIGURATION_TYPES)
# If we're not doing multi-configuration, just set the three main
# variables to the correct values.
if(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${${PROJECT_NAME}_BINARY_DIR}/${LIB_DIR} CACHE INTERNAL "Single output directory for building all libraries.")
endif(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
if(NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${${PROJECT_NAME}_BINARY_DIR}/${LIB_DIR} CACHE INTERNAL "Single output directory for building all archives.")
endif(NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
if(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${${PROJECT_NAME}_BINARY_DIR}/${BIN_DIR} CACHE INTERNAL "Single output directory for building all executables.")
endif(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
else(NOT CMAKE_CONFIGURATION_TYPES)
# Multi-configuration is more difficult. Not only do we need to
# properly set the output directories, but we also need to
# identify the "toplevel" directory for each configuration so
# we can place files, documentation, etc. in the correct
# relative positions. Because files may be placed by CMake
# without a build target to put them in their proper relative build
# directory position using these paths, we must fully qualify them
# without using CMAKE_CFG_INTDIR.
#
# We define directories that may not be quite "standard"
# for a particular build tool - for example, native VS2010 projects use
# another directory to denote CPU type being compiled for - but CMake only
# supports multi-configuration setups having multiple configurations,
# not multiple compilers.
#
# One additional wrinkle we must watch for here is the case where
# a multi-configuration setup uses "." for its internal directory -
# if that's the case, we need to just set the various config output
# directories to the same value.
set(CFG_ROOT ${${PROJECT_NAME}_BINARY_DIR})
foreach(CFG_TYPE ${CMAKE_CONFIGURATION_TYPES})
if(NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".")
set(CFG_ROOT ${${PROJECT_NAME}_BINARY_DIR}/${CFG_TYPE})
endif(NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".")
string(TOUPPER "${CFG_TYPE}" CFG_TYPE_UPPER)
if(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CFG_TYPE_UPPER})
set("CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CFG_TYPE_UPPER}" ${CFG_ROOT}/${LIB_DIR} CACHE INTERNAL "Single output directory for building ${CFG_TYPE} libraries.")
endif(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CFG_TYPE_UPPER})
if(NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CFG_TYPE_UPPER})
set("CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CFG_TYPE_UPPER}" ${CFG_ROOT}/${LIB_DIR} CACHE INTERNAL "Single output directory for building ${CFG_TYPE} archives.")
endif(NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CFG_TYPE_UPPER})
if(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CFG_TYPE_UPPER})
set("CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CFG_TYPE_UPPER}" ${CFG_ROOT}/${BIN_DIR} CACHE INTERNAL "Single output directory for building ${CFG_TYPE} executables.")
endif(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CFG_TYPE_UPPER})
if(NOT DEFINED CMAKE_BINARY_DIR_${CFG_TYPE_UPPER})
set("CMAKE_BINARY_DIR_${CFG_TYPE_UPPER}" ${CFG_ROOT} CACHE INTERNAL "Toplevel binary dir for ${CFG_TYPE} building.")
endif(NOT DEFINED CMAKE_BINARY_DIR_${CFG_TYPE_UPPER})
if(NOT DEFINED ${PROJECT_NAME}_BINARY_DIR_${CFG_TYPE_UPPER})
set("${PROJECT_NAME}_BINARY_DIR_${CFG_TYPE_UPPER}" ${CFG_ROOT} CACHE INTERNAL "Toplevel binary dir for ${CFG_TYPE} building.")
endif(NOT DEFINED ${PROJECT_NAME}_BINARY_DIR_${CFG_TYPE_UPPER})
endforeach()
endif(NOT CMAKE_CONFIGURATION_TYPES)
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+176
View File
@@ -0,0 +1,176 @@
# BIN and LIB directories
if(NOT DEFINED BIN_DIR)
set(BIN_DIR bin)
endif(NOT DEFINED BIN_DIR)
if(NOT DEFINED LIB_DIR)
set(LIB_DIR lib)
endif(NOT DEFINED LIB_DIR)
# testing and compilation options, build output dirs, install dirs, etc
# included by root CMakeLists
if(NOT DEFINED INCLUDE_INSTALL_DIR)
set(INCLUDE_INSTALL_DIR include)
endif(NOT DEFINED INCLUDE_INSTALL_DIR)
if(NOT DEFINED LIB_INSTALL_DIR)
set(LIB_INSTALL_DIR lib)
endif(NOT DEFINED LIB_INSTALL_DIR)
if(NOT DEFINED BIN_INSTALL_DIR)
set(BIN_INSTALL_DIR bin)
endif(NOT DEFINED BIN_INSTALL_DIR)
if(NOT DEFINED SC_BUILD_TYPE)
set(SC_BUILD_TYPE "Debug" CACHE STRING "Build type") # By default set debug build
endif(NOT DEFINED SC_BUILD_TYPE)
if(NOT SC_IS_SUBBUILD)
set(CMAKE_BUILD_TYPE ${SC_BUILD_TYPE} CACHE INTERNAL "Build type, immutable" FORCE)
else(NOT SC_IS_SUBBUILD)
set(CMAKE_BUILD_TYPE ${SC_BUILD_TYPE})
endif(NOT SC_IS_SUBBUILD)
# Define helper macro OPTION_WITH_DEFAULT
macro(OPTION_WITH_DEFAULT OPTION_NAME OPTION_STRING OPTION_DEFAULT)
if(NOT DEFINED ${OPTION_NAME})
set(${OPTION_NAME} ${OPTION_DEFAULT})
endif(NOT DEFINED ${OPTION_NAME})
option(${OPTION_NAME} "${OPTION_STRING}" ${${OPTION_NAME}})
endmacro(OPTION_WITH_DEFAULT OPTION_NAME OPTION_STRING OPTION_DEFAULT)
# build shared libs by default
OPTION_WITH_DEFAULT(SC_BUILD_SHARED_LIBS "Build shared libs" ON)
# don't build static libs by default
OPTION_WITH_DEFAULT(SC_BUILD_STATIC_LIBS "Build static libs" OFF)
OPTION_WITH_DEFAULT(SC_PYTHON_GENERATOR "Compile exp2python" ON)
OPTION_WITH_DEFAULT(SC_CPP_GENERATOR "Compile exp2cxx" ON)
OPTION_WITH_DEFAULT(SC_MEMMGR_ENABLE_CHECKS "Enable sc_memmgr's memory leak detection" OFF)
OPTION_WITH_DEFAULT(SC_TRACE_FPRINTF "Enable extra comments in generated code so the code's source in exp2cxx may be located" OFF)
# Should we use C++11?
OPTION_WITH_DEFAULT(SC_ENABLE_CXX11 "Build with C++ 11 features" ON)
# Get version from git
OPTION_WITH_DEFAULT(SC_GIT_VERSION "Build using version from git" ON)
option(SC_BUILD_EXPRESS_ONLY "Only build express parser." OFF)
mark_as_advanced(SC_BUILD_EXPRESS_ONLY)
option(DEBUGGING_GENERATED_SOURCES "disable md5 verification of generated sources" OFF)
mark_as_advanced(DEBUGGING_GENERATED_SOURCES)
#---------------------------------------------------------------------
# Coverage option
OPTION_WITH_DEFAULT(SC_ENABLE_COVERAGE "Enable code coverage test" OFF)
if(SC_ENABLE_COVERAGE)
set(SC_ENABLE_TESTING ON CACHE BOOL "Testing enabled by coverage option" FORCE)
# build static libs, better coverage report
set(SC_BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libs" FORCE)
set(SC_BUILD_STATIC_LIBS ON CACHE BOOL "Build static libs" FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -fprofile-arcs -ftest-coverage" CACHE STRING "Extra compile flags required by code coverage" FORCE)
set(CMAKE_C_FLAGS_DEBUG "-O0 -g -fprofile-arcs -ftest-coverage" CACHE STRING "Extra compile flags required by code coverage" FORCE)
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "-fprofile-arcs -ftest-coverage" CACHE STRING "Extra linker flags required by code coverage" FORCE)
set(SC_BUILD_TYPE "Debug" CACHE STRING "Build type required by testing framework" FORCE)
set(SC_PYTHON_GENERATOR OFF) #won't build with static libs
endif(SC_ENABLE_COVERAGE)
#---------------------------------------------------------------------
# Testing option
OPTION_WITH_DEFAULT(SC_ENABLE_TESTING "Enable unittesting framework" OFF)
if(SC_ENABLE_TESTING)
if(NOT ${SC_BUILD_EXPRESS_ONLY} AND NOT DEFINED SC_BUILD_SCHEMAS)
set(SC_BUILD_SCHEMAS "ALL") #test all schemas, unless otherwise specified
endif()
include(CTest)
endif(SC_ENABLE_TESTING)
#---------------------------------------------------------------------
# Executable install option
OPTION_WITH_DEFAULT(SC_SKIP_EXEC_INSTALL "Skip installing executables" OFF)
if(SC_SKIP_EXEC_INSTALL)
set(SC_EXEC_NOINSTALL "NO_INSTALL")
endif(SC_SKIP_EXEC_INSTALL)
#---------------------------------------------------------------------
# The following logic is what allows binaries to run successfully in
# the build directory AND install directory. Thanks to plplot for
# identifying the necessity of setting CMAKE_INSTALL_NAME_DIR on OSX.
# Documentation of these options is available at
# http://www.cmake.org/Wiki/CMake_RPATH_handling
# use, i.e. don't skip the full RPATH for the build tree
set(CMAKE_SKIP_BUILD_RPATH FALSE)
# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
# the RPATH/INSTALL_NAME_DIR to be used when installing
if (NOT APPLE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib:\$ORIGIN/../lib")
endif(NOT APPLE)
# On OSX, we need to set INSTALL_NAME_DIR instead of RPATH
# http://www.cmake.org/cmake/help/cmake-2-8-docs.html#variable:CMAKE_INSTALL_NAME_DIR
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
# add the automatically determined parts of the RPATH which point to
# directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# When this is a subbuild, assume that the parent project controls all of the following
#======================================================================================
if(NOT SC_IS_SUBBUILD)
# Output directories. In a separate file so it can be used by the schema scanner CMake as well.
include(${SC_CMAKE_DIR}/SC_Outdirs.cmake)
#-----------------------------------------------------------------------------
# Configure install locations. Only do this if CMAKE_INSTALL_PREFIX hasn't
# been set already, to try and allow parent builds (if any) some control.
#
# Need a good Debug location for Windows.
if(NOT WIN32)
if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
set(SC_INSTALL_PREFIX "${SC_SOURCE_DIR}/../sc-install")
else()
set(SC_INSTALL_PREFIX "/usr/local")
endif()
endif(NOT WIN32)
set(SC_INSTALL_PREFIX ${SC_INSTALL_PREFIX} CACHE
PATH "Install prefix prepended to target to create install location")
set(CMAKE_INSTALL_PREFIX ${SC_INSTALL_PREFIX} CACHE INTERNAL "Prefix prepended to install directories if target destination is not absolute, immutable" FORCE)
#-----------------------------------------------------------------------------
# SC Packaging
# $make package
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "STEPcode")
set(CPACK_SET_DESTDIR "ON")
set(CPACK_PACKAGE_VERSION_MAJOR ${SC_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${SC_VERSION_MINOR})
set(CPACK_PACKAGE_NAME SC)
set(CPACK_PACKAGE_CONTACT "SC Developers <scl-dev@googlegroups.com>")
include(CPack)
#-----------------------------------------------------------------------------
# Uninstall target
# From http://www.cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif(NOT SC_IS_SUBBUILD)
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+18 -51
View File
@@ -27,29 +27,20 @@ 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)
if(BUILD_SHARED_LIBS)
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)
elseif(BUILD_STATIC_LIBS)
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}-static stepeditor-static stepcore-static stepdai-static steputils-static TESTABLE)
endif()
SC_ADDEXEC(p21read_${PROJECT_NAME} SOURCES "${RELATIVE_PATH_COMPONENT}/src/test/p21read/p21read.cc" LINK_LIBRARIES ${PROJECT_NAME} stepdai stepcore stepeditor steputils base TESTABLE)
#add_dependencies(p21read_${PROJECT_NAME} version_string)
if(NOT WIN32)
if(BUILD_SHARED_LIBS)
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)
elseif(BUILD_STATIC_LIBS)
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}-static steplazyfile-static stepeditor-static stepcore-static stepdai-static steputils-static TESTABLE)
endif()
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)
#add_dependencies(lazy_${PROJECT_NAME} version_string)
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)
if(BUILD_SHARED_LIBS)
SC_ADDEXEC(${name}_${PROJECT_NAME} SOURCES ${src} LINK_LIBRARIES ${PROJECT_NAME} stepdai stepcore stepeditor steputils TESTABLE)
elseif(BUILD_STATIC_LIBS)
SC_ADDEXEC(${name}_${PROJECT_NAME} SOURCES ${src} LINK_LIBRARIES ${PROJECT_NAME}-static stepcore-static stepdai-static stepeditor-static steputils-static TESTABLE)
SC_ADDEXEC(${name}_${PROJECT_NAME} SOURCES ${src} LINK_LIBRARIES ${PROJECT_NAME} stepdai stepcore stepeditor steputils base TESTABLE)
add_dependencies(${name}_${PROJECT_NAME} version_string)
#set_target_properties(${name}_${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${${PROJECT_NAME}_COMPILE_FLAGS} -I${path}")
endif()
endforeach(src ${SC_SDAI_ADDITIONAL_EXES_SRCS})
ENDMACRO(SCHEMA_EXES)
@@ -89,62 +80,37 @@ macro(SCHEMA_TARGETS expFile schemaName sourceFiles)
# schema scanner comes up with a short schema name for PROJECT() (which sets ${PROJECT_NAME})
message(STATUS "Will generate ${${PROJECT_NAME}_file_count} C++ files for ${PROJECT_NAME}.")
set(_schema_generated_files)
foreach(_schema_source ${sourceFiles})
list(APPEND _schema_generated_files "${CMAKE_CURRENT_SOURCE_DIR}/${_schema_source}")
endforeach()
add_custom_target(generate_cpp_${PROJECT_NAME} DEPENDS exp2cxx ${expFile} ${_schema_generated_files} SOURCES ${_schema_generated_files})
add_custom_target(generate_cpp_${PROJECT_NAME} DEPENDS exp2cxx ${expFile} ${sourceFiles} SOURCES ${sourceFiles})
# this calls a cmake script because it doesn't seem to be possible
# to divert stdout, stderr in cmake except via execute_process
add_custom_command(OUTPUT ${_schema_generated_files}
add_custom_command(OUTPUT ${sourceFiles}
COMMAND ${CMAKE_COMMAND} -DEXE=\"$<TARGET_FILE:exp2cxx>\" -DEXP=\"${expFile}\"
-DONESHOT=\"${SC_GENERATE_CXX_ONESHOT}\" -DSDIR=\"${CMAKE_CURRENT_LIST_DIR}\"
-DCHUNK_SIZE=\"${SC_EXP2CXX_CHUNK_SIZE}\"
-DAPI_VERSION=\"${SC_EXP2CXX_API_VERSION}\"
-DLATE_BOUND=\"${SC_EXP2CXX_LATE_BOUND}\"
-DCOMPAT_NAMES=\"${SC_EXP2CXX_COMPAT_NAMES}\"
-DMETADATA_PROFILE=\"${SC_EXP2CXX_METADATA}\"
-DGENERATOR_ENVIRONMENT=\"${SC_SCHEMA_GENERATOR_ENVIRONMENT}\"
-P ${SC_CMAKE_DIR}/SC_Run_exp2cxx.cmake
DEPENDS exp2cxx ${expFile}
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
COMMENT "[exp2cxx] Generating ${${PROJECT_NAME}_file_count} C++ files for ${PROJECT_NAME}."
)
set(_schema_include_dirs
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/cllazyfile
${SC_SOURCE_DIR}/src/cllazyfile/judy/src
${SC_SOURCE_DIR}/src/clutils ${SC_SOURCE_DIR}/src/clstepcore ${SC_SOURCE_DIR}/src/base
${SC_SOURCE_DIR}/src/base/judy/src
)
# Schema libraries should be installed by default
if(BUILD_SHARED_LIBS)
SC_ADDLIB(${PROJECT_NAME} SHARED SOURCES ${_schema_generated_files} LINK_LIBRARIES stepdai stepcore stepeditor steputils)
# if testing is enabled, "TESTABLE" sets property EXCLUDE_FROM_ALL and prevents installation
if($CACHE{SC_BUILD_SHARED_LIBS})
SC_ADDLIB(${PROJECT_NAME} SHARED SOURCES ${sourceFiles} LINK_LIBRARIES stepdai stepcore stepeditor steputils base TESTABLE)
add_dependencies(${PROJECT_NAME} generate_cpp_${PROJECT_NAME})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${_schema_include_dirs})
if(${PROJECT_NAME}_unity_build)
target_compile_definitions(${PROJECT_NAME} PRIVATE SC_SDAI_UNITY_BUILD)
endif()
if(WIN32)
target_compile_definitions("${PROJECT_NAME}" PRIVATE SC_SCHEMA_DLL_EXPORTS)
if(MSVC)
target_compile_options("${PROJECT_NAME}" PRIVATE "/bigobj")
endif()
endif()
# TODO - ideally we would avoid generating code that triggers this warning, but figuring out
# how to do so is a non-trivial exercise. In the meantime, suppress the (very verbose) warnings
# we get due to this issue so it doesn't mask other problems.
if(${CMAKE_C_COMPILER_ID} STREQUAL "GNU")
target_compile_options("${PROJECT_NAME}" PRIVATE "-Wno-ignored-qualifiers")
endif()
endif()
if(BUILD_STATIC_LIBS)
SC_ADDLIB(${PROJECT_NAME}-static STATIC SOURCES ${_schema_generated_files} LINK_LIBRARIES stepcore-static stepdai-static stepeditor-static steputils-static)
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)
add_dependencies(${PROJECT_NAME}-static generate_cpp_${PROJECT_NAME})
target_include_directories(${PROJECT_NAME}-static PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${_schema_include_dirs})
target_compile_definitions("${PROJECT_NAME}-static" PRIVATE SC_STATIC)
if(${PROJECT_NAME}_unity_build)
target_compile_definitions(${PROJECT_NAME}-static PRIVATE SC_SDAI_UNITY_BUILD)
endif()
target_compile_defines("${PROJECT_NAME}-static" PRIVATE SC_STATIC)
if(MSVC)
target_compile_options("${PROJECT_NAME}-static" PRIVATE "/bigobj")
endif()
@@ -164,3 +130,4 @@ endmacro(SCHEMA_TARGETS expFile schemaName sourceFiles)
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+51 -4
View File
@@ -1,4 +1,23 @@
# create config.h
# create sc_cf.h and sc_version_string.h
# Take the sc config file template as the starting point for
# sc_cf.h.in - scripts may need to append to the template, so
# it is read into memory initially.
set(CONFIG_H_FILE ${SC_BINARY_DIR}/include/sc_cf.h.in)
set_source_files_properties(${CONFIG_H_FILE} PROPERTIES GENERATED TRUE)
set(CMAKE_CURRENT_PROJECT SC)
define_property(GLOBAL PROPERTY SC_CONFIG_H_CONTENTS BRIEF_DOCS "config.h.in contents" FULL_DOCS "config.h.in contents for SC project")
if(NOT COMMAND CONFIG_H_APPEND)
macro(CONFIG_H_APPEND PROJECT_NAME NEW_CONTENTS)
if(PROJECT_NAME)
get_property(${PROJECT_NAME}_CONFIG_H_CONTENTS GLOBAL PROPERTY ${PROJECT_NAME}_CONFIG_H_CONTENTS)
set(${PROJECT_NAME}_CONFIG_H_FILE_CONTENTS "${${PROJECT_NAME}_CONFIG_H_CONTENTS}${NEW_CONTENTS}")
set_property(GLOBAL PROPERTY ${PROJECT_NAME}_CONFIG_H_CONTENTS "${${PROJECT_NAME}_CONFIG_H_FILE_CONTENTS}")
endif(PROJECT_NAME)
endmacro(CONFIG_H_APPEND NEW_CONTENTS)
endif(NOT COMMAND CONFIG_H_APPEND)
file(READ ${SC_SOURCE_DIR}/include/sc_cf_cmake.h.in CONFIG_H_FILE_CONTENTS)
CONFIG_H_APPEND(SC "${CONFIG_H_FILE_CONTENTS}")
include(CheckLibraryExists)
include(CheckIncludeFile)
@@ -77,9 +96,37 @@ int main() {return !(f() == f());}
cmake_pop_check_state()
endif(SC_ENABLE_CXX11)
# 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)
# Now that all the tests are done, configure the sc_cf.h file:
get_property(CONFIG_H_FILE_CONTENTS GLOBAL PROPERTY SC_CONFIG_H_CONTENTS)
file(WRITE ${CONFIG_H_FILE} "${CONFIG_H_FILE_CONTENTS}")
configure_file(${CONFIG_H_FILE} ${SC_BINARY_DIR}/${INCLUDE_INSTALL_DIR}/sc_cf.h)
# ------------------------
# create sc_version_string.h, http://stackoverflow.com/questions/3780667
# Using 'ver_string' instead of 'sc_version_string.h' is a trick to force the
# command to always execute when the custom target is built. It works because
# a file by that name never exists.
if(SC_GIT_VERSION)
configure_file(${SC_CMAKE_DIR}/sc_version_string.cmake ${SC_BINARY_DIR}/sc_version_string.cmake @ONLY)
add_custom_target(version_string ALL DEPENDS ver_string)
# creates sc_version_string.h using cmake script
add_custom_command(OUTPUT ver_string
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${SC_SOURCE_DIR} -DBINARY_DIR=${SC_BINARY_DIR} -P ${SC_BINARY_DIR}/sc_version_string.cmake
)
# sc_version_string.h is a generated file
else(SC_GIT_VERSION)
set(VER_HDR "
#ifndef SC_VERSION_STRING
#define SC_VERSION_STRING
static char sc_version[512] = {\"${SC_VERSION}\"};
#endif"
)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${INCLUDE_INSTALL_DIR}/sc_version_string.h "${VER_HDR}")
endif(SC_GIT_VERSION)
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${INCLUDE_INSTALL_DIR}/sc_version_string.h
PROPERTIES GENERATED TRUE
HEADER_FILE_ONLY TRUE )
# Local Variables:
# tab-width: 8
+2 -3
View File
@@ -29,9 +29,8 @@ endif()
if(NOT "${SC_GENERATE_LEXER_PARSER}" STREQUAL "OFF")
# NOTE: lemon doesn't have a stable versioning system (it's always 1)
find_package(LEMON ${_verbosity})
find_package(RE2C ${_verbosity})
find_package(PERPLEX ${_verbosity})
find_package(RE2C 1.0.3 ${_verbosity})
if(LEMON_FOUND AND RE2C_FOUND)
set(SC_GENERATE_LP_SOURCES 1)
message(".. Found re2c, and lemon - can regenerate lexer/parser if necessary")
+2 -17
View File
@@ -1,26 +1,10 @@
# if oneshot is true, don't run exp2cxx if source files exist. if schema.cc exists, assume others do
if(NOT DEFINED API_VERSION OR "${API_VERSION}" STREQUAL "")
set(API_VERSION 1)
endif()
if(NOT DEFINED METADATA_PROFILE OR "${METADATA_PROFILE}" STREQUAL "")
set(METADATA_PROFILE full)
endif()
if(ONESHOT AND EXISTS "${SDIR}/schema.cc")
message("WARNING: SC_GENERATE_CXX_ONESHOT is enabled. If generated code has been modified, it will NOT be rewritten!")
message("This is ONLY for debugging STEPcode internals!")
else()
set(_exp2cxx_mode_args)
if(LATE_BOUND)
list(APPEND _exp2cxx_mode_args --late-bound)
endif()
if(COMPAT_NAMES)
list(APPEND _exp2cxx_mode_args --compat-names)
endif()
list(APPEND _exp2cxx_mode_args --metadata ${METADATA_PROFILE})
execute_process(COMMAND ${CMAKE_COMMAND} -E env ${GENERATOR_ENVIRONMENT}
${EXE} -k ${CHUNK_SIZE} -V ${API_VERSION} ${_exp2cxx_mode_args} ${EXP}
execute_process(COMMAND ${EXE} ${EXP}
WORKING_DIRECTORY ${SDIR}
RESULT_VARIABLE _res
OUTPUT_FILE exp2cxx_stdout.txt
@@ -38,3 +22,4 @@ endif()
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+10 -26
View File
@@ -10,23 +10,15 @@ macro(SC_ADDEXEC execname)
add_executable(${execname} ${${_arg_prefix}_SOURCES})
if(BUILD_STATIC_LIBS)
target_compile_definitions(${execname} PRIVATE SC_STATIC)
endif()
if(DEFINED "${_arg_prefix}_LINK_LIBRARIES")
foreach(_lib ${${_arg_prefix}_LINK_LIBRARIES})
if($CACHE{SC_STATIC_UTILS})
get_property(_lib_type TARGET ${_lib} PROPERTY TYPE)
if(NOT _lib_type STREQUAL "STATIC_LIBRARY")
if(NOT $<TARGET_PROPERTY:${_lib},TYPE> STREQUAL "STATIC_LIBRARY")
message(SEND_ERROR "SC_ADDEXEC usage error - expected STATIC LINK_LIBRARIES targets (${_lib})")
endif()
endif()
# Executables consume their dependencies but do not publish an
# interface to downstream targets.
target_link_libraries(${execname} PRIVATE ${_lib})
target_link_libraries(${execname} ${_lib})
endforeach()
target_link_libraries(${execname} PRIVATE ${${_arg_prefix}_LINK_LIBRARIES})
endif()
if(NOT ${_arg_prefix}_NO_INSTALL AND NOT ${_arg_prefix}_TESTABLE)
@@ -45,7 +37,7 @@ endmacro()
macro(SC_ADDLIB _addlib_target)
set(_addlib_opts SHARED STATIC NO_INSTALL TESTABLE)
set(_addlib_multikw SOURCES LINK_LIBRARIES)
string(TOUPPER "SC_ADDLIB_${_addlib_target}_ARG" _arg_prefix)
string(TOUPPER "SC_ADDLIB_${libname}_ARG" _arg_prefix)
cmake_parse_arguments(${_arg_prefix} "${_addlib_opts}" "" "${_addlib_multikw}" ${ARGN})
if(NOT DEFINED ${_arg_prefix}_SOURCES)
@@ -54,11 +46,7 @@ macro(SC_ADDLIB _addlib_target)
if(${_arg_prefix}_SHARED)
add_library(${_addlib_target} SHARED ${${_arg_prefix}_SOURCES})
if(OPENBSD)
set_target_properties(${_addlib_target} PROPERTIES VERSION ${SC_VERSION_MAJOR}.${SC_VERSION_MINOR})
else(OPENBSD)
set_target_properties(${_addlib_target} PROPERTIES VERSION ${SC_VERSION} SOVERSION ${SC_VERSION_MAJOR})
endif(OPENBSD)
set_target_properties(${_addlib_target} PROPERTIES VERSION ${SC_ABI_VERSION} SOVERSION ${SC_ABI_SOVERSION})
if(APPLE)
set_target_properties(${_addlib_target} PROPERTIES LINK_FLAGS "-flat_namespace -undefined suppress")
endif(APPLE)
@@ -72,25 +60,20 @@ macro(SC_ADDLIB _addlib_target)
if(DEFINED ${_arg_prefix}_LINK_LIBRARIES)
foreach(_lib ${${_arg_prefix}_LINK_LIBRARIES})
if(${_arg_prefix}_STATIC AND TARGET ${_lib})
get_property(_libtype TARGET ${_lib} PROPERTY TYPE)
if(NOT ${_libtype} STREQUAL "STATIC_LIBRARY")
message(SEND_ERROR "SC_ADDLIB usage error - expected (static) LINK_LIBRARIES targets (${_lib})")
get_property(_libtype TARGET ${_lib} PROPERTY TYPE)
if(NOT ${_libtype} STREQUAL "STATIC_LIBRARY")
message(SEND_ERROR "SC_ADDLIB usage error - expected (static) LINK_LIBRARIES targets (${_lib})")
endif()
endif()
# Schema libraries are consumed directly by generated test programs.
# Publish their link requirements explicitly; the legacy unscoped
# signature does not reliably provide a transitive interface with
# current CMake versions.
target_link_libraries(${_addlib_target} PUBLIC ${_lib})
target_link_libraries(${_addlib_target} ${_lib})
endforeach()
target_link_libraries(${_addlib_target} ${_lib})
endif()
if(NOT ${_arg_prefix}_NO_INSTALL AND NOT ${_arg_prefix}_TESTABLE)
install(TARGETS ${_addlib_target}
RUNTIME DESTINATION ${BIN_DIR}
LIBRARY DESTINATION ${LIB_DIR}
ARCHIVE DESTINATION ${LIB_DIR}
ARCHIVE DESTINATION ${LIB_DIR}
)
endif()
endmacro()
@@ -101,3 +84,4 @@ endmacro()
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+35
View File
@@ -0,0 +1,35 @@
# Inherit the parent CMake setting
set(CURRENT_SOURCE_DIR @CMAKE_CURRENT_SOURCE_DIR@)
set(CURRENT_BINARY_DIR @CMAKE_CURRENT_BINARY_DIR@)
# Define a variety of convenience routines
include(@PROJECT_CMAKE_DIR@/Generated_Source_Utils.cmake)
# The following steps are executed to sync generated sources:
#
# 1. Create a new verification_info.cmake file and populate
# it with the MD5 sums for current files.
#
# 2. Overwrite the original cached verification_info.cmake
# and generated files with the new ones. If LOCKED_SOURCE_DIR
# is ON, this step will not be carried out - instead, an
# informational message with manual updating instructions
# will be printed.
set(new_info_file "${CURRENT_BINARY_DIR}/verification_info.cmake")
file(WRITE ${new_info_file} "# Autogenerated verification information\n")
# Handle input files
set(input_files "@MD5_FILELIST@")
WRITE_MD5_SUMS("${input_files}" "${new_info_file}")
message("New verification file created: ${new_info_file}")
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+30
View File
@@ -0,0 +1,30 @@
# Inherit the parent CMake setting
set(DEBUGGING_GENERATED_SOURCES @DEBUGGING_GENERATED_SOURCES@)
set(CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@")
# Include the file the provides the baseline against which
# current files will be compared
include("@BASELINE_INFORMATION_FILE@")
# Define a variety of convenience routines
include("@PROJECT_CMAKE_DIR@/Generated_Source_Utils.cmake")
# Individually verify all of the files in question.
set(filelist "@MD5_FILELIST@")
VERIFY_FILES("${filelist}" 1 srcs_pass)
if(NOT srcs_pass)
if(NOT DEBUGGING_GENERATED_SOURCES)
message(FATAL_ERROR "Sources have been modified and md5 sums have not been updated. This generally indicates either\n a) an input file has been modified but generated files have not been updated, or\n b) genenerated files have been edited directly.\nTo clear the error:\n a) Copy the new generated sources from the build directory to the generated/ sources directory, use the <target>_md5gen build target to create a new verifictation_info.cmake file, and copy verfication_info.cmake to generated/ as well.\n b) install Perplex/Re2C/LEMON and make the changes to the input file rather than the generated file.\nNote:\n If this is a debugging situation where multiple sequential tests must be conducted, temporarily set the variable DEBUGGING_GENERATED_SOURCES to ON during the CMake configure to disable this check.\nThis measure is necessary to ensure that compilations using either Perplex/Re2C/LEMON generation or the cached outputs of those tools produce consistent results.")
else(NOT DEBUGGING_GENERATED_SOURCES)
message(WARNING "Note: Sources have been modified and md5 sums have not been updated - build failure condition temporarily overridden by DEBUGGING_GENERATED_SOURCES setting.")
endif(NOT DEBUGGING_GENERATED_SOURCES)
endif(NOT srcs_pass)
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+84
View File
@@ -0,0 +1,84 @@
# creates sc_version_string.h, which defines sc_version()
# sc_version() returns a pretty commit description and a build timestamp.
# only update the file if the git commit has changed, because whenever the file is updated files including the header must rebuild
# parallel rebuilds can result in race conditions and failures, particularly when running ctest in parallel
# http://stackoverflow.com/questions/3780667
# http://www.cmake.org/pipermail/cmake/2009-February/027014.html
set(SC_IS_SUBBUILD "@SC_IS_SUBBUILD@")
set(SC_ENABLE_TESTING "@SC_ENABLE_TESTING@")
set(SC_VERSION_HEADER "${BINARY_DIR}/include/sc_version_string.h")
#---------- find commit id ------------------
#use git for a pretty commit id
#uses 'git describe --tags', so tags are required in the repo
#create a tag with 'git tag <name>' and 'git push --tags'
#if git can't be found, uses contents of SC_VERSION.txt
set(VERS_FILE ${SOURCE_DIR}/SC_VERSION.txt)
if(EXISTS ${SOURCE_DIR}/.git)
find_package(Git QUIET)
if(GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags WORKING_DIRECTORY ${SOURCE_DIR}
RESULT_VARIABLE res_var OUTPUT_VARIABLE GIT_COMMIT_ID)
if(NOT ${res_var} EQUAL 0)
file(READ ${VERS_FILE} GIT_COMMIT_ID LIMIT 255)
if(NOT SC_IS_SUBBUILD)
message(WARNING "Git failed (probably no tags in repo). Build will contain revision info from ${VERS_FILE}.")
endif(NOT SC_IS_SUBBUILD)
endif()
else(GIT_FOUND)
file(READ ${VERS_FILE} GIT_COMMIT_ID LIMIT 255)
if(NOT SC_IS_SUBBUILD)
message(WARNING "Git not found. Build will contain revision info from ${VERS_FILE}.")
endif(NOT SC_IS_SUBBUILD)
endif(GIT_FOUND)
else()
file(READ ${VERS_FILE} GIT_COMMIT_ID LIMIT 255)
if(NOT SC_IS_SUBBUILD)
message(WARNING "Git failed ('.git' not found). Build will contain revision info from ${VERS_FILE}.")
endif(NOT SC_IS_SUBBUILD)
endif()
string(REPLACE "\n" "" GIT_COMMIT_ID ${GIT_COMMIT_ID})
#-------------- date and time ---------------
if(SC_ENABLE_TESTING)
set (date_time_string "NA - disabled for testing")
else()
string(TIMESTAMP date_time_string UTC)
endif()
set(header_string "/* sc_version_string.h - written by cmake. Changes will be lost! */\n"
"#ifndef SC_VERSION_STRING\n"
"#define SC_VERSION_STRING\n\n"
"/*\n** The git commit id looks like \"test-1-g5e1fb47\", where test is the\n"
"** name of the last tagged git revision, 1 is the number of commits since that tag,\n"
"** 'g' is unknown, and 5e1fb47 is the first 7 chars of the git sha1 commit id.\n"
"** timestamp is created from date/time commands on known platforms, and uses\n"
"** preprocessor macros elsewhere.\n*/\n\n"
"static char sc_version[512] = {\n"
" \"git commit id: ${GIT_COMMIT_ID}, build timestamp ${date_time_string}\"\n"
"}\;\n\n"
"#endif\n"
)
#don't update the file unless something changed
string(RANDOM tmpsuffix)
file(WRITE ${SC_VERSION_HEADER}.${tmpsuffix} ${header_string})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SC_VERSION_HEADER}.${tmpsuffix} ${SC_VERSION_HEADER})
execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${SC_VERSION_HEADER}.${tmpsuffix})
if(NOT SC_IS_SUBBUILD)
message("-- sc_version_string.h is up-to-date.")
endif(NOT SC_IS_SUBBUILD)
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+6 -3
View File
@@ -1,5 +1,5 @@
project(SC_SUBPROJECT_SCHEMA_SCANNER)
cmake_minimum_required(VERSION 3.12)
cmake_minimum_required(VERSION 3.6.3)
if(NOT ("${CALLED_FROM}" STREQUAL "STEPCODE_CMAKELISTS" AND DEFINED SC_ROOT AND DEFINED SC_BUILDDIR))
message(" ${CALLED_FROM} ${SC_ROOT} ${SC_BUILDDIR}")
@@ -16,14 +16,15 @@ 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
${SC_ROOT}/src/express/generated/expscan.c
${SC_ROOT}/src/express/lexsupport.c
${SC_ROOT}/src/express/alg.c
${SC_ROOT}/src/express/alloc.c
${SC_ROOT}/src/express/caseitem.c
${SC_ROOT}/src/express/dict.c
${SC_ROOT}/src/express/entity.c
${SC_ROOT}/src/express/error.c
${SC_ROOT}/src/express/exp_kw.c
@@ -31,7 +32,6 @@ set(schema_scanner_src
${SC_ROOT}/src/express/express.c
${SC_ROOT}/src/express/factory.c
${SC_ROOT}/src/express/hash.c
${SC_ROOT}/src/express/lexact.c
${SC_ROOT}/src/express/linklist.c
${SC_ROOT}/src/express/memory.c
${SC_ROOT}/src/express/object.c
@@ -44,13 +44,16 @@ set(schema_scanner_src
${SC_ROOT}/src/express/symbol.c
${SC_ROOT}/src/express/type.c
${SC_ROOT}/src/express/variable.c
${SC_ROOT}/src/auxlib/bstrlib.c
${CMAKE_CURRENT_SOURCE_DIR}/schemaScanner.cc
)
include_directories(
${SC_ROOT}/include/
${SC_ROOT}/src/auxlib
${SC_ROOT}/src/express/
${SC_ROOT}/src/express/generated
${SC_ROOT}/src/base
${SC_ROOT}/src/exp2cxx
${SC_BUILDDIR}/include
)
+28 -121
View File
@@ -14,28 +14,22 @@
*/
extern "C" {
#define _XOPEN_SOURCE /* for S_IFDIR */
# include "expparse.h"
# include "expscan.h"
# include "express/scope.h"
# include "genCxxFilenames.h"
# include "sc_mkdir.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
# include <string.h>
#include "expparse.h"
#include "expscan.h"
#include "express/scope.h"
#include "genCxxFilenames.h"
#include <string.h>
#ifdef _WIN32
# include <direct.h>
# define getcwd _getcwd
#else
# include <unistd.h>
#endif
# ifdef _WIN32
# include <direct.h>
# define getcwd _getcwd
# else
# include <unistd.h>
# endif
}
#include <algorithm>
#include <string>
#include <sstream>
#include <iomanip>
@@ -51,35 +45,6 @@ using std::ofstream;
using std::cerr;
using std::cout;
static unsigned long entityChunkSize = 256;
static unsigned long typeChunkSize = 256;
static bool
parseChunkSizes( const char * value )
{
if( !value || !value[0] ) {
return false;
}
char * end = 0;
const unsigned long entities = strtoul( value, &end, 10 );
if( !end || entities == 0 ) {
return false;
}
unsigned long types = entities;
if( *end == ':' ) {
char * typeEnd = 0;
types = strtoul( end + 1, &typeEnd, 10 );
if( !end[1] || !typeEnd || *typeEnd || types == 0 ) {
return false;
}
} else if( *end ) {
return false;
}
entityChunkSize = entities;
typeChunkSize = types;
return true;
}
/** \return true for types that exp2cxx won't generate code for */
bool notGenerated( const Type t ) {
switch( TYPEget_body( t )->type ) {
@@ -160,30 +125,6 @@ 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 ) {
@@ -216,34 +157,20 @@ void writeLists( const char * schemaName, stringstream & eh, stringstream & ei,
cmLists << "# targets, logic, etc are within a set of macros shared by all schemas" << endl;
cmLists << "include(${SC_CMAKE_DIR}/SC_CXX_schema_macros.cmake)" << endl;
const int entityChunks = std::max( 1, ( ecount + static_cast<int>( entityChunkSize ) - 1 ) / static_cast<int>( entityChunkSize ) );
const int typeChunks = std::max( 1, ( tcount + static_cast<int>( typeChunkSize ) - 1 ) / static_cast<int>( typeChunkSize ) );
cmLists << "if(SC_EXP2CXX_LATE_BOUND)" << endl;
cmLists << " set(" << shortName << "_file_count 10)" << endl;
cmLists << "else()" << endl;
cmLists << " set(" << shortName << "_file_count " <<
( ecount + tcount ) * 2 + entityChunks + typeChunks + 14 << ")" << endl;
cmLists << "endif()" << endl << endl;
// * 2 for headers, + 10 other files
cmLists << "set(" << shortName << "_file_count " << ( ( ecount + tcount ) * 2 ) + 10 << ")" << endl << endl;
cmLists << "PROJECT(" << shortName << ")" << endl;
cmLists << "# list headers so they can be installed - entity, type, misc" << endl;
cmLists << "if(SC_EXP2CXX_LATE_BOUND)" << endl;
cmLists << " set(" << shortName << "_entity_hdrs)" << endl;
cmLists << "else()" << endl;
cmLists << " set(" << shortName << "_entity_hdrs" << endl;
cmLists << "set(" << shortName << "_entity_hdrs" << endl;
cmLists << eh.str();
cmLists << " )" << endl;
cmLists << "endif()" << endl << endl;
cmLists << " )" << endl << endl;
cmLists << "if(SC_EXP2CXX_LATE_BOUND)" << endl;
cmLists << " set(" << shortName << "_type_hdrs)" << endl;
cmLists << "else()" << endl;
cmLists << " set(" << shortName << "_type_hdrs" << endl;
cmLists << "set(" << shortName << "_type_hdrs" << endl;
cmLists << th.str();
cmLists << " )" << endl;
cmLists << "endif()" << endl << endl;
cmLists << " )" << endl << endl;
cmLists << "set(" << shortName << "_misc_hdrs" << endl;
cmLists << " Sdaiclasses.h schema.h" << endl;
@@ -268,26 +195,11 @@ void writeLists( const char * schemaName, stringstream & eh, stringstream & ei,
cmLists << "# unity build: #include small .cc files to reduce the number" << endl;
cmLists << "# of translation units that must be compiled" << endl;
cmLists << "if(SC_EXP2CXX_LATE_BOUND)" << endl;
cmLists << " set(" << shortName << "_unity_build FALSE)" << endl;
cmLists << " set(" << shortName << "_entity_impls)" << endl;
cmLists << " set(" << shortName << "_type_impls)" << endl;
cmLists << "elseif(SC_UNITY_BUILD)" << endl;
cmLists << " # bounded compact chunks; definitions are target-local" << endl;
cmLists << " set(" << shortName << "_unity_build TRUE)" << endl;
cmLists << " set(" << shortName << "_entity_impls" << endl;
for( int chunk = 1; chunk <= entityChunks; ++chunk ) {
cmLists << " Sdai" << schema_upper << "_unity_entities_" <<
std::setfill( '0' ) << std::setw( 4 ) << chunk << ".cc" << endl;
}
cmLists << " )" << endl;
cmLists << " set(" << shortName << "_type_impls" << endl;
for( int chunk = 1; chunk <= typeChunks; ++chunk ) {
cmLists << " Sdai" << schema_upper << "_unity_types_" <<
std::setfill( '0' ) << std::setw( 4 ) << chunk << ".cc" << endl;
}
cmLists << " )" << endl;
cmLists << "else()" << endl;
cmLists << "if(SC_UNITY_BUILD)" << endl << " # turns off include statements within type and entity .cc's - the unity T.U.'s include a unity header" << endl;
cmLists << " add_definitions( -DSC_SDAI_UNITY_BUILD)" << endl;
cmLists << " set(" << shortName << "_entity_impls Sdai" << schema_upper << "_unity_entities.cc)" << endl;
cmLists << " set(" << shortName << "_type_impls Sdai" << schema_upper << "_unity_types.cc)" << endl;
cmLists << "else(SC_UNITY_BUILD)" << endl;
cmLists << " set(" << shortName << "_entity_impls" << endl;
cmLists << ei.str();
cmLists << " )" << endl << endl;
@@ -295,13 +207,12 @@ void writeLists( const char * schemaName, stringstream & eh, stringstream & ei,
cmLists << " set(" << shortName << "_type_impls" << endl;
cmLists << ti.str();
cmLists << " )" << endl;
cmLists << "endif()" << endl << endl;
cmLists << "endif(SC_UNITY_BUILD)" << endl << endl;
cmLists << "set( " << shortName << "_misc_impls" << endl;
cmLists << " SdaiAll.cc compstructs.cc schema.cc" << endl;
cmLists << " Sdai" << schema_upper << ".cc" << endl;
cmLists << " Sdai" << schema_upper << ".init.cc" << endl;
cmLists << " Sdai" << schema_upper << ".sources.cmake )" << endl << endl;
cmLists << " Sdai" << schema_upper << ".init.cc )" << endl << endl;
cmLists << "set(schema_target_files ${" << shortName << "_entity_impls} " << "${" << shortName << "_type_impls} " << "${" << shortName << "_misc_impls})" << endl;
cmLists << "SCHEMA_TARGETS(\"" << input_filename << "\" \"" << schemaName << "\"" << endl;
@@ -309,7 +220,7 @@ void writeLists( const char * schemaName, stringstream & eh, stringstream & ei,
cmLists.close();
char pwd[BUFSIZ+1] = {0};
char pwd[BUFSIZ] = {0};
if( getcwd( pwd, BUFSIZ ) ) {
cout << pwd << "/" << shortName << endl;
} else {
@@ -390,18 +301,14 @@ int main( int argc, char ** argv ) {
DictionaryEntry de;
/* copied from fedex.c */
Express model;
if( ( argc != 2 && argc != 3 ) || ( strlen( argv[1] ) < 1 ) ) {
fprintf( stderr, "\nUsage: %s file.exp [entity-chunk-size[:type-chunk-size]]\nOutput: a CMakeLists.txt to build the schema,", argv[0] );
if( ( argc != 2 ) || ( strlen( argv[1] ) < 1 ) ) {
fprintf( stderr, "\nUsage: %s file.exp\nOutput: a CMakeLists.txt to build the schema,", argv[0] );
fprintf( stderr, " containing file names for entities, types, etc\n" );
fprintf( stderr, "also prints (to stdout) the absolute path to the directory CMakeLists.txt was created in\n" );
exit( EXIT_FAILURE );
}
EXPRESSprogram_name = argv[0];
input_filename = argv[1];
if( argc == 3 && !parseChunkSizes( argv[2] ) ) {
fprintf( stderr, "chunk sizes must be positive integers in N or N:N form\n" );
exit( EXIT_FAILURE );
}
EXPRESSinitialize();
+4 -51
View File
@@ -18,44 +18,6 @@ else(NOT DEFINED SC_UNITY_BUILD)
message( STATUS "Respecting user-defined SC_UNITY_BUILD value of ${SC_UNITY_BUILD}.")
endif(NOT DEFINED SC_UNITY_BUILD)
if(NOT DEFINED SC_EXP2CXX_CHUNK_SIZE)
set(SC_EXP2CXX_CHUNK_SIZE "64:8" CACHE STRING "Maximum entity:type objects in generated unity translation units")
endif()
if(NOT DEFINED SC_EXP2CXX_API_VERSION)
set(SC_EXP2CXX_API_VERSION "1")
endif()
set(SC_EXP2CXX_API_VERSION "${SC_EXP2CXX_API_VERSION}" CACHE STRING "Generated C++ API version (1 or 2)")
set_property(CACHE SC_EXP2CXX_API_VERSION PROPERTY STRINGS 1 2)
if(NOT SC_EXP2CXX_API_VERSION MATCHES "^[12]$")
message(FATAL_ERROR "SC_EXP2CXX_API_VERSION must be 1 or 2")
endif()
option(SC_EXP2CXX_LATE_BOUND "Generate descriptor-backed entities without early-bound C++ entity classes" OFF)
if(SC_EXP2CXX_LATE_BOUND AND NOT SC_EXP2CXX_API_VERSION STREQUAL "2")
message(FATAL_ERROR "SC_EXP2CXX_LATE_BOUND requires SC_EXP2CXX_API_VERSION=2")
endif()
option(SC_EXP2CXX_COMPAT_NAMES "Retain generated entity aliases in late-bound output" OFF)
if(SC_EXP2CXX_COMPAT_NAMES AND NOT SC_EXP2CXX_LATE_BOUND)
message(FATAL_ERROR "SC_EXP2CXX_COMPAT_NAMES requires SC_EXP2CXX_LATE_BOUND=ON")
endif()
if(NOT DEFINED SC_EXP2CXX_METADATA)
set(SC_EXP2CXX_METADATA "full")
endif()
set(SC_EXP2CXX_METADATA "${SC_EXP2CXX_METADATA}" CACHE STRING
"Generated schema metadata profile (full or structural)")
set_property(CACHE SC_EXP2CXX_METADATA PROPERTY STRINGS full structural)
if(NOT SC_EXP2CXX_METADATA MATCHES "^(full|structural)$")
message(FATAL_ERROR "SC_EXP2CXX_METADATA must be full or structural")
endif()
if(SC_EXP2CXX_METADATA STREQUAL "structural" AND
NOT SC_EXP2CXX_LATE_BOUND)
message(FATAL_ERROR
"SC_EXP2CXX_METADATA=structural requires SC_EXP2CXX_LATE_BOUND=ON")
endif()
# --- variables ---
# SC_ROOT: SC root dir
@@ -109,9 +71,9 @@ message( STATUS "Schema scanner built. Running it...")
# not sure if it makes sense to install this or not...
if(WIN32)
install(PROGRAMS ${SCANNER_OUT_DIR}/schema_scanner.exe DESTINATION ${BIN_DIR})
install(PROGRAMS ${SCANNER_OUT_DIR}/schema_scanner.exe DESTINATION ${BIN_INSTALL_DIR})
else(WIN32)
install(PROGRAMS ${SCANNER_OUT_DIR}/schema_scanner DESTINATION ${BIN_DIR})
install(PROGRAMS ${SCANNER_OUT_DIR}/schema_scanner DESTINATION ${BIN_INSTALL_DIR})
endif(WIN32)
# macro SCHEMA_CMLIST
@@ -120,7 +82,7 @@ endif(WIN32)
# SCHEMA_FILE - path to the schema
# TODO should we have a result variable to return schema name(s) found?
macro(SCHEMA_CMLIST SCHEMA_FILE)
execute_process(COMMAND ${SCANNER_OUT_DIR}/schema_scanner ${SCHEMA_FILE} ${SC_EXP2CXX_CHUNK_SIZE}
execute_process(COMMAND ${SCANNER_OUT_DIR}/schema_scanner ${SCHEMA_FILE}
WORKING_DIRECTORY ${SC_BINARY_DIR}/schemas
RESULT_VARIABLE _ss_stat
OUTPUT_VARIABLE _ss_out
@@ -135,16 +97,7 @@ macro(SCHEMA_CMLIST SCHEMA_FILE)
string(STRIP "${_ss_out}" _ss_stripped)
string(REGEX REPLACE "\\\n" ";" _list ${_ss_stripped})
foreach(_dir ${_list})
get_property(_already_added GLOBAL PROPERTY _SC_SCHEMA_DIRS)
list(FIND _already_added "${_dir}" _idx)
if(${_idx} EQUAL -1)
set_property(GLOBAL APPEND PROPERTY _SC_SCHEMA_DIRS "${_dir}")
# Keep generated targets under the top-level binary tree. Passing the
# absolute generated-source path as both arguments creates absolute
# make target names with newer CMake.
get_filename_component(_schema_dir_name "${_dir}" NAME)
add_subdirectory("${_dir}" "${SC_BINARY_DIR}/schema-targets/${_schema_dir_name}")
endif()
add_subdirectory(${_dir} ${_dir}) #specify source and binary dirs as the same
endforeach(_dir ${_ss_out})
# configure_file forces cmake to run again if the schema has been modified
#if multiple schemas in one file, _schema is the last one printed.
+83
View File
@@ -0,0 +1,83 @@
# Inherit the parent CMake setting
set(CURRENT_SOURCE_DIR @CMAKE_CURRENT_SOURCE_DIR@)
set(CURRENT_BINARY_DIR @CMAKE_CURRENT_BINARY_DIR@)
set(CACHED_FILES_DIR @CACHED_FILES_DIR@)
set(LEMON_EXECUTABLE @LEMON_EXECUTABLE@)
set(RE2C_EXECUTABLE @RE2C_EXECUTABLE@)
set(PERPLEX_EXECUTABLE @PERPLEX_EXECUTABLE@)
set(LOCKED_SOURCE_DIR @LOCKED_SOURCE_DIR@)
set(DEBUGGING_GENERATED_SOURCES @DEBUGGING_GENERATED_SOURCES@)
if(NOT DEBUGGING_GENERATED_SOURCES)
# Define a variety of convenience routines
include(@PROJECT_CMAKE_DIR@/Generated_Source_Utils.cmake)
# The following steps are executed to sync generated sources:
#
# 1. Create a new verification_info.cmake file and populate
# it with the current versions of perplex, re2c and lemon.
# Also add the MD5 sums for current template files.
#
# 2. For all files that need to be updated in the cache,
# calculate new MD5 sums and add them to the new
# verification_info.cmake - this is usually the input
# files and the generated outputs.
#
# 3. Overwrite the original cached verification_info.cmake
# and generated files with the new ones. If LOCKED_SOURCE_DIR
# is ON, this step will not be carried out - instead, an
# informational message with manual updating instructions
# will be printed.
set(new_info_file "${CURRENT_BINARY_DIR}/verification_info.cmake.new")
file(WRITE ${new_info_file} "# Autogenerated verification information\n")
# Handle generator version numbers
GET_GENERATOR_EXEC_VERSIONS()
file(APPEND ${new_info_file} "set(baseline_lemon_version \"${lemon_version}\")\n")
file(APPEND ${new_info_file} "set(baseline_re2c_version \"${re2c_version}\")\n")
file(APPEND ${new_info_file} "set(baseline_perplex_version \"${perplex_version}\")\n")
# Handle template files
set(template_files "@TEMPLATE_FILELIST@")
WRITE_MD5_SUMS("${template_files}" "${new_info_file}")
# Handle input files
set(input_files "@INPUT_FILELIST@")
WRITE_MD5_SUMS("${input_files}" "${new_info_file}")
# Handle generated files
set(output_files "@BUILD_OUTPUT_FILELIST@")
WRITE_MD5_SUMS("${output_files}" "${new_info_file}")
# Copy files into their final locations
if(NOT LOCKED_SOURCE_DIR)
configure_file(${new_info_file} "${CACHED_FILES_DIR}/verification_info.cmake" COPYONLY)
foreach(outf ${output_files})
get_filename_component(filecorename ${outf} NAME)
message("copying ${outf} to ${CACHED_FILES_DIR}/${filecorename}")
configure_file(${outf} "${CACHED_FILES_DIR}/${filecorename}" COPYONLY)
endforeach(outf ${output_files})
else(NOT LOCKED_SOURCE_DIR)
message("Source directory writing is locked - LOCKED_SOURCE_DIR is set.")
message("To update the generated files, manually copy the following to ${CACHED_FILES_DIR}:")
message(" ${new_info_file} (rename to verification_info.cmake)")
foreach(outf ${output_files})
message(" ${outf}")
endforeach(outf ${output_files})
endif(NOT LOCKED_SOURCE_DIR)
else(NOT DEBUGGING_GENERATED_SOURCES)
message("\nNote: DEBUGGING_GENERATED_SOURCES is enabled - generated outputs will contain configuration-specific debugging information, so syncing cached output files is not possible. To restore normal behavior, disable DEBUGGING_GENERATED_SOURCES.\n")
endif(NOT DEBUGGING_GENERATED_SOURCES)
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+1 -1
View File
@@ -9,7 +9,7 @@ set(CTEST_INITIAL_CACHE "
SITE:STRING=${CTEST_SITE}
BUILDNAME:STRING=${CTEST_BUILD_NAME}
SC_ENABLE_TESTING:BOOL=ON
CMAKE_BUILD_TYPE:STRING=Debug
SC_BUILD_TYPE:STRING=Debug
")
+1 -1
View File
@@ -10,7 +10,7 @@
# .exp file inside, which it uses. otherwise, ${path} is assumed to
# be an express file.
if(NOT "${SC_BUILD_EXPRESS_ONLY}" AND NOT "${SC_BUILD_SCHEMAS}" STREQUAL "")
if(NOT ${SC_BUILD_EXPRESS_ONLY} AND NOT "${SC_BUILD_SCHEMAS}" STREQUAL "")
include(${SC_CMAKE_DIR}/schema_scanner/schemaScanner.cmake)
foreach(src ${SC_SDAI_ADDITIONAL_EXES_SRCS})
get_filename_component(name ${src} NAME_WE)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-62
View File
@@ -1,62 +0,0 @@
# AP242 TREAT Schema File
This directory contains an altered version of the AP242 (ISO 10303-242) schema.
It is corrected to avoid the non-standard parsing requirement of the original
by using explicit TREAT expression for type narrowing
## The Difference
Both files are identical except for a single line at line 34149 in the `styled_item` entity WHERE rule WR3:
**Original (242_mim_lf.exp)**:
```express
QUERY(it <* item | ...)
```
**TREAT version (242_mim_lf_treat.exp)**:
```express
QUERY(it <* TREAT(item AS set_representation_item) | ...)
```
### Historical Context
The original AP242 schema contains a WHERE rule that:
1. Checks if `item` (a SELECT type) is a `SET_REPRESENTATION_ITEM`
2. Then tries to iterate over `item` in a QUERY expression
This pattern requires implicit type narrowing, which is not part of the ISO 10303-11 standard.
### STEPcode's Solution
STEPcode implements **flow-sensitive type narrowing** as an extension:
- Recognizes TYPEOF guard patterns like `'Type' IN TYPEOF(var)` in AND expressions
- Automatically narrows the type for subsequent uses
- Makes the original schema parse successfully
### Standards-Compliant Alternative
The TREAT version uses the ISO 10303-11 TREAT expression:
- `TREAT(item AS set_representation_item)` explicitly narrows the type
- No implicit narrowing needed
- Works in any compliant EXPRESS parser
## Testing
Both versions parse successfully and produce identical output:
```bash
# Run comparison test
./test/compare_ap242_versions.sh
```
Expected output:
```
✓ Both versions parse successfully
✓ Both versions generate the same number of files
```
For detailed comparison, see `doc/ap242-comparison.md`.
## Related Documentation
- `doc/ap242-comparison.md` - Detailed comparison and analysis
- `doc/express-type-unwrapping.md` - TREAT and narrowing documentation
- `src/express/test/README_AP242_BASELINE.md` - Historical PE056 error info
-165
View File
@@ -1,165 +0,0 @@
# AP242 Schema Comparison: Flow-Sensitive Narrowing vs TREAT Expression
## Overview
This document compares two versions of the AP242 schema to demonstrate the difference between STEPcode's non-standard flow-sensitive narrowing extension and the ISO 10303-11 compliant TREAT expression.
## Schema Versions
### 1. Original Version (`242_mim_lf.exp`)
- **Status**: Uses implicit flow-sensitive narrowing (non-standard extension)
- **Location**: `data/ap242/242_mim_lf.exp`
- **Size**: 54,756 lines
- **Problematic code**: Line 34149 in `styled_item` entity, WR3 WHERE rule
### 2. TREAT Version (`242_mim_lf_treat.exp`)
- **Status**: Standards-compliant using TREAT expression
- **Location**: `data/ap242/242_mim_lf_treat.exp`
- **Size**: 54,756 lines
- **Fix applied**: Line 34149 - explicit TREAT expression
## The Problem
In the `styled_item` entity at line ~34148, the WHERE rule WR3 contains:
```express
WR3: ('AP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF.MAPPED_ITEM' IN TYPEOF(item)) OR
('AP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF.GEOMETRIC_REPRESENTATION_ITEM' IN TYPEOF(item)) OR
(('AP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF.SET_REPRESENTATION_ITEM' IN TYPEOF(item)) AND
(SIZEOF(QUERY(it <* item | ...)) = 0));
```
### Issue
- `item` is of type `styled_item_target`, which is a SELECT type
- The SELECT contains `set_representation_item` (which is an aggregate type)
- The code checks `'SET_REPRESENTATION_ITEM' IN TYPEOF(item)` (a TYPEOF guard)
- Then tries to iterate over `item` in a QUERY: `QUERY(it <* item | ...)`
### Why This Was Problematic
According to strict ISO 10303-11 standards, you cannot iterate over a SELECT type directly in a QUERY expression, even if there's a preceding TYPEOF guard. The guard and the QUERY are separate expressions in an AND clause.
## The Solutions
### Solution 1: Flow-Sensitive Narrowing (Non-Standard Extension)
STEPcode implements a **flow-sensitive type narrowing** extension that:
1. Recognizes the pattern `'TypeName' IN TYPEOF(var)` in AND expressions
2. Automatically narrows the type of `var` to `TypeName` for subsequent expressions in the AND
3. Allows `QUERY(it <* item | ...)` to work because `item` is implicitly narrowed to `set_representation_item`
**Code (original, line 34149)**:
```express
QUERY(it <* item | ...)
```
**How it works**:
- The AND expression LHS has the guard: `'SET_REPRESENTATION_ITEM' IN TYPEOF(item)`
- The RHS has the QUERY: `SIZEOF(QUERY(it <* item | ...)) = 0`
- STEPcode's narrowing recognizes the pattern and narrows `item` to `set_representation_item`
- The QUERY can now iterate over the narrowed type
### Solution 2: TREAT Expression (Standards-Compliant)
The ISO 10303-11 standard provides the TREAT expression for explicit type narrowing:
**Code (TREAT version, line 34149)**:
```express
QUERY(it <* TREAT(item AS set_representation_item) | ...)
```
**How it works**:
- `TREAT(item AS set_representation_item)` explicitly narrows the SELECT type to the member type
- The QUERY can iterate over the result of TREAT, which is guaranteed to be `set_representation_item`
- No implicit narrowing needed - the intent is explicit in the code
## The Exact Difference
```diff
--- data/ap242/242_mim_lf.exp
+++ data/ap242/242_mim_lf_treat.exp
@@ -34146,7 +34146,7 @@
('AP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF.GEOMETRIC_REPRESENTATION_ITEM' IN TYPEOF(item)) OR
(('AP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF.SET_REPRESENTATION_ITEM' IN TYPEOF(item)) AND
(SIZEOF(QUERY(it
- <* item
+ <* TREAT(item AS set_representation_item)
| NOT (('AP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF.MAPPED_ITEM' IN TYPEOF(it)) OR
('AP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF.GEOMETRIC_REPRESENTATION_ITEM' IN
TYPEOF(it))))) =
```
**Change**: Single line change from `<* item` to `<* TREAT(item AS set_representation_item)`
## Testing Results
### Original Version (with Flow-Sensitive Narrowing)
```bash
./build/bin/exp2cxx data/ap242/242_mim_lf.exp /tmp/ap242_original_test
```
**Result**: ✅ Parses successfully, generates 5,626 C++ files
### TREAT Version (Standards-Compliant)
```bash
./build/bin/exp2cxx data/ap242/242_mim_lf_treat.exp /tmp/ap242_treat_test
```
**Result**: ✅ Parses successfully, generates 5,626 C++ files
### Output Comparison
Both versions generate identical output:
- Same number of entities
- Same entity relationships
- Same multiple inheritance warnings
- Identical "Finished writing files" status
## Verification
To verify both versions produce consistent output:
```bash
# Parse original version
mkdir -p /tmp/ap242_original
./build/bin/exp2cxx data/ap242/242_mim_lf.exp /tmp/ap242_original
# Parse TREAT version
mkdir -p /tmp/ap242_treat
./build/bin/exp2cxx data/ap242/242_mim_lf_treat.exp /tmp/ap242_treat
# Compare generated headers (should be identical except for file references)
diff /tmp/ap242_original/SdaiAP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF.h \
/tmp/ap242_treat/SdaiAP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF.h
```
## Implications
### For STEPcode Users
- **Current**: Both versions work due to flow-sensitive narrowing extension
- **Future**: TREAT version is more portable if other EXPRESS parsers are used
- **Recommended**: Use TREAT for new schemas to ensure standards compliance
### For STEPcode Development
- Flow-sensitive narrowing is a valuable usability extension
- TREAT expression provides standards-compliant alternative
- Both should continue to be supported for compatibility
### For Standards Compliance
- Original AP242 schema uses pattern that requires extension
- TREAT version is fully ISO 10303-11 compliant
- TREAT makes intent explicit and improves code clarity
## Related Documentation
- `doc/express-type-unwrapping.md` - Full documentation of TREAT and narrowing features
- `src/express/test/README_AP242_BASELINE.md` - Historical PE056 error documentation
- Test schemas:
- `test/unitary_schemas/flow_narrowing_test.exp` - Flow-sensitive narrowing examples
- `test/unitary_schemas/minimal_treat_test.exp` - TREAT expression examples
## Conclusion
This comparison demonstrates:
1. ✅ STEPcode's flow-sensitive narrowing successfully handles the original AP242 schema
2. ✅ TREAT expression provides the standards-compliant alternative
3. ✅ Both approaches produce identical, correct output
4. ✅ The single-line change makes the code more explicit and portable
The availability of both approaches gives users flexibility while maintaining standards compliance when needed.
-251
View File
@@ -1,251 +0,0 @@
# AP242 API v2 Output Benchmarks
This file records comparable measurements for the staged API v2 output
work. It is intended to make changes in generated output cost visible in
the commits which introduce them.
## Method
The measurements were made on 2026-08-02 with GCC 13.3.0 and C++11.
The schema under test was BRL-CAD's `ap242e4.exp` conversion schema.
The real exchange-file workload was the NIST STC 09 ASME AP242 edition
4 sample, `nist_stc_09_asme1_ap242-e4.stp`.
The generator used `--late-bound`, the default 64-entity and 8-type chunk
limits, and a release STEPcode build. Compilation used `-O2 -fPIC` and two
concurrent compiler processes. Generated-output counts include `.cc`, `.h`,
and `.cmake` files through directory depth two. The baseline is commit
`fa2758c5` before recommendations 1--4.
## Results
| Measurement | Baseline | Recommendations 1--4 | Change |
|---|---:|---:|---:|
| Generated files | 5,719 | 905 | -84.2% |
| Generated lines | 254,220 | 123,552 | -51.4% |
| Generated bytes | 13,942,523 | 9,804,680 | -29.7% |
| Entity leaf files | 4,814 | 0 | -100.0% |
| Generation wall time | 2.74 s | 0.56 s | -79.6% |
| Generation peak RSS | 109,024 KiB | 109,280 KiB | +0.2% |
| Compile/link wall time | 157.68 s | 37.02 s | -76.5% |
| Compile/link user time | 277.75 s | 66.32 s | -76.1% |
| Compile/link peak RSS | 593,320 KiB | 199,156 KiB | -66.4% |
| Schema shared library | 9,956,640 B | 7,716,096 B | -22.5% |
| ELF relocations | 28,843 | 39,719 | +37.7% |
| Function symbols | 15,641 | 13,542 | -13.4% |
| Read/write wall time | 0.26 s | 0.25 s | -3.8% |
| Read/write peak RSS | 88,732 KiB | 85,040 KiB | -4.2% |
The relocation increase is caused by the stable module-ID tables referring
to descriptor slots. It is recorded here because the packed schema image
stage is expected to remove most of that cost.
## Recommendations 1--4
This stage adds stable entity, type, and attribute IDs through `SchemaModule`,
makes compatibility entity names opt-in for late-bound output, moves schema
rules and complex-entity support to runtime-consumed tables, and writes late
entity metadata directly to bounded chunks instead of creating 4,814 leaf
files.
The real AP242 exchange-file check created and validated 10,609 instances
with zero errors and zero warnings. Its 949,685-byte rewritten Part 21 file
matched the baseline apart from the expected `FILE_NAME` timestamp.
## Recommendation 5
This stage resolves each late-bound entity's flattened attribute layout once
after schema initialization. Instance construction then follows descriptor
and index records directly instead of recursively walking supertypes and
repeating attribute-name searches. The cache is external to
`EntityDescriptor`, so its object layout and the API v1 ABI are unchanged.
The construction benchmark uses the 1,531 `DIRECTION` instances in the real
exchange file and repeats that population 1,000 times. This isolates the
work changed by this stage while retaining a type and frequency from the
AP242 workload. Results are the median of three runs.
| Measurement | Recommendations 1--4 | Recommendation 5 | Change |
|---|---:|---:|---:|
| 1,531,000 entity constructions | 0.84 s | 0.63 s | -25.0% |
| Construction user time | 0.82 s | 0.61 s | -25.6% |
| Construction peak RSS | 68,956 KiB | 69,600 KiB | +0.9% |
| 20 full read/write runs | 4.90 s | 4.91 s | no measurable change |
| Full read/write peak RSS | 85,164 KiB | 85,732 KiB | +0.7% |
| `libstepcore` size | 640,936 B | 651,312 B | +1.6% |
The complete exchange-file check still created and validated 10,609
instances with zero errors and zero warnings. Its rewritten file remained
949,685 bytes and differed from the previous stage only in the expected
`FILE_NAME` timestamp. Generated schema file counts, source size, and the
schema shared library are unchanged because this is a shared-runtime change.
## Recommendation 6
This stage replaces the generated `SchemaModuleSlot` pointer arrays with a
16-byte, relocation-free `SchemaModuleImage`. Shared initialization helpers
capture descriptor pointers in stable generated-ID order and transfer those
vectors to `SchemaModule` after initialization. The older slot-based entry
point remains available for existing generated API v2 code.
Source and binary measurements compare recommendation 5 with the packed
image. Compile times use matching clean CMake builds with two compiler
processes. Read/write times are medians from paired 20-run batches.
| Measurement | Recommendation 5 | Recommendation 6 | Change |
|---|---:|---:|---:|
| Generated files | 905 | 905 | unchanged |
| Generated lines | 123,552 | 117,046 | -5.3% |
| Generated bytes | 9,804,680 | 9,060,249 | -7.6% |
| Schema module source | 808,907 B | 64,367 B | -92.0% |
| Schema module source lines | 7,280 | 773 | -89.4% |
| Compile/link wall time | 41.38 s | 41.49 s | no measurable change |
| Compile/link peak RSS | 208,312 KiB | 208,188 KiB | -0.1% |
| Schema shared library | 7,728,384 B | 7,470,304 B | -3.3% |
| ELF relocations | 39,719 | 33,221 | -16.4% |
| 20 full read/write runs | 5.10 s | 5.07 s | -0.6% |
| Full read/write peak RSS | 85,736 KiB | 85,572 KiB | -0.2% |
| `libstepcore` size | 651,312 B | 661,088 B | +1.5% |
The image removes 6,498 per-descriptor pointer relocations. The shared
runtime grows by 9,776 bytes once, while each AP242 schema library is 258,080
bytes smaller. Generated API v1 output and the conventional public entity
classes remain unchanged.
The complete exchange-file check again created and validated 10,609
instances with zero errors and zero warnings. Its 949,685-byte rewrite
differed from recommendation 5 only in the expected `FILE_NAME` timestamp.
## Recommendation 7
This stage replaces the remaining generated descriptor procedures with one
bounded, offset-based schema image. The shared loader validates every array,
string, range, descriptor reference, schema binding, and complex-entity tree
before it changes the registry. It then constructs the descriptor graph with
an explicit per-load context; the process-global capture path remains only for
older generated API v2 code. Complex-entity metadata uses the same packed
representation and validation model.
Source and binary measurements compare recommendation 6 with the complete
descriptor image. Compile times use clean CMake builds with two compiler
processes. Read/write times use matching 20-run batches.
| Measurement | Recommendation 6 | Recommendation 7 | Change |
|---|---:|---:|---:|
| Generated files | 905 | 865 | -4.4% |
| Generated lines | 117,046 | 86,400 | -26.2% |
| Generated bytes | 9,060,249 | 4,865,657 | -46.3% |
| Entity initialization chunks | 38 | 0 | -100.0% |
| Compile/link wall time | 41.49 s | 18.71 s | -54.9% |
| Compile/link peak RSS | 208,188 KiB | 208,528 KiB | +0.2% |
| Schema shared library | 7,470,304 B | 3,503,352 B | -53.1% |
| ELF relocations | 33,221 | 9,620 | -71.0% |
| 20 full read/write runs | 5.07 s | 4.97 s | -2.0% |
| Full read/write peak RSS | 85,572 KiB | 82,916 KiB | -3.1% |
The image removes the 2,407 generated entity initialization functions and
23,601 additional relocations. The generated schema library is 3,966,952
bytes smaller, while its existing typed SELECT and enumeration factories
remain available for this transitional stage.
The complete exchange-file check created and validated 10,609 instances with
zero errors and zero warnings. Its 949,685-byte rewrite retained the same
semantic result as recommendation 6.
## Recommendations 8 and 9
This stage makes the compact late-bound output independent of generated type
classes. Shared descriptor-driven implementations now construct SELECT,
enumeration, and aggregate values, including nested values and BOOLEAN or
LOGICAL aliases. Enumeration elements and renamed USE or REFERENCE items are
retained in the packed image. The conventional early-bound API v1 and API v2
paths still emit their schema-specific type classes.
The generated schema header is now a dependency-bounded consumer interface.
It contains stable entity, type, and attribute IDs plus `SchemaModule` lookup
functions, and includes only `schemaModule.h`. Runtime and model-construction
declarations remain in the internal `schema.h` umbrella.
| Measurement | Recommendation 7 | Recommendations 8--9 | Change |
|---|---:|---:|---:|
| Generated files | 865 | 10 | -98.8% |
| Generated lines | 86,400 | 54,839 | -36.5% |
| Generated bytes | 4,865,657 | 3,303,993 | -32.1% |
| Type leaf files | 802 | 0 | -100.0% |
| Type initialization chunks | 51 | 0 | -100.0% |
| Compile/link wall time | 18.71 s | 1.21 s | -93.5% |
| Compile/link peak RSS | 208,528 KiB | 126,580 KiB | -39.3% |
| Schema shared library | 3,503,352 B | 2,178,296 B | -37.8% |
| ELF relocations | 9,620 | 49 | -99.5% |
| Exported function symbols | 4,647 | 8 | -99.8% |
| Public header preprocessed bytes | 2,384,191 | 635,945 | -73.3% |
| 20 full read/write runs | 4.97 s | 4.91 s | -1.2% |
| Full read/write peak RSS | 82,916 KiB | 82,304 KiB | -0.7% |
The complete exchange-file check again created and validated 10,609
instances with zero errors and zero warnings, and wrote the same 949,685-byte
semantic result. Runtime unit coverage separately exercises generic SELECT,
enumeration, aggregate, malformed-image, and packed rename behavior.
## Recommendation 10
This stage adds an opt-in `structural` metadata profile for late-bound API
version 2. The default `full` profile is unchanged. Structural images keep
the descriptor graph needed to construct, read, write, and inspect entity,
attribute, type, aggregate, enumeration, SELECT, inverse, and renamed values.
They omit EXPRESS descriptions, WHERE and UNIQUE rules, schema rule and
algorithm text, supertype statements, derived expressions, and symbolic
aggregate-bound text.
The source and library measurements below compare matching fresh output from
the two profiles. Compile times use clean CMake builds with one compiler
process; read/write times use matching 20-run batches.
| Measurement | Full metadata | Structural metadata | Change |
|---|---:|---:|---:|
| Generated files | 10 | 10 | unchanged |
| Generated lines | 54,839 | 29,993 | -45.3% |
| Generated bytes | 3,304,007 | 1,525,897 | -53.8% |
| Packed schema source | 2,612,413 B | 834,303 B | -68.1% |
| Generation wall time | 0.48 s | 0.41 s | -14.6% |
| Compile/link wall time | 2.08 s | 2.03 s | -2.4% |
| Compile/link peak RSS | 126,784 KiB | 118,220 KiB | -6.8% |
| Schema shared library | 2,178,296 B | 720,120 B | -66.9% |
| ELF relocations | 49 | 49 | unchanged |
| 20 full read/write runs | 4.76 s | 4.71 s | -1.1% |
| Full read/write peak RSS | 82,276 KiB | 78,900 KiB | -4.1% |
The structural profile created and validated all 10,609 instances in the
real exchange file with zero errors and zero warnings. It wrote the same
949,685-byte semantic result as the full profile.
## Recommendation 11
This stage writes each generated file to a sibling temporary file and replaces
the destination only when its content changes. A compact generated-file
manifest supports safe cleanup when an option change makes old entity, type,
or unity files obsolete; files not named by the previous manifest are left
alone. The manifest itself is also content-stable.
The deterministic-output audit also found that nonliteral aggregate bounds
were being read through the integer member of the expression union. Packed
images now emit those bounds as expression records, eliminating process-address
values from generated AP242 source as well as correcting the metadata kind.
| Measurement after identical AP242 generation | Rewrite all | Stable output | Change |
|---|---:|---:|---:|
| Changed schema source/header timestamps | 10 of 10 | 0 of 10 | -100.0% |
| Changed manifest timestamps | n/a | 0 of 1 | stable |
| Generation wall time | 0.41 s | 0.40 s | no overhead |
| Following CMake build wall time | 2.01 s | 0.06 s | -97.0% |
| Following build peak RSS | 118,108 KiB | 18,432 KiB | -84.4% |
The AP242 manifest is 390 bytes. Switching the focused regression schema
from early-bound API version 2 to compact late-bound output removes all stale
entity, type, and unity files and their empty directories while preserving an
unrelated file in the output directory.
The real exchange-file check still created and validated all 10,609 instances
with zero errors and zero warnings. Its rewritten result remained 949,685
bytes.
-367
View File
@@ -1,367 +0,0 @@
# EXPRESS Type Unwrapping and Narrowing
## Overview
This document describes the type unwrapping and narrowing features implemented in STEPcode's EXPRESS compiler. These features enable proper type checking and semantic analysis for aggregate types and SELECT type narrowing.
**Note:** Some features described here are extensions beyond the ISO 10303-11 standard and are explicitly marked as such.
## Deep Aggregate Unwrapping
### Background
In EXPRESS, aggregate types (ARRAY, LIST, SET, BAG) can be nested and wrapped in type definitions. For semantic analysis and type checking, the compiler often needs to "unwrap" these layers to access the underlying element type.
### Shallow vs Deep Type Checking
#### Shallow Aggregate Check: `TYPEis_aggregate`
The macro `TYPEis_aggregate(t)` performs a **shallow** check by testing if `t->u.type->body->base` is non-NULL. This indicates the type has a base type, which is characteristic of aggregate types.
```c
#define TYPEis_aggregate(t) ((t)->u.type->body->base)
```
**Important:** This is a shallow check and does not follow type definition chains. It returns true if the immediate type structure has a base type.
**Use when:**
- You need a quick check if a type is directly an aggregate
- You're working with the immediate type structure
- Performance is critical and deep unwrapping isn't needed
#### Deep Aggregate Unwrapping: `TYPEget_nonaggregate_base_type`
The function `TYPEget_nonaggregate_base_type(Type t)` performs **deep unwrapping** by iteratively following the chain of aggregate base types until reaching a non-aggregate type.
```express
TYPE int_list = LIST OF INTEGER;
TYPE named_int_list = int_list; -- typedef chain
TYPE set_of_lists = SET OF named_int_list;
```
For `set_of_lists`:
- `TYPEis_aggregate()` → true (immediate check)
- `TYPEget_nonaggregate_base_type()` → INTEGER (unwraps through SET → LIST → INTEGER)
**Use when:**
- Comparing element types across different aggregate wrappers
- Type resolution requires the ultimate element type
- Semantic checking needs to validate deep type compatibility
### Deep Unwrapping Implementation
```c
Type TYPEget_nonaggregate_base_type( Type t ) {
while( TYPEis_aggregate( t ) ) {
t = t->u.type->body->base;
}
return t;
}
```
This function safely handles:
- Nested aggregates (SET OF LIST OF ...)
- Type definition chains
- Mixed aggregate types
### Aggregate Type Comparison: `TYPE_retrieve_aggregate`
For SELECT types containing multiple aggregate members, `TYPE_retrieve_aggregate()` validates that all aggregate members share the same element type.
```express
TYPE item_a = SET OF INTEGER;
TYPE item_b = LIST OF INTEGER;
TYPE my_select = SELECT(item_a, item_b); -- Valid: both have INTEGER elements
```
The function:
1. Iterates through SELECT members
2. Identifies which are aggregates
3. Unwraps typedef chains to find element types
4. Returns common element type or NULL if incompatible
## TREAT Expression Semantics
### ISO 10303-11 Standard Syntax
The TREAT expression is defined in ISO 10303-11 as:
```express
TREAT(expression AS type_identifier)
```
**Purpose:** Explicitly narrow a SELECT type to one of its member types.
### STEPcode Implementation
STEPcode implements TREAT as specified in ISO 10303-11 with the following semantics:
#### Type Resolution
1. **Operand Resolution:** The expression being narrowed is resolved first
```c
EXPresolve( e->e.op1, s, Type_Dont_Care );
operand_type = e->e.op1->return_type;
```
2. **Target Type Lookup:** The target type identifier is resolved via scope lookup
```c
target_type = (Type)SCOPEfind( s, e->symbol.name, SCOPE_FIND_TYPE );
```
3. **Type Compatibility:** The implementation validates that narrowing is semantically valid
- For SELECT operands: Verifies target is a member type
- For other types: Allows permissively (may emit warnings)
4. **Return Type:** The expression's return type becomes the target type
```c
return target_type; /* Not Type_Generic */
```
#### Error Handling
**Clear errors with location information:**
- **Missing operand:** `SYNTAX` error - "TREAT expression missing operand"
- **Missing target type:** `SYNTAX` error - "TREAT expression missing target type"
- **Undefined type:** `UNDEFINED_TYPE` error with the type name
- **Type mismatch:** Currently permissive (no error, future: may warn)
All errors use `ERRORreport_with_symbol()` which provides:
- File name and line number
- Symbol context
- Descriptive error message
#### Example Usage
```express
TYPE attachment = SELECT(nail, screw);
END_TYPE;
FUNCTION get_length(item : attachment) : REAL;
LOCAL
n : nail;
END_LOCAL;
IF ('EXAMPLE.NAIL' IN TYPEOF(item)) THEN
n := TREAT(item AS nail); -- Narrows SELECT to nail
RETURN n.length;
END_IF;
RETURN 0.0;
END_FUNCTION;
```
### Grammar Integration
The TREAT syntax is integrated into the EXPRESS parser grammar as a unary expression:
```yacc
unary_expression ::= TOK_TREAT TOK_LEFT_PAREN expression TOK_AS
TOK_IDENTIFIER TOK_RIGHT_PAREN
```
Key points:
- `TOK_TREAT`: Recognized as a keyword
- Creates unary expression with `OP_TREAT` operator
- Operand stored in `op1`
- Target type name stored in `symbol` field
## Flow-Sensitive SELECT Narrowing
**Extension Status:** This is a **non-standard extension** that enhances type safety for SELECT types.
### Background
EXPRESS WHERE clauses often use TYPEOF guards to check SELECT types before accessing member-specific attributes. Flow-sensitive narrowing automatically narrows SELECT types within the scope of such guards.
### Pattern Recognition
The narrowing system recognizes this pattern:
```express
'TypeName' IN TYPEOF(variable)
```
When this pattern appears in an AND conjunction, the variable is narrowed to `TypeName` for subsequent expressions in the conjunction.
### Implementation Architecture
#### Refinement Context
A **refinement context** tracks active type narrowings during expression resolution:
```c
typedef struct RefinementContext_ {
Refinement refinements; /* Linked list of variable → type mappings */
struct RefinementContext_ *previous; /* Stack of contexts */
} *RefinementContext;
RefinementContext active_refinements = NULL; /* Thread-local global */
```
#### Pattern Matching
The function `match_typeof_guard()` identifies guard patterns:
1. Expression is `IN` operator
2. Left operand is string literal (type name)
3. Right operand is `TYPEOF(identifier)`
4. Identifier resolves to a variable
#### Refinement Collection
The function `collect_refinements_from_conjunction()` recursively walks AND expressions:
1. Recursively descends into AND nodes
2. Matches TYPEOF guard patterns at leaves
3. Validates narrowing is semantically correct:
- Variable must have SELECT type
- Target type must be SELECT member (validated via `is_select_member()`)
4. Returns linked list of valid refinements
#### Application
In `EXPresolve_op_and()`:
```c
Type EXPresolve_op_and(Expression e, Scope s) {
EXPresolve(e->e.op1, s, Type_Dont_Care); /* Resolve LHS normally */
Refinement refs = collect_refinements_from_conjunction(e->e.op1, s);
if (refs) {
/* Create temporary context */
struct RefinementContext_ ctx;
ctx.refinements = refs;
ctx.previous = active_refinements;
active_refinements = &ctx;
EXPresolve(e->e.op2, s, Type_Dont_Care); /* Resolve RHS with narrowing */
/* Restore previous context */
active_refinements = ctx.previous;
free_refinements(refs);
} else {
EXPresolve(e->e.op2, s, Type_Dont_Care);
}
return Type_Logical;
}
```
### Behavior Scope
**What is narrowed:**
- Variables with SELECT type
- Within RHS of AND expressions
- Where LHS contains TYPEOF guard
**What is NOT narrowed:**
- OR expressions (conservative - doesn't extract from disjunction)
- NOT expressions (conservative - doesn't extract from negation)
- Other boolean operators
- Variables not guarded by TYPEOF
**Rationale:** Conservative approach prevents false narrowing in cases where the guard may not hold.
### Limitations
1. **Single-level context:** Only immediate AND RHS is narrowed, not deeply nested scopes
2. **No cross-statement narrowing:** Limited to expression-level scope
3. **AND-only:** Does not propagate through OR/NOT (conservative)
4. **Pattern-based:** Only recognizes exact `'Type' IN TYPEOF(var)` pattern
### Example
```express
ENTITY test_entity;
item : target; -- target is SELECT(set_representation_item, simple_int)
WHERE
wr1: ('SCHEMA.SET_REPRESENTATION_ITEM' IN TYPEOF(item)) AND
(SIZEOF(item) > 0); -- item narrowed to set_representation_item
END_ENTITY;
```
Without narrowing, `SIZEOF(item)` would fail (can't take SIZEOF of SELECT). With narrowing, `item` is known to be an aggregate, so `SIZEOF` is valid.
## Memory Management
### Refinement Lifecycle
1. **Collection:** `collect_refinements_from_conjunction()` allocates refinement nodes
2. **Usage:** Active during RHS expression resolution only
3. **Cleanup:** `free_refinements()` called after RHS resolution completes
### Context Stack Model
The implementation uses a **stack-based context model** rather than deep copying:
- `RefinementContext` has `previous` pointer forming a stack
- New contexts pushed onto stack with `active_refinements = &ctx`
- Restored with `active_refinements = ctx.previous`
- No deep copying of refinement data
**Memory safety:**
- Refinement nodes allocated individually
- Freed immediately after use
- No dangling pointers (stack-local contexts)
- No memory leaks (verified by code inspection)
## Testing
### Test Coverage
**TREAT expression tests:**
- `test/unitary_schemas/minimal_treat_test.exp` - Basic TREAT usage
- `test/unitary_schemas/test_treat_real.exp` - Nested SELECT types
- `test/unitary_schemas/treat_expression.exp` - TREAT in WHERE clauses
**Flow-sensitive narrowing tests:**
- `test/unitary_schemas/flow_narrowing_test.exp` - AND-based narrowing
- `test/unitary_schemas/select_aggregate_test.exp` - SELECT of aggregates
**Production schema comparison:**
- `data/ap242/242_mim_lf.exp` - Original AP242 with flow-sensitive narrowing
- `data/ap242/242_mim_lf_treat.exp` - TREAT-based standards-compliant version
- `test/compare_ap242_versions.sh` - Automated comparison script
See `doc/ap242-comparison.md` for detailed analysis of the AP242 schema comparison.
### AP242 Compatibility
The implementation is validated against the AP242 schema, ensuring:
- Large-scale schema parsing succeeds
- Complex type hierarchies handled correctly
- Production schema compatibility
**AP242 Schema Versions:**
- `data/ap242/242_mim_lf.exp` - Original schema using flow-sensitive narrowing extension
- `data/ap242/242_mim_lf_treat.exp` - Standards-compliant version using TREAT expression
Both versions parse successfully and produce identical output. See `doc/ap242-comparison.md` for detailed analysis.
## Standards Compliance Notes
### ISO 10303-11 Compliance
**Fully compliant:**
- TREAT expression syntax and semantics
- Aggregate type definitions
- SELECT type definitions
- Standard type resolution rules
**Extensions (non-standard):**
- Flow-sensitive type narrowing in AND expressions
- Permissive TREAT type checking (warns vs errors)
### Extension Philosophy
STEPcode's extensions follow these principles:
1. **Conservative:** Only apply when semantically safe
2. **Permissive:** Prefer warnings over errors where reasonable
3. **Explicit:** Document extensions clearly
4. **Compatible:** Don't break standard-compliant schemas
Extensions are designed to enhance usability while maintaining backward compatibility with ISO 10303-11 compliant EXPRESS schemas.
+1 -33
View File
@@ -45,11 +45,6 @@ EXPRESS code into C++ source code. The C++ source code is generated
in files in the directory in which exp2cxx was run. The files are
named according to the schema names in the input EXPRESS file.
Generated files are replaced only when their content changes. exp2cxx records
the files it owns in `.exp2cxx-manifest`; a later run removes obsolete files
from that manifest while leaving unrelated files in the output directory
untouched.
.SH OPTIONS
.TP
.B -s|S
@@ -62,34 +57,6 @@ Generates C++ classes for use with CORBA (Orbix).
.B -l|L
Prints logging code in the generated C++ classes.
.TP
.B -k entity-chunk-size[:type-chunk-size]
Limits the number of generated schema objects in each deterministic unity
translation unit. A single value applies to both entity and type chunks.
.TP
.B -V 1|2, --api-version 1|2
Selects the generated C++ API. Version 1 is the source-compatible default.
Version 2 emits compact SELECT classes, table-driven schema initialization, and
dependency-bounded entity headers backed by shared runtime code. Version 2
clients include the individual entity headers they use; schema.h does not
include every entity class definition.
.TP
.B -T, --late-bound
Selects API version 2 and omits generated early-bound C++ entity classes.
Entity instances are constructed at runtime from schema descriptors. This mode
is intended for conversion and inspection applications which do not require the
conventional generated entity API.
.TP
.B --compat-names
Retains the generated entity-name aliases in late-bound output. Normal
late-bound API v2 output uses schema module IDs instead and omits these aliases.
.TP
.B --metadata full|structural
Selects the generated schema metadata profile. Full is the default and
retains EXPRESS descriptions, constraints, and executable schema text.
Structural is available with late-bound API version 2; it retains the entity,
attribute, type, aggregate, enumeration, SELECT, inverse, and rename graph
needed by conversion tools while omitting descriptive and constraint text.
.TP
.B -v
Produces a version description.
.TP
@@ -194,3 +161,4 @@ appropriate file to download).
.SH BUGS
See fedex(1).
+12 -6
View File
@@ -6,7 +6,7 @@
# for the use of this file.
#
project(AP203Minimum)
cmake_minimum_required(VERSION 3.12)
cmake_minimum_required(VERSION 3.6.3)
# Set STEPCODE_ROOT_DIR to point to the root of the STEPcode source tree.
if(NOT DEFINED STEPCODE_ROOT_DIR)
@@ -14,14 +14,14 @@ if(NOT DEFINED STEPCODE_ROOT_DIR)
endif(NOT DEFINED STEPCODE_ROOT_DIR)
# STEPCODE_ROOT_DIR is relative or absolute path?
if(EXISTS "${CMAKE_BINARY_DIR}/${STEPCODE_ROOT_DIR}/src/express/express.c")
if(EXISTS "${CMAKE_BINARY_DIR}/${STEPCODE_ROOT_DIR}/SC_VERSION.txt")
set(STEPCODE_ROOT_DIR "${CMAKE_BINARY_DIR}/${STEPCODE_ROOT_DIR}")
message("** STEPCODE_ROOT_DIR is a relative path; converted to absolute path: ${STEPCODE_ROOT_DIR}.")
else()
if(NOT EXISTS "${STEPCODE_ROOT_DIR}/src/express/express.c")
if(NOT EXISTS "${STEPCODE_ROOT_DIR}/SC_VERSION.txt")
message(FATAL_ERROR "**** Cannot locate STEPCODE_ROOT_DIR - try an absolute path.")
endif(NOT EXISTS "${STEPCODE_ROOT_DIR}/src/express/express.c")
endif(EXISTS "${CMAKE_BINARY_DIR}/${STEPCODE_ROOT_DIR}/src/express/express.c")
endif(NOT EXISTS "${STEPCODE_ROOT_DIR}/SC_VERSION.txt")
endif(EXISTS "${CMAKE_BINARY_DIR}/${STEPCODE_ROOT_DIR}/SC_VERSION.txt")
# Use STEPcode as library, but build from this build process.
@@ -31,6 +31,7 @@ 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")
@@ -50,13 +51,18 @@ 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 stepcore stepeditor stepdai steputils ${SCHEMA_LINK_NAME})
set(STEPCODE_LIBRARIES base 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}
@@ -6,7 +6,7 @@
# for the use of this file.
#
project(AP203Minimum)
cmake_minimum_required(VERSION 3.12)
cmake_minimum_required(VERSION 3.6.3)
INCLUDE( ExternalProject )
@@ -19,6 +19,7 @@ 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
@@ -27,6 +28,7 @@ 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
@@ -42,6 +44,7 @@ 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
@@ -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}
-DCMAKE_BUILD_TYPE=Debug
-DSC_BUILD_TYPE=Debug
-DSC_BUILD_SCHEMAS=ap203/ap203.exp
-DBUILD_STATIC_LIBS=ON
-DSC_BUILD_STATIC_LIBS=ON
-DSC_PYTHON_GENERATOR=OFF
-DSC_INSTALL_PREFIX:PATH=<INSTALL_DIR>
)
@@ -22,3 +22,8 @@ ENDIF()
SET( STEPCODE_BINARY_DIR ${BINARY_DIR} )
# SC CMake does not honor -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
# Consequently, force Debug so it installs in ../sc-install directory
# instead of /usr/local/lib.
#
# SC's own programs fail to build with -DSC_BUILD_SHARED_LIBS=OFF
+8 -8
View File
@@ -49,15 +49,15 @@
// $./AP203Minimum
// AP203Minimum outfile.stp
#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 <STEPfile.h>
#include <sdai.h>
#include <STEPattribute.h>
#include <ExpDict.h>
#include <Registry.h>
#include <errordesc.h>
#include <clstepcore/STEPcomplex.h>
#include <cleditor/SdaiHeaderSchema.h>
#include <STEPcomplex.h>
#include <SdaiHeaderSchema.h>
#include "schema.h"
+7 -11
View File
@@ -22,26 +22,22 @@ set(express_HDRS
express/variable.h
)
install(FILES ${express_HDRS}
DESTINATION ${INCLUDE_DIR}/stepcode/express)
DESTINATION ${INCLUDE_INSTALL_DIR}/stepcode/express)
set(exppp_HDRS
exppp/exppp.h
)
install(FILES ${exppp_HDRS}
DESTINATION ${INCLUDE_DIR}/stepcode/exppp)
DESTINATION ${INCLUDE_INSTALL_DIR}/stepcode/exppp)
install(FILES ordered_attrs.h
sc_export.h
DESTINATION ${INCLUDE_DIR}/stepcode)
sc_stdbool.h
DESTINATION ${INCLUDE_INSTALL_DIR}/stepcode)
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)
install(FILES ${SC_BINARY_DIR}/${INCLUDE_INSTALL_DIR}/sc_cf.h
${SC_BINARY_DIR}/${INCLUDE_INSTALL_DIR}/sc_version_string.h
DESTINATION ${INCLUDE_INSTALL_DIR}/stepcode)
# Local Variables:
# tab-width: 8
-24
View File
@@ -1,24 +0,0 @@
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
-20
View File
@@ -1,20 +0,0 @@
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
-27
View File
@@ -1,27 +0,0 @@
set(LAZY_HDRS
headerSectionReader.h
lazyFileReader.h
lazyP21DataSectionReader.h
p21HeaderSectionReader.h
lazyDataSectionReader.h
lazyInstMgr.h
lazySupport.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
-131
View File
@@ -1,131 +0,0 @@
#ifndef LAZYSUPPORT_H
#define LAZYSUPPORT_H
#include <cstddef>
#include <functional>
#include <iosfwd>
#include <string>
#include <vector>
#include "cllazyfile/lazyTypes.h"
#include "sc_export.h"
class lazyInstMgr;
class SDAI_Application_instance;
enum LazyDiagnosticSeverity {
LAZY_DIAGNOSTIC_INFO,
LAZY_DIAGNOSTIC_WARNING,
LAZY_DIAGNOSTIC_ERROR,
LAZY_DIAGNOSTIC_FATAL
};
struct SC_LAZYFILE_EXPORT LazyDiagnostic {
LazyDiagnosticSeverity severity;
instanceID entity;
std::string type;
lazyFileOffset offset;
uint64_t line;
std::string attribute;
std::string message;
uint64_t occurrences;
LazyDiagnostic(): severity( LAZY_DIAGNOSTIC_INFO ), entity( 0 ), offset( 0 ),
line( 0 ), occurrences( 1 ) {}
};
struct SC_LAZYFILE_EXPORT LazyScanProgress {
fileID file;
lazyFileOffset offset;
lazyFileOffset fileSize;
uint64_t instancesScanned;
LazyScanProgress(): file( 0 ), offset( 0 ), fileSize( 0 ), instancesScanned( 0 ) {}
};
struct SC_LAZYFILE_EXPORT LazyCacheStatistics {
uint64_t instancesScanned;
uint64_t instancesLoaded;
uint64_t instancesPinned;
uint64_t cacheHighWater;
uint64_t cacheHits;
uint64_t cacheMisses;
uint64_t materializations;
uint64_t evictions;
uint64_t activeBatches;
uint64_t dataSections;
uint64_t residentSourceBytes;
uint64_t sourceBytesHighWater;
bool cancelled;
LazyCacheStatistics(): instancesScanned( 0 ), instancesLoaded( 0 ), instancesPinned( 0 ),
cacheHighWater( 0 ), cacheHits( 0 ), cacheMisses( 0 ), materializations( 0 ),
evictions( 0 ), activeBatches( 0 ), dataSections( 0 ), residentSourceBytes( 0 ),
sourceBytesHighWater( 0 ), cancelled( false ) {}
};
typedef std::function<void ( const LazyScanProgress & )> LazyProgressCallback;
typedef std::function<bool ()> LazyCancellationCallback;
typedef std::function<void ( const LazyDiagnostic & )> LazyDiagnosticCallback;
/** A non-owning, zero-copy view of an indexed instance-ID vector.
* The view remains valid until another file is scanned by the manager.
*/
class SC_LAZYFILE_EXPORT LazyInstanceIdView {
public:
typedef instanceRefs::const_iterator const_iterator;
LazyInstanceIdView(): _ids( 0 ) {}
explicit LazyInstanceIdView( const instanceRefs * ids ): _ids( ids ) {}
const_iterator begin() const;
const_iterator end() const;
size_t size() const;
bool empty() const;
instanceID operator[]( size_t index ) const;
private:
const instanceRefs * _ids;
};
/** A dependency closure materialized and pinned for a bounded operation.
* STEPcode parsing remains single-threaded. Detach immutable conversion data
* before releasing the batch or passing work to another thread.
*/
class SC_LAZYFILE_EXPORT LazyInstanceBatch {
public:
LazyInstanceBatch();
~LazyInstanceBatch();
LazyInstanceBatch( LazyInstanceBatch && other );
LazyInstanceBatch & operator=( LazyInstanceBatch && other );
LazyInstanceBatch( const LazyInstanceBatch & ) = delete;
LazyInstanceBatch & operator=( const LazyInstanceBatch & ) = delete;
bool valid() const;
void release();
const std::vector<instanceID> & roots() const;
const std::vector<instanceID> & instances() const;
SDAI_Application_instance * get( instanceID id ) const;
private:
friend class lazyInstMgr;
LazyInstanceBatch( lazyInstMgr * manager, const std::vector<instanceID> & roots,
const std::vector<instanceID> & instances );
lazyInstMgr * _manager;
std::vector<instanceID> _roots;
std::vector<instanceID> _instances;
};
/** Adapter preserving a stream-oriented diagnostic presentation. */
class SC_LAZYFILE_EXPORT LazyTextDiagnosticAdapter {
public:
explicit LazyTextDiagnosticAdapter( std::ostream & stream );
void operator()( const LazyDiagnostic & diagnostic ) const;
private:
std::ostream * _stream;
};
#endif // LAZYSUPPORT_H
-72
View File
@@ -1,72 +0,0 @@
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
schemaInit.h
schemaModule.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
-362
View File
@@ -1,362 +0,0 @@
#ifndef SCHEMAINIT_H
#define SCHEMAINIT_H
#include <stddef.h>
#include "sc_export.h"
#include "clstepcore/attrDescriptor.h"
#include "clstepcore/aggrTypeDescriptor.h"
#include "clstepcore/dictSchema.h"
#include "clstepcore/entityDescriptor.h"
#include "clstepcore/enumTypeDescriptor.h"
#include "clstepcore/selectTypeDescriptor.h"
#include "clstepcore/schemaModule.h"
class Derived_attribute;
class Inverse_attribute;
class ComplexCollect;
class Registry;
/** Compact records used by API v2 generated schema initialization. */
struct SC_CORE_EXPORT SchemaInitRecord {
Schema ** slot;
const char * name;
ModelContentsCreator modelContentsCreator;
};
struct SC_CORE_EXPORT EntityDescriptorInitRecord {
EntityDescriptor ** slot;
const char * name;
Schema ** schemaSlot;
Logical abstractEntity;
Logical externalMapping;
Creator creator;
};
struct SC_CORE_EXPORT EntitySupertypeInitRecord {
EntityDescriptor * supertype;
};
enum TypeDescriptorInitKind {
TypeDescriptorInit_Base,
TypeDescriptorInit_Enum,
TypeDescriptorInit_Select,
TypeDescriptorInit_Aggregate,
TypeDescriptorInit_Array,
TypeDescriptorInit_List,
TypeDescriptorInit_Set,
TypeDescriptorInit_Bag
};
struct SC_CORE_EXPORT TypeDescriptorInitRecord {
void * slot;
TypeDescriptorInitKind kind;
const char * name;
PrimitiveType fundamentalType;
Schema ** schemaSlot;
const char * description;
int uniqueElements;
SelectCreator selectCreator;
EnumCreator enumCreator;
AggregateCreator aggregateCreator;
TypeDescriptorInitRecord( TypeDescriptor ** descriptorSlot,
const char * typeName, PrimitiveType type,
Schema ** schema, const char * typeDescription );
TypeDescriptorInitRecord( EnumTypeDescriptor ** descriptorSlot,
const char * typeName, PrimitiveType type,
Schema ** schema, const char * typeDescription,
EnumCreator creator );
TypeDescriptorInitRecord( SelectTypeDescriptor ** descriptorSlot,
int unique, const char * typeName,
PrimitiveType type, Schema ** schema,
const char * typeDescription,
SelectCreator creator );
TypeDescriptorInitRecord( AggrTypeDescriptor ** descriptorSlot,
const char * typeName, PrimitiveType type,
Schema ** schema, const char * typeDescription,
AggregateCreator creator );
TypeDescriptorInitRecord( ArrayTypeDescriptor ** descriptorSlot,
const char * typeName, PrimitiveType type,
Schema ** schema, const char * typeDescription,
AggregateCreator creator );
TypeDescriptorInitRecord( ListTypeDescriptor ** descriptorSlot,
const char * typeName, PrimitiveType type,
Schema ** schema, const char * typeDescription,
AggregateCreator creator );
TypeDescriptorInitRecord( SetTypeDescriptor ** descriptorSlot,
const char * typeName, PrimitiveType type,
Schema ** schema, const char * typeDescription,
AggregateCreator creator );
TypeDescriptorInitRecord( BagTypeDescriptor ** descriptorSlot,
const char * typeName, PrimitiveType type,
Schema ** schema, const char * typeDescription,
AggregateCreator creator );
};
/**
* Attribute descriptor record. The overloaded constructors preserve the
* concrete type of generated descriptor slots without templates or casts in
* generated translation units.
*/
struct SC_CORE_EXPORT AttributeInitRecord {
AttrDescriptor ** attributeSlot;
Derived_attribute ** derivedSlot;
Inverse_attribute ** inverseSlot;
const char * name;
const TypeDescriptor * domain;
Logical optional;
Logical unique;
AttrType_Enum attrType;
const char * initializer;
const char * invertedAttribute;
const char * invertedEntity;
AttributeInitRecord( AttrDescriptor ** slot, const char * attrName,
const TypeDescriptor * domainType, Logical isOptional,
Logical isUnique, AttrType_Enum type,
const char * init = 0 );
AttributeInitRecord( Derived_attribute ** slot, const char * attrName,
const TypeDescriptor * domainType, Logical isOptional,
Logical isUnique, AttrType_Enum type,
const char * init = 0 );
AttributeInitRecord( Inverse_attribute ** slot, const char * attrName,
const TypeDescriptor * domainType, Logical isOptional,
Logical isUnique, const char * invertedAttr,
const char * invertedEnt );
};
enum ComplexNodeInitKind {
ComplexNodeInit_Simple,
ComplexNodeInit_And,
ComplexNodeInit_Or,
ComplexNodeInit_AndOr
};
struct SC_CORE_EXPORT ComplexNodeInitRecord {
ComplexNodeInitKind kind;
const char * name;
size_t firstChild;
size_t nextSibling;
};
struct SC_CORE_EXPORT ComplexListInitRecord {
size_t rootNode;
};
struct SC_CORE_EXPORT GlobalRuleInitRecord {
const char * name;
const char * text;
};
enum SchemaImageDescriptorRefKind {
SchemaImageRef_None,
SchemaImageRef_Entity,
SchemaImageRef_Type,
SchemaImageRef_Builtin,
SchemaImageRef_Aggregate
};
struct SC_CORE_EXPORT SchemaImageDescriptorRef {
uint32_t kind;
uint32_t schema;
uint32_t index;
};
struct SC_CORE_EXPORT SchemaImageSchemaRecord {
uint32_t name;
uint32_t firstEntity;
uint32_t entityCount;
uint32_t firstType;
uint32_t typeCount;
};
struct SC_CORE_EXPORT SchemaImageEntityRecord {
uint32_t schema;
uint32_t name;
uint32_t flags;
uint32_t supertypeStatement;
uint32_t firstSupertype;
uint32_t supertypeCount;
uint32_t firstAttribute;
uint32_t attributeCount;
uint32_t firstWhereRule;
uint32_t whereRuleCount;
uint32_t firstUniqueRule;
uint32_t uniqueRuleCount;
};
enum SchemaImageEntityFlags {
SchemaImageEntity_Abstract = 1u << 0,
SchemaImageEntity_ExternalMapping = 1u << 1
};
struct SC_CORE_EXPORT SchemaImageTypeRecord {
uint32_t schema;
uint32_t name;
uint32_t description;
uint32_t fundamentalType;
uint32_t descriptorKind;
int32_t uniqueElements;
SchemaImageDescriptorRef referent;
uint32_t aggregate;
uint32_t firstSelectElement;
uint32_t selectElementCount;
uint32_t firstWhereRule;
uint32_t whereRuleCount;
uint32_t firstEnumElement;
uint32_t enumElementCount;
};
struct SC_CORE_EXPORT SchemaImageAttributeRecord {
uint32_t name;
SchemaImageDescriptorRef domain;
uint32_t optional;
uint32_t unique;
uint32_t attrType;
uint32_t initializer;
uint32_t invertedAttribute;
uint32_t invertedEntity;
};
struct SC_CORE_EXPORT SchemaImageAggregateRecord {
uint32_t schema;
uint32_t description;
uint32_t fundamentalType;
SchemaImageDescriptorRef referent;
uint32_t bound1Type;
int32_t bound1;
uint32_t bound1Text;
uint32_t bound2Type;
int32_t bound2;
uint32_t bound2Text;
uint32_t optionalElements;
uint32_t uniqueElements;
};
struct SC_CORE_EXPORT SchemaImageRuleRecord {
uint32_t text;
};
enum SchemaImageSchemaTextKind {
SchemaImageText_GlobalRule,
SchemaImageText_Function,
SchemaImageText_Procedure
};
struct SC_CORE_EXPORT SchemaImageSchemaTextRecord {
uint32_t schema;
uint32_t kind;
uint32_t name;
uint32_t text;
};
struct SC_CORE_EXPORT SchemaImageRenameRecord {
SchemaImageDescriptorRef descriptor;
uint32_t schema;
uint32_t name;
};
struct SC_CORE_EXPORT SchemaImageSchemaBinding {
Schema ** schemaSlot;
ModelContentsCreator modelContentsCreator;
SchemaModule * module;
};
struct SC_CORE_EXPORT SchemaImageTypeBinding {
void * slot;
SelectCreator selectCreator;
EnumCreator enumCreator;
AggregateCreator aggregateCreator;
};
enum SchemaLoadError {
SchemaLoad_Ok,
SchemaLoad_UnsupportedVersion,
SchemaLoad_TruncatedImage,
SchemaLoad_InvalidOffset,
SchemaLoad_InvalidString,
SchemaLoad_InvalidReference,
SchemaLoad_CountMismatch,
SchemaLoad_MissingBinding,
SchemaLoad_ModuleFailure
};
struct SC_CORE_EXPORT SchemaLoadResult {
SchemaLoadError error;
uint32_t record;
bool Succeeded() const {
return error == SchemaLoad_Ok;
}
const char * Message() const;
};
SC_CORE_EXPORT SchemaLoadResult InitializeSchemaFromImage(
Registry & registry, const SchemaModuleImage & image,
const SchemaImageSchemaBinding * schemaBindings,
size_t schemaBindingCount,
const SchemaImageTypeBinding * typeBindings,
size_t typeBindingCount, SchemaLoadContext & context );
enum PackedComplexImageVersion {
PackedComplexImageVersion_1 = 1
};
struct SC_CORE_EXPORT PackedComplexImage {
uint32_t version;
uint32_t byteSize;
uint32_t stringOffset;
uint32_t stringBytes;
uint32_t nodeOffset;
uint32_t nodeCount;
uint32_t listOffset;
uint32_t listCount;
};
struct SC_CORE_EXPORT PackedComplexNode {
uint32_t kind;
uint32_t name;
uint32_t firstChild;
uint32_t nextSibling;
};
struct SC_CORE_EXPORT PackedComplexList {
uint32_t rootNode;
};
SC_CORE_EXPORT ComplexCollect * InitializePackedComplexSupport(
const PackedComplexImage & image, SchemaLoadResult * result = 0 );
SC_CORE_EXPORT void InitializeSchemas( Registry & reg,
const SchemaInitRecord * records,
size_t count );
SC_CORE_EXPORT void InitializeSchemaModuleImages(
const SchemaInitRecord * records, size_t count );
SC_CORE_EXPORT void InitializeEntityDescriptors(
const EntityDescriptorInitRecord * records, size_t count );
SC_CORE_EXPORT void InitializeTypeDescriptors(
const TypeDescriptorInitRecord * records, size_t count );
SC_CORE_EXPORT void InitializeTypeMetadata(
Registry & reg, Schema & schema, TypeDescriptor & type,
const TypeDescriptor * referent,
const TypeDescriptor * const * selectElements, size_t selectElementCount );
SC_CORE_EXPORT void InitializeEntityMetadata(
Registry & reg, EntityDescriptor & entity, Schema & schema,
const EntitySupertypeInitRecord * supertypes, size_t supertypeCount,
const AttributeInitRecord * attributes, size_t attributeCount );
SC_CORE_EXPORT void InitializeWhereRules(
TypeDescriptor & owner, const char * const * rules, size_t count );
SC_CORE_EXPORT void InitializeUniquenessRules(
EntityDescriptor & owner, const char * const * rules, size_t count );
SC_CORE_EXPORT void InitializeGlobalRules(
Schema & schema, const GlobalRuleInitRecord * rules, size_t count );
SC_CORE_EXPORT void InitializeFunctions(
Schema & schema, const char * const * functions, size_t count );
SC_CORE_EXPORT void InitializeProcedures(
Schema & schema, const char * const * procedures, size_t count );
SC_CORE_EXPORT ComplexCollect * InitializeComplexSupport(
const ComplexNodeInitRecord * nodes, size_t nodeCount,
const ComplexListInitRecord * lists, size_t listCount );
#endif
-171
View File
@@ -1,171 +0,0 @@
#ifndef SCHEMAMODULE_H
#define SCHEMAMODULE_H
#include <stddef.h>
#include <stdint.h>
#include <vector>
#include "sc_export.h"
class AttrDescriptor;
class EntityDescriptor;
class Schema;
class TypeDescriptor;
enum SchemaModuleSlotKind {
SchemaModuleSlot_Entity,
SchemaModuleSlot_Type,
SchemaModuleSlot_EnumType,
SchemaModuleSlot_SelectType,
SchemaModuleSlot_AggregateType,
SchemaModuleSlot_ArrayType,
SchemaModuleSlot_ListType,
SchemaModuleSlot_SetType,
SchemaModuleSlot_BagType,
SchemaModuleSlot_Attribute,
SchemaModuleSlot_DerivedAttribute,
SchemaModuleSlot_InverseAttribute
};
struct SC_CORE_EXPORT SchemaModuleSlot {
const void * slot;
SchemaModuleSlotKind kind;
};
enum SchemaModuleImageVersion {
SchemaModuleImageVersion_1 = 1,
SchemaModuleImageVersion_2 = 2
};
enum SchemaModuleImageFlags {
SchemaModuleImage_FullMetadata = 0,
SchemaModuleImage_StructuralMetadata = 1u << 0
};
/**
* Relocation-free generated header for a schema module image.
*
* Version 1 records only stable generated-ID counts. Version 2 describes
* one bounded block of offset-based schemas, descriptors, metadata, and
* strings. Runtime loading validates the complete block before constructing
* descriptors or changing a Registry.
*/
struct SC_CORE_EXPORT SchemaModuleImage {
uint32_t version;
uint32_t entityCount;
uint32_t typeCount;
uint32_t attributeCount;
/* Version 2 fields. Version 1 initializers leave these zero. */
uint32_t byteSize;
uint32_t flags;
uint32_t schemaCount;
uint32_t stringBytes;
uint32_t schemaOffset;
uint32_t entityOffset;
uint32_t typeOffset;
uint32_t attributeOffset;
uint32_t aggregateCount;
uint32_t aggregateOffset;
uint32_t referenceCount;
uint32_t referenceOffset;
uint32_t ruleCount;
uint32_t ruleOffset;
uint32_t schemaTextCount;
uint32_t schemaTextOffset;
uint32_t enumElementCount;
uint32_t enumElementOffset;
uint32_t stringOffset;
uint32_t reserved;
uint64_t fingerprint;
uint32_t renameCount;
uint32_t renameOffset;
};
class SchemaModule;
/**
* Per-load descriptor collection used by packed API v2 schema images.
*
* Keeping this state explicit makes independent schema loads reentrant and
* avoids the process-global capture map retained for version-1 images.
*/
class SC_CORE_EXPORT SchemaLoadContext {
class Impl;
Impl * _impl;
SchemaLoadContext( const SchemaLoadContext & );
SchemaLoadContext & operator=( const SchemaLoadContext & );
friend class SchemaModule;
public:
SchemaLoadContext();
~SchemaLoadContext();
void Begin( Schema & schema );
void RecordEntity( Schema & schema, const EntityDescriptor * entity );
void RecordType( Schema & schema, const TypeDescriptor * type );
void RecordAttribute( Schema & schema, const AttrDescriptor * attribute );
};
SC_CORE_EXPORT void RecordSchemaModuleEntity(
Schema & schema, const EntityDescriptor * entity );
SC_CORE_EXPORT void RecordSchemaModuleType(
Schema & schema, const TypeDescriptor * type );
SC_CORE_EXPORT void RecordSchemaModuleAttribute(
Schema & schema, const AttrDescriptor * attribute );
SC_CORE_EXPORT void BeginSchemaModuleImage( Schema & schema );
/**
* Stable API v2 view of a generated schema.
*
* Generated EntityId, TypeId, and AttributeId enumerations are converted to
* indexes before calling this class. Keeping the public lookup API separate
* from generated descriptor globals allows the underlying representation to
* move from C++ objects to packed schema data without another API break.
*/
class SC_CORE_EXPORT SchemaModule {
Schema * _schema;
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable: 4251 )
#endif
std::vector<const EntityDescriptor *> _entities;
std::vector<const TypeDescriptor *> _types;
std::vector<const AttrDescriptor *> _attributes;
uint64_t _fingerprint;
#ifdef _MSC_VER
#pragma warning( pop )
#endif
public:
SchemaModule();
~SchemaModule();
void Initialize(
Schema & schema,
const EntityDescriptor * const * entities, size_t entityCount,
const TypeDescriptor * const * types, size_t typeCount,
const AttrDescriptor * const * attributes, size_t attributeCount );
void InitializeFromSlots(
Schema & schema,
const SchemaModuleSlot * entities, size_t entityCount,
const SchemaModuleSlot * types, size_t typeCount,
const SchemaModuleSlot * attributes, size_t attributeCount );
void InitializeFromImage( Schema & schema,
const SchemaModuleImage & image );
bool InitializeFromContext( Schema & schema, SchemaLoadContext & context,
uint64_t fingerprint );
bool IsInitialized() const;
const Schema & GetSchema() const;
const EntityDescriptor * Entity( size_t id ) const;
const TypeDescriptor * Type( size_t id ) const;
const AttrDescriptor * Attribute( size_t id ) const;
size_t EntityCount() const;
size_t TypeCount() const;
size_t AttributeCount() const;
uint64_t Fingerprint() const;
};
#endif
-20
View File
@@ -1,20 +0,0 @@
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
-31
View File
@@ -1,31 +0,0 @@
#ifndef SCL_CF_H
#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
#cmakedefine HAVE_SYS_PARAM_H 1
#cmakedefine HAVE_SYSENT_H 1
#cmakedefine HAVE_UNISTD_H 1
#cmakedefine HAVE_DIRENT_H 1
#cmakedefine HAVE_STDBOOL_H 1
#cmakedefine HAVE_PROCESS_H 1
#cmakedefine HAVE_IO_H 1
#cmakedefine SC_TRACE_FPRINTF 1
#cmakedefine HAVE_ABS 1
#cmakedefine HAVE_MEMCPY 1
#cmakedefine HAVE_MEMMOVE 1
#cmakedefine HAVE_GETOPT 1
#cmakedefine HAVE_VSNPRINTF 1
#cmakedefine HAVE_SSIZE_T 1
#cmakedefine HAVE_STD_THREAD 1
#cmakedefine HAVE_STD_CHRONO 1
#cmakedefine HAVE_NULLPTR 1
#endif /* SCL_CF_H */
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef EXPPP_H
#define EXPPP_H
#include <stdbool.h>
#include <sc_stdbool.h>
#include <sc_export.h>
-11
View File
@@ -58,23 +58,12 @@ struct freelist_head {
#endif
};
char * nnew(void);
#include "error.h"
/***********************************************/
/* space allocation macros with error package: */
/***********************************************/
extern SC_EXPRESS_EXPORT int yylineno;
/** CALLOC grabs and initializes to all 0s space for the indicated
* number of instances of the indicated type */
#define CALLOC(ptr, num, type) \
if (((ptr) = (type*)calloc((num), (unsigned)sizeof(type)))==NULL) { \
fprintf(stderr,"fedex: out of space");\
} else {}
SC_EXPRESS_EXPORT void _ALLOCinitialize( void );
SC_EXPRESS_EXPORT void ALLOCinitialize( struct freelist_head * flh, unsigned int size, int alloc1, int alloc2 );
SC_EXPRESS_EXPORT void ALLOC_destroy( struct freelist_head *, Freelist * );
+4 -6
View File
@@ -71,7 +71,7 @@
*
*/
#include "config.h"
#include <sc_cf.h>
#include <sc_export.h>
#include <stdio.h>
@@ -82,7 +82,7 @@
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# include <stdbool.h>
# include <sc_stdbool.h>
#endif
#if defined(_MSC_VER) && (_MSC_VER < 1900) && !defined(__cplusplus)
@@ -93,10 +93,8 @@
/* function pointer types */
/**************************/
typedef void ( *voidFuncptr )(void);
typedef int ( *intFuncptr )(void);
typedef void ( *voidFuncptr )();
typedef int ( *intFuncptr )();
#endif /* BASIC_H */
+6 -17
View File
@@ -56,7 +56,7 @@
/************/
typedef struct Hash_Table_ * Dictionary;
typedef HashEntry DictionaryEntry;
typedef struct Hash_Iterator_ DictionaryEntry;
/****************/
/* modules used */
@@ -71,27 +71,15 @@ typedef HashEntry DictionaryEntry;
/********************/
/* global variables */
/********************/
/*TODO: surely this is not a good thing?! */
extern SC_EXPRESS_EXPORT char DICT_type; /**< set as a side-effect of DICT lookup routines to type of object found */
/*******************************/
/* macro function definitions */
/*******************************/
#define DICTcreate(estimated_max_size) HASHcreate(estimated_max_size)
/** should really can DICTdo_init and rename do_type_init to do_init! */
#define DICTdo_init(dict,de) HASHlistinit((dict),(de))
#define DICTdo_type_init(dict,de,t) HASHlistinit_by_type((dict),(de),(t))
#define DICTdo_end(hash_entry) HASHlistend(hash_entry)
/** modify dictionary entry in-place */
#define DICTchange(e,obj,sym,typ) { \
(e)->data = (obj); \
(e)->symbol = (sym); \
(e)->type = (typ); \
}
#define DICTchange_type(e,typ) (e)->type = (typ)
#define DICTcreate(x) HASHcreate()
#define DICTdo_init(dict,de,t) HASHdo_init((dict),(de),(t))
/***********************/
/* function prototypes */
@@ -100,8 +88,9 @@ extern SC_EXPRESS_EXPORT char DICT_type; /**< set as a side-effect of DICT look
extern SC_EXPRESS_EXPORT void DICTinitialize( void );
extern SC_EXPRESS_EXPORT void DICTcleanup( void );
extern SC_EXPRESS_EXPORT int DICTdefine( Dictionary, char *, void *, Symbol *, char );
extern SC_EXPRESS_EXPORT int DICT_define( Dictionary, char *, void *, Symbol *, char );
extern SC_EXPRESS_EXPORT int DICTdefine_enum( Dictionary, char *, void *, Symbol *, char );
extern SC_EXPRESS_EXPORT void DICTundefine( Dictionary, char * );
/* TODO: could DICTlookup be implemented more generically using function pointers? */
extern SC_EXPRESS_EXPORT void * DICTlookup( Dictionary, char * );
extern SC_EXPRESS_EXPORT void * DICTlookup_symbol( Dictionary, char *, Symbol ** );
extern SC_EXPRESS_EXPORT void * DICTdo( DictionaryEntry * );
+3 -3
View File
@@ -144,11 +144,11 @@ extern SC_EXPRESS_EXPORT struct Scope_ * ENTITYcreate( struct Symbol_ * );
extern SC_EXPRESS_EXPORT void ENTITYinitialize( void );
extern SC_EXPRESS_EXPORT void ENTITYadd_attribute( struct Scope_ *, struct Variable_ * );
extern SC_EXPRESS_EXPORT struct Scope_ * ENTITYcopy( struct Scope_ * );
extern SC_EXPRESS_EXPORT Entity ENTITYfind_inherited_entity( struct Scope_ *, char *, int );
extern SC_EXPRESS_EXPORT Variable ENTITYfind_inherited_attribute( struct Scope_ *, char *, struct Symbol_ ** );
extern SC_EXPRESS_EXPORT Entity ENTITYfind_inherited_entity( struct Scope_ *, const char *, int );
extern SC_EXPRESS_EXPORT Symbol *ENTITYfind_inherited_attribute( struct Scope_ *, const char *, struct Symbol_ ** );
extern SC_EXPRESS_EXPORT Variable ENTITYresolve_attr_ref( Entity, Symbol *, Symbol * );
extern SC_EXPRESS_EXPORT bool ENTITYhas_immediate_supertype( Entity, Entity );
extern SC_EXPRESS_EXPORT Variable ENTITYget_named_attribute( Entity, char * );
extern SC_EXPRESS_EXPORT Variable ENTITYget_named_attribute( Entity, const char * );
extern SC_EXPRESS_EXPORT Linked_List ENTITYget_all_attributes( Entity );
extern SC_EXPRESS_EXPORT bool ENTITYhas_supertype( Entity, Entity );
extern SC_EXPRESS_EXPORT void ENTITYadd_instance( Entity, void *);
+2 -2
View File
@@ -225,7 +225,7 @@ extern SC_EXPRESS_EXPORT void ERRORset_all_warnings( bool );
extern SC_EXPRESS_EXPORT void ERRORsafe( jmp_buf env );
extern SC_EXPRESS_EXPORT void ERRORunsafe( void );
extern SC_EXPRESS_EXPORT char * ERRORget_warnings_help(const char* prefix, const char *eol);
extern SC_EXPRESS_EXPORT bool ERRORis_enabled(enum ErrorCode errnum);
extern char * ERRORget_warnings_help(const char* prefix, const char *eol);
extern bool ERRORis_enabled(enum ErrorCode errnum);
#endif /* ERROR_H */
-1
View File
@@ -108,7 +108,6 @@ extern SC_EXPRESS_EXPORT char * KW_SUPERTYPE;
extern SC_EXPRESS_EXPORT char * KW_TAN;
extern SC_EXPRESS_EXPORT char * KW_THEN;
extern SC_EXPRESS_EXPORT char * KW_TO;
extern SC_EXPRESS_EXPORT char * KW_TREAT;
extern SC_EXPRESS_EXPORT char * KW_TRUE;
extern SC_EXPRESS_EXPORT char * KW_TYPE;
extern SC_EXPRESS_EXPORT char * KW_TYPEOF;
+6
View File
@@ -128,6 +128,7 @@ typedef char * Binary;
/** these represent a different way of selecting classes of objects
* these are particularly useful when looking for multiple types concurrently */
#define OBJ_TYPE_BITS 0x1
#define OBJ_ENTITY_BITS 0x2
#define OBJ_FUNCTION_BITS 0x4
@@ -138,6 +139,10 @@ typedef char * Binary;
#define OBJ_SCHEMA_BITS 0x80
#define OBJ_VARIABLE_BITS 0x100
#define OBJ_WHERE_BITS 0x200
#define OBJ_ALIAS_BITS 0x400
#define OBJ_REPEAT_BITS 0x800
#define OBJ_QUERY_BITS 0x1000
#define OBJ_ANYTHING_BITS 0x0fffffff
#define OBJ_UNFINDABLE_BITS 0x10000000 /**< should never be found */
@@ -148,6 +153,7 @@ typedef char * Binary;
/* OBJ_UNUSED should die, but until it does, allow it to work */
#define OBJ_UNUSED_BITS OBJ_UNFINDABLE_BITS
#define OBJ_DOCROOT_BITS OBJ_UNFINDABLE_BITS
#endif /*EXPRESS_BASIC_H*/
+1 -1
View File
@@ -83,7 +83,7 @@ typedef enum {
OP_MINUS, OP_MOD, OP_NEGATE,
OP_NOT, OP_NOT_EQUAL, OP_OR,
OP_PLUS, OP_REAL_DIV, OP_SUBCOMPONENT,
OP_TIMES, OP_TREAT, OP_XOR, OP_UNKNOWN,
OP_TIMES, OP_XOR, OP_UNKNOWN,
OP_LAST /**< must be last - used only to size tables */
} Op_Code;
+1 -2
View File
@@ -62,7 +62,6 @@
#include "alg.h"
#include "schema.h"
#include "lexact.h"
#include "dict.h"
/************/
/* typedefs */
@@ -102,7 +101,7 @@ extern char EXPRESSgetopt_options[]; /* initialized elsewhere */
extern SC_EXPRESS_EXPORT int ( *EXPRESSgetopt )( int, char * );
extern SC_EXPRESS_EXPORT bool EXPRESSignore_duplicate_schemas;
extern SC_EXPRESS_EXPORT Dictionary EXPRESSbuiltins; /* procedures/functions */
extern SC_EXPRESS_EXPORT Hash_Table EXPRESSbuiltins; /* procedures/functions */
extern SC_EXPRESS_EXPORT struct Scope_ * FUNC_NVL;
extern SC_EXPRESS_EXPORT struct Scope_ * FUNC_USEDIN;
+1 -3
View File
@@ -1,8 +1,6 @@
#ifndef __FACTORY_H_
#define __FACTORY_H_
#include "sc_export.h"
SC_EXPRESS_EXPORT void FACTORYinitialize(void);
void FACTORYinitialize();
#endif /* __FACTORY_H_ */
+31 -92
View File
@@ -80,28 +80,10 @@
*
*/
#include "basic.h" /* get basic definitions */
#include "sc_export.h"
/*************/
/* constants */
/*************/
#define HASH_NULL (Hash_Table)NULL
#define SEGMENT_SIZE 256
#define SEGMENT_SIZE_SHIFT 8 /**< log2(SEGMENT_SIZE) */
#define DIRECTORY_SIZE 256
#define DIRECTORY_SIZE_SHIFT 8 /**< log2(DIRECTORY_SIZE) */
#define PRIME1 37
#define PRIME2 1048583
#define MAX_LOAD_FACTOR 5
/*****************/
/* packages used */
/*****************/
#include <sc_export.h>
#include "alloc.h"
#include "expbasic.h"
#include "symbol.h"
/************/
/* typedefs */
@@ -109,96 +91,53 @@
typedef enum { HASH_FIND, HASH_INSERT, HASH_DELETE } Action;
typedef unsigned long Address;
/****************/
/* abstractions */
/****************/
typedef struct Element_ {
char * key;
char * data;
struct Element_ * next;
Symbol * symbol; /**< for debugging hash conflicts */
char type; /**< user-supplied type */
} * Element;
typedef Symbol **Segment;
typedef Element * Segment;
typedef struct Hash_Table_ {
#if 0
int in_use; /**< If someone is traversing the hash table */
#endif
unsigned int p; /**< Next bucket to be split */
unsigned int maxp; /**< upper bound on p during expansion */
struct Hash_Table_ {
unsigned int p; /**< Next bucket to be split */
unsigned int maxp; /**< upper bound on p during expansion */
unsigned int KeyCount; /**< current # keys */
unsigned int SegmentCount; /**< current # segments */
unsigned int MinLoadFactor;
unsigned int MaxLoadFactor;
Segment Directory[DIRECTORY_SIZE];
} * Hash_Table;
Segment *Directory;
unsigned int DirectorySize;
unsigned int SegmentSize;
#ifdef HASH_DEBUG
unsigned int HashCollisions;
#endif
};
typedef struct {
unsigned int i; /**< segment index (i think) */
unsigned int j; /**< key index in segment (ditto) */
Element p; /**< usually the next element to be returned */
typedef struct Hash_Table_ *Hash_Table;
struct Hash_Iterator_ {
Hash_Table table;
unsigned int hash;
Symbol *p;
char type;
Element e; /**< originally thought of as a place for
* the caller of HASHlist to temporarily stash the return value
* to allow the caller (i.e., DICTdo) to be macroized, but now
* conveniently used by HASHlist, which both stores the ultimate
* value here as well as returns it via the return value of HASHlist
*/
} HashEntry;
};
typedef struct Hash_Iterator_ Hash_Iterator;
/********************/
/* global variables */
/********************/
extern SC_EXPRESS_EXPORT struct freelist_head HASH_Table_fl;
extern SC_EXPRESS_EXPORT struct freelist_head HASH_Element_fl;
/******************************/
/* macro function definitions */
/******************************/
/*
** Fast arithmetic, relying on powers of 2
*/
/**
The centerline compiler was having problems with MUL and DIV. Where DIV
was called like this DIV(NewAddress, SEGMENT_SIZE) it is now being called like
DIV(NewAddress, SEGMENT_SIZE_SHIFT). The compiler was mentioning some kind of
problem with ##. I wonder if maybe the precompiler was expanding SEGMENT_SIZE
(which is also defined as a macro) before turning it into SEGMENT_SIZE_SHIFT.
SEGMENT_SIZE and DIRECTORY_SIZE were used to call these macros. They are both
defined to be 8 though so it seems these are always being used the same way.
This change only seems to have affected hash.h and hash.c
*/
/* #define MUL(x,y) ((x) << (y##_SHIFT)) */
#define MUL(x,y) ((x) << (y))
/* #define DIV(x,y) ((x) >> (y##_SHIFT)) */
#define DIV(x,y) ((x) >> (y))
#define MOD(x,y) ((x) & ((y)-1))
#define HASH_Table_new() (struct Hash_Table_ *)ALLOC_new(&HASH_Table_fl)
#define HASH_Table_destroy(x) ALLOC_destroy(&HASH_Table_fl,(Freelist *)x)
#define HASH_Element_new() (struct Element_ *)ALLOC_new(&HASH_Element_fl)
#define HASH_Element_destroy(x) ALLOC_destroy(&HASH_Element_fl,(Freelist *)(char *)x)
/***********************/
/* function prototypes */
/***********************/
extern SC_EXPRESS_EXPORT void HASHinitialize( void );
extern SC_EXPRESS_EXPORT Hash_Table HASHcreate( unsigned );
extern SC_EXPRESS_EXPORT Hash_Table HASHcopy( Hash_Table );
extern SC_EXPRESS_EXPORT void HASHdestroy( Hash_Table );
extern SC_EXPRESS_EXPORT Element HASHsearch( Hash_Table, Element, Action );
extern SC_EXPRESS_EXPORT void HASHlistinit( Hash_Table, HashEntry * );
extern SC_EXPRESS_EXPORT void HASHlistinit_by_type( Hash_Table, HashEntry *, char );
extern SC_EXPRESS_EXPORT Element HASHlist( HashEntry * );
extern SC_EXPRESS_EXPORT void HASHinitialize( void );
extern SC_EXPRESS_EXPORT Hash_Table HASHcreate( void );
extern SC_EXPRESS_EXPORT Hash_Table HASHcopy( Hash_Table );
extern SC_EXPRESS_EXPORT void HASHdestroy( Hash_Table );
extern SC_EXPRESS_EXPORT Symbol * HASHsearch( Hash_Table, Symbol, Action );
extern SC_EXPRESS_EXPORT void HASHdelete( Hash_Table, Symbol * );
extern SC_EXPRESS_EXPORT void HASHdo_init( Hash_Table, Hash_Iterator *, char );
extern SC_EXPRESS_EXPORT Symbol * HASHdo( Hash_Iterator * );
#endif /*HASH_H*/
#endif /* HASH_H */
+1 -3
View File
@@ -1,8 +1,6 @@
#ifndef __MEMORY_H
#define __MEMORY_H
#include "sc_export.h"
SC_EXPRESS_EXPORT void MEMORYinitialize(void);
void MEMORYinitialize();
#endif // __MEMORY_H
+1 -1
View File
@@ -68,7 +68,7 @@
/***************************/
struct Object {
struct Symbol_ * ( *get_symbol )( void * );
struct Symbol_ * ( *get_symbol )();
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 */
};
-19
View File
@@ -47,25 +47,6 @@
extern SC_EXPRESS_EXPORT int print_objects_while_running;
/*************************/
/* Refinement structures */
/*************************/
/* Maximum length for type name lookups */
#define MAX_TYPE_NAME_LENGTH 512
/** Structure to track type refinements from TYPEOF guards in AND expressions */
typedef struct Refinement_ {
Variable variable; /**< the variable being refined */
Type refined_type; /**< the narrowed type */
struct Refinement_ *next; /**< next refinement in the chain */
} *Refinement;
/** Context for passing refinements through expression resolution */
typedef struct RefinementContext_ {
Refinement refinements; /**< linked list of active refinements */
} *RefinementContext;
/* macros */
/* cheaper doing the check here, then inside the function call. Return */
+8
View File
@@ -0,0 +1,8 @@
#ifndef __SC_FWD_H
#define __SC_FWD_H
struct Symbol_;
typedef struct Symbol_ Symbol;
#endif /* __SC_FWD_H */
+4 -4
View File
@@ -61,8 +61,8 @@
/****************/
#include "alg.h"
#include "dict.h"
#include "entity.h"
#include "hash.h"
#include "linklist.h"
/***************************/
@@ -91,8 +91,8 @@ struct Schema_ {
* dictionaries into which are entered renames for each specific
* object specified in a rename clause (even if it uses the same
* name */
Dictionary refdict;
Dictionary usedict;
Hash_Table refdict;
Hash_Table usedict;
Linked_List use_schemas; /**< lists of schemas that are fully use'd
* entries can be 0 if schemas weren't found during RENAMEresolve */
@@ -133,7 +133,7 @@ extern SC_EXPRESS_EXPORT int __SCOPE_search_id;
/* function prototypes */
/***********************/
extern SC_EXPRESS_EXPORT Variable VARfind( Scope, char *, int );
extern SC_EXPRESS_EXPORT Symbol * VARfind( Scope, const char * );
extern SC_EXPRESS_EXPORT Schema SCHEMAcreate( void );
extern SC_EXPRESS_EXPORT void SCHEMAinitialize( void );
extern SC_EXPRESS_EXPORT void SCHEMAadd_use( Schema, Symbol *, Symbol *, Symbol * );
+8 -8
View File
@@ -50,6 +50,7 @@
/****************/
#include <sc_export.h>
#include "hash.h"
#include "type.h"
#include "variable.h"
#include "entity.h"
@@ -62,7 +63,6 @@
/*****************/
#include "expbasic.h" /* get basic definitions */
#include "dict.h"
#include "symbol.h"
/***************************/
@@ -82,7 +82,7 @@ struct Scope_ {
char type; /* see above */
ClientData clientData; /**< user may use this for any purpose */
int search_id; /**< key to avoid searching this scope twice */
Dictionary symbol_table, enum_table;
Hash_Table symbol_table, enum_table;
struct Scope_ * superscope;
union {
struct Procedure_ * proc;
@@ -115,16 +115,16 @@ struct Scope_ {
#define SCOPEput_clientData(s,d) ((s)->clientData = (d))
#define SCOPEdo_types(s,t,de) DICTdo_type_init(s->symbol_table,&de,OBJ_TYPE);{\
#define SCOPEdo_types(s,t,de) DICTdo_init(s->symbol_table,&de,OBJ_TYPE);{\
Type t; \
while (0 != (t = (Type)DICTdo(&de))) {
#define SCOPEdo_entities(s,t,de) DICTdo_type_init(s->symbol_table,&de,OBJ_ENTITY); { \
#define SCOPEdo_entities(s,t,de) DICTdo_init(s->symbol_table,&de,OBJ_ENTITY); { \
Entity t; \
while (0 != (t = (Entity)DICTdo(&de))) {
#define SCOPEdo_functions(s,t,de) DICTdo_type_init(s->symbol_table,&de,OBJ_FUNCTION); { \
#define SCOPEdo_functions(s,t,de) DICTdo_init(s->symbol_table,&de,OBJ_FUNCTION); { \
Entity t; \
while (0 != (t = (Entity)DICTdo(&de))) {
#define SCOPEdo_rules(s,t,de) DICTdo_type_init(s->symbol_table,&de,OBJ_RULE); { \
#define SCOPEdo_rules(s,t,de) DICTdo_init(s->symbol_table,&de,OBJ_RULE); { \
Entity t; \
while (0 != (t = (Entity)DICTdo(&de))) {
@@ -138,12 +138,12 @@ extern SC_EXPRESS_EXPORT struct Symbol_ * SCOPE_get_symbol( void * );
extern SC_EXPRESS_EXPORT void SCOPE_get_entities( Scope, Linked_List );
extern SC_EXPRESS_EXPORT Linked_List SCOPEget_entities( Scope );
extern SC_EXPRESS_EXPORT Linked_List SCOPEget_entities_superclass_order( Scope );
extern SC_EXPRESS_EXPORT void * SCOPEfind( Scope, char *, int );
extern SC_EXPRESS_EXPORT Symbol * SCOPEfind( Scope, const char *, int );
extern SC_EXPRESS_EXPORT void SCOPE_get_functions( Scope, Linked_List );
extern SC_EXPRESS_EXPORT Linked_List SCOPEget_functions( Scope );
extern SC_EXPRESS_EXPORT void SCOPE_get_rules( Scope, Linked_List );
extern SC_EXPRESS_EXPORT Linked_List SCOPEget_rules( Scope );
void * SCOPE_find( Scope, char *, int );
Symbol * SCOPE_find( Scope, const char *, int );
#endif /* SCOPE_H */
+16 -15
View File
@@ -43,27 +43,30 @@
/* packages used */
/*****************/
#include <sc_export.h>
#include "sc_export.h"
#include "basic.h" /* get basic definitions */
#include "alloc.h"
/************/
/* typedefs */
/************/
typedef struct Symbol_ Symbol;
/***************************/
/* hidden type definitions */
/* type definitions */
/***************************/
struct Symbol_ {
char * name;
const char * filename;
const char *name;
void *data; /* the AST for this symbol */
char type; /* the OBJ_ type, see expbasic.h */
int ref_tok; /* the lexer ref_type for this symbol */
const char *filename;
int line;
char resolved;
char resolved; /* if imported TYPE or ENTITY is unresolved */
struct Symbol_ *next; /* symbol table clashes */
};
typedef struct Symbol_ Symbol;
/****************/
/* modules used */
/****************/
@@ -78,9 +81,7 @@ extern SC_EXPRESS_EXPORT struct freelist_head SYMBOL_fl;
/* macro function definitions */
/******************************/
#define SYMBOL_new() (struct Symbol_ *)ALLOC_new(&SYMBOL_fl)
#define SYMBOL_destroy(x) ALLOC_destroy(&SYMBOL_fl,(Freelist *)x)
/* TODO: gets called from e.g. type.c, should be set by parser */
#define SYMBOLset(obj) obj->symbol.line = yylineno; \
obj->symbol.filename = current_filename
@@ -89,6 +90,6 @@ extern SC_EXPRESS_EXPORT struct freelist_head SYMBOL_fl;
/***********************/
extern SC_EXPRESS_EXPORT void SYMBOLinitialize( void );
SC_EXPRESS_EXPORT Symbol * SYMBOLcreate( char * name, int line, const char * filename );
SC_EXPRESS_EXPORT Symbol * SYMBOLcreate( char * name, int type, int ref_tok, int line, const char * filename );
#endif /* SYMBOL_H */
-5
View File
@@ -129,7 +129,6 @@ typedef enum type_enum Class;
/* modules used */
/****************/
#include "dict.h"
#include "entity.h"
#include "expr.h"
#include "scope.h"
@@ -237,9 +236,6 @@ extern SC_EXPRESS_EXPORT struct freelist_head TYPEBODY_fl;
#define TYPEis_oneof(t) ((t)->u.type->body->type == oneof_)
#define TYPEis_entity(t) ((t)->u.type->body->type == entity_)
#define TYPEis_enumeration(t) ((t)->u.type->body->type == enumeration_)
/** Shallow aggregate check - returns true if type has a base (characteristic of aggregates).
* Does NOT follow type definition chains. For deep unwrapping through typedef chains,
* use TYPEget_nonaggregate_base_type() or TYPEget_aggregate_base(). */
#define TYPEis_aggregate(t) ((t)->u.type->body->base)
#define TYPEis_aggregate_raw(t) ((t)->u.type->body->type == aggregate_)
#define TYPEis_array(t) ((t)->u.type->body->type == array_)
@@ -306,7 +302,6 @@ extern SC_EXPRESS_EXPORT void TYPEcleanup( void );
extern SC_EXPRESS_EXPORT bool TYPEinherits_from( Type, enum type_enum );
extern SC_EXPRESS_EXPORT Type TYPEget_nonaggregate_base_type( Type );
extern SC_EXPRESS_EXPORT Type TYPEget_aggregate_base( Type );
extern SC_EXPRESS_EXPORT Type TYPEcreate_user_defined_type( Type, Scope, struct Symbol_ * );
extern SC_EXPRESS_EXPORT Type TYPEcreate_user_defined_tag( Type, Scope, struct Symbol_ * );
+1 -1
View File
@@ -127,6 +127,6 @@ extern SC_EXPRESS_EXPORT struct freelist_head VAR_fl;
extern SC_EXPRESS_EXPORT Variable VARcreate( Expression, Type );
extern SC_EXPRESS_EXPORT void VARinitialize( void );
extern SC_EXPRESS_EXPORT char * VARget_simple_name( Variable );
extern SC_EXPRESS_EXPORT const char * VARget_simple_name( Variable );
#endif /* VARIABLE_H */
@@ -2,7 +2,6 @@
#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
@@ -15,6 +14,7 @@
#cmakedefine HAVE_IO_H 1
#cmakedefine SC_TRACE_FPRINTF 1
#cmakedefine SC_MEMMGR_ENABLE_CHECKS 1
#cmakedefine HAVE_ABS 1
#cmakedefine HAVE_MEMCPY 1
+43
View File
@@ -0,0 +1,43 @@
#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_*/
+1 -1
View File
@@ -15,7 +15,7 @@ BUILDNAME:STRING=${CTEST_BUILD_NAME}
SC_ENABLE_TESTING:BOOL=ON
SC_ENABLE_COVERAGE:BOOL=ON
SC_BUILD_SCHEMAS:STRING=ALL
CMAKE_BUILD_TYPE:STRING=Debug
SC_BUILD_TYPE:STRING=Debug
")
set(LCOV_OUT "${CTEST_BINARY_DIRECTORY}/lcov_html")
-10
View File
@@ -1,10 +0,0 @@
#!/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" {} \;
+330
View File
@@ -0,0 +1,330 @@
//summarize MSVC errors from an appveyor log
// compile with 'go build summarize-appveyor-log.go'
// takes 0 or 1 args; with 0, gets log from latest
// build. with 1, uses that file as raw json-like log
package main
import (
"bufio"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"regexp"
"sort"
"strings"
)
const (
headerKey = "Authorization"
headerVal = "Bearer %s"
projUrl = "https://ci.appveyor.com/api/projects/mpictor/stepcode"
//"https://ci.appveyor.com/api/buildjobs/2rjxdv1rnb8jcg8y/log"
logUrl = "https://ci.appveyor.com/api/buildjobs/%s/log"
consoleUrl = "https://ci.appveyor.com/api/buildjobs/%s/console"
)
func main() {
var rawlog io.ReadCloser
var build string
var err error
if len(os.Args) == 2 {
rawlog, build, err = processArgv()
} else {
rawlog, build, err = getLog()
}
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
return
}
defer rawlog.Close()
log := decodeConsole(rawlog)
warns, errs := countMessages(log)
fi, err := os.Create(fmt.Sprintf("appveyor-%s.smy", build))
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
return
}
printMessages("error", errs, fi)
printMessages("warning", warns, fi)
fmt.Printf("done\n")
}
/* categorizes warnings and errors based upon the MSVC message number (i.e. C4244)
* the regex will match lines like
c:\projects\stepcode\src\base\sc_benchmark.h(45): warning C4251: 'benchmark::descr' : class 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>' needs to have dll-interface to be used by clients of class 'benchmark' [C:\projects\STEPcode\build\src\base\base.vcxproj]
[00:03:48] C:\projects\STEPcode\src\base\sc_benchmark.cc(61): warning C4244: '=' : conversion from 'SIZE_T' to 'long', possible loss of data [C:\projects\STEPcode\build\src\base\base.vcxproj]*
*/
func countMessages(log []string) (warns, errs map[string][]string) {
warns = make(map[string][]string)
errs = make(map[string][]string)
fname := " *(.*)" // $1
fline := `(?:\((\d+)\)| ): ` // $2 - either line number in parenthesis or a space, followed by a colon
msgNr := `([A-Z]+\d+): ` // $3 - C4251, LNK2005, etc
msgTxt := `([^\[]*) ` // $4
tail := `\[[^\[\]]*\]`
warnRe := regexp.MustCompile(fname + fline + `warning ` + msgNr + msgTxt + tail)
errRe := regexp.MustCompile(fname + fline + `(?:fatal )?error ` + msgNr + msgTxt + tail)
for _, line := range log {
if warnRe.MatchString(line) {
key := warnRe.ReplaceAllString(line, "$3")
path := strings.ToLower(warnRe.ReplaceAllString(line, "$1:$2"))
arr := warns[key]
if arr == nil {
arr = make([]string, 5)
//detailed text as first string in array
text := warnRe.ReplaceAllString(line, "$4")
arr[0] = fmt.Sprintf("%s", text)
}
//eliminate duplicates
match := false
for _, l := range arr {
if l == path {
match = true
}
}
if !match {
warns[key] = append(arr, path)
}
} else if errRe.MatchString(line) {
key := errRe.ReplaceAllString(line, "$3")
path := strings.ToLower(errRe.ReplaceAllString(line, "$1:$2"))
arr := errs[key]
if arr == nil {
arr = make([]string, 5)
//detailed text as first string in array
text := errRe.ReplaceAllString(line, "$4")
arr[0] = fmt.Sprintf("%s", text)
}
//eliminate duplicates
match := false
for _, l := range arr {
if l == path {
match = true
}
}
if !match {
errs[key] = append(arr, path)
}
}
}
return
}
func printMessages(typ string, m map[string][]string, w io.Writer) {
//sort keys
keys := make([]string, 0, len(m))
for key := range m {
keys = append(keys, key)
}
sort.Strings(keys)
for _, k := range keys {
for i, l := range m[k] {
//first string is an example, not a location
if i == 0 {
fmt.Fprintf(w, "%s %s (i.e. \"%s\")\n", typ, k, l)
} else if len(l) > 1 { //not sure where blank lines are coming from...
fmt.Fprintf(w, " >> %s\n", l)
}
}
}
}
//structs from http://json2struct.mervine.net/
//{"values":[{"i":0,"t":"Specify a project or solution file. The directory does not contain a project or solution file.\r\n","dt":"00:00:04","bg":12,"fg":15}]}
type AppVeyorConsoleLines struct {
Values []struct {
I int `json:"i"`
Text string `json:"t"`
DateTime string `json:"dt"`
BgColor int `json:"bg"`
FgColor int `json:"fg"`
}
}
type AppVeyorBuild struct {
Build struct {
/*BuildNumber int `json:"buildNumber"`*/
Version string `json:"version"`
Jobs []struct {
JobID string `json:"jobId"`
} `json:"jobs"`
} `json:"build"`
}
func splitAppend(log *[]string, blob string) {
//blob = strings.Replace(blob,"\r\n", "\n",-1)
blob = strings.Replace(blob, "\\", "/", -1)
r := strings.NewReader(blob)
unwrapScanner := bufio.NewScanner(r)
for unwrapScanner.Scan() {
txt := unwrapScanner.Text()
//fmt.Printf("%s\n", txt)
*log = append(*log, txt)
}
}
//calculate length of string without escape chars
// func escapeLen(s string)(l int) {
// //s = strings.Replace(s,"\\\\", "/",-1)
// s = strings.Replace(s,"\\\"", "",-1)
// s = strings.Replace(s,"\r\n", "RN",-1)
// return len(s)
// }
//decode the almost-JSON console data from appveyor
func decodeConsole(r io.Reader) (log []string) {
wrapper := Wrap(r)
dec := json.NewDecoder(wrapper)
var consoleLines AppVeyorConsoleLines
var err error
var txtBlob string
err = dec.Decode(&consoleLines)
if err == io.EOF {
err = nil
}
if err == nil {
for _, l := range consoleLines.Values {
txtBlob += l.Text
//el := escapeLen(l.Text)
//something inserts newlines at 229 chars (+\n\r == 231) (found in CMake output)
lenTwoThreeOne := len(l.Text) == 231
if lenTwoThreeOne {
txtBlob = strings.TrimSuffix(txtBlob, "\r\n")
}
//something else starts new log lines at 1024 chars without inserting newlines (found in CTest error output)
if len(l.Text) != 1024 && !lenTwoThreeOne {
//fmt.Printf("sa for l %d, el %d\n", len(l.Text),el)
splitAppend(&log, txtBlob)
txtBlob = ""
}
}
} else {
fmt.Printf("decode err %s\n", err)
}
if len(txtBlob) > 0 {
splitAppend(&log, txtBlob)
}
return
}
func processArgv() (log io.ReadCloser, build string, err error) {
fname := os.Args[1]
if len(fname) < 14 {
err = fmt.Errorf("Name arg '%s' too short. Run as '%s appveyor-NNN.log'", fname, os.Args[0])
return
}
buildRe := regexp.MustCompile(`appveyor-(.+).log`)
build = buildRe.ReplaceAllString(fname, "$1")
if len(build) == 0 {
err = fmt.Errorf("No build id in %s", fname)
return
}
log, err = os.Open(fname)
return
}
func getLog() (log io.ReadCloser, build string, err error) {
client := &http.Client{}
req, err := http.NewRequest("GET", projUrl, nil)
if err != nil {
return
}
apikey := os.Getenv("APPVEYOR_API_KEY")
//api key isn't necessary for read-only queries on public projects
if len(apikey) > 0 {
req.Header.Add(headerKey, fmt.Sprintf(headerVal, apikey))
} //else {
// fmt.Printf("Env var APPVEYOR_API_KEY is not set.")
//}
resp, err := client.Do(req)
if err != nil {
return
}
build, job := decodeProjInfo(resp.Body)
fmt.Printf("build #%s, jobId %s\n", build, job)
resp, err = http.Get(fmt.Sprintf(consoleUrl, job))
if err != nil {
return
}
logName := fmt.Sprintf("appveyor-%s.log", build)
fi, err := os.Create(logName)
if err != nil {
return
}
_, err = io.Copy(fi, resp.Body)
if err != nil {
return
}
log, err = os.Open(logName)
if err != nil {
log = nil
}
return
}
func decodeProjInfo(r io.Reader) (vers string, job string) {
dec := json.NewDecoder(r)
var av AppVeyorBuild
err := dec.Decode(&av)
if err != io.EOF && err != nil {
fmt.Printf("err %s\n", err)
return
}
if len(av.Build.Jobs) != 1 {
return
}
vers = av.Build.Version
job = av.Build.Jobs[0].JobID
return
}
//wrap a reader, modifying content to make the json decoder happy
//only tested with data from appveyor console
type jsonWrapper struct {
source io.Reader
begin bool
end bool
}
func Wrap(r io.Reader) *jsonWrapper {
return &jsonWrapper{
source: r,
begin: true,
}
}
// func nonNeg(n int) (int) {
// if n < 0 {
// return 0
// }
// return n
// }
func (w *jsonWrapper) Read(p []byte) (n int, err error) {
if w.end {
return 0, io.EOF
}
if w.begin {
w.begin = false
n = copy(p, []byte(`{"values":[`))
}
m, err := w.source.Read(p[n:])
n += m
if err == io.EOF {
w.end = true
if n < len(p) {
n = copy(p, []byte(`{"dummy":"data"}]}`))
} else {
err = fmt.Errorf("No room to terminate JSON struct with '}'\n")
}
}
return
}
// kate: indent-width 8; space-indent off; replace-tabs off; replace-tabs-save off; replace-trailing-space-save on; remove-trailing-space on; tab-intent on; tab-width 8; show-tabs off;
+1 -1
View File
@@ -9,7 +9,7 @@ set(CTEST_INITIAL_CACHE "
SITE:STRING=${CTEST_SITE}
BUILDNAME:STRING=${CTEST_BUILD_NAME}
SC_ENABLE_TESTING:BOOL=ON
CMAKE_BUILD_TYPE:STRING=Debug
SC_BUILD_TYPE:STRING=Debug
")
+16
View File
@@ -0,0 +1,16 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
if (${SC_MEMMGR_ENABLE_CHECKS})
add_definitions(-DSC_MEMMGR_ENABLE_CHECKS)
endif()
SC_ADDLIB(auxlib STATIC SOURCES bstrlib.c)
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+3137
View File
File diff suppressed because it is too large Load Diff
+321
View File
@@ -0,0 +1,321 @@
/*
* This source file is part of the bstring string library. This code was
* written by Paul Hsieh in 2002-2015, and is covered by the BSD open source
* license and the GPL. Refer to the accompanying documentation for details
* on usage and license.
*/
/*
* bstrlib.h
*
* This file is the interface for the core bstring functions.
*/
#ifndef BSTRLIB_INCLUDE
#define BSTRLIB_INCLUDE
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP)
# if defined (__TURBOC__) && !defined (__BORLANDC__)
# define BSTRLIB_NOVSNP
# endif
#endif
#define BSTR_ERR (-1)
#define BSTR_OK (0)
#define BSTR_BS_BUFF_LENGTH_GET (0)
typedef struct tagbstring * bstring;
typedef const struct tagbstring * const_bstring;
/* Version */
#define BSTR_VER_MAJOR 1
#define BSTR_VER_MINOR 0
#define BSTR_VER_UPDATE 0
/* Copy functions */
#define cstr2bstr bfromcstr
extern bstring bfromcstr (const char * str);
extern bstring bfromcstralloc (int mlen, const char * str);
extern bstring bfromcstrrangealloc (int minl, int maxl, const char* str);
extern bstring blk2bstr (const void * blk, int len);
extern char * bstr2cstr (const_bstring s, char z);
extern int bcstrfree (char * s);
extern bstring bstrcpy (const_bstring b1);
extern int bassign (bstring a, const_bstring b);
extern int bassignmidstr (bstring a, const_bstring b, int left, int len);
extern int bassigncstr (bstring a, const char * str);
extern int bassignblk (bstring a, const void * s, int len);
/* Destroy function */
extern int bdestroy (bstring b);
/* Space allocation hinting functions */
extern int balloc (bstring s, int len);
extern int ballocmin (bstring b, int len);
/* Substring extraction */
extern bstring bmidstr (const_bstring b, int left, int len);
/* Various standard manipulations */
extern int bconcat (bstring b0, const_bstring b1);
extern int bconchar (bstring b0, char c);
extern int bcatcstr (bstring b, const char * s);
extern int bcatblk (bstring b, const void * s, int len);
extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill);
extern int binsertblk (bstring s1, int pos, const void * s2, int len, unsigned char fill);
extern int binsertch (bstring s1, int pos, int len, unsigned char fill);
extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill);
extern int bdelete (bstring s1, int pos, int len);
extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill);
extern int btrunc (bstring b, int n);
/* Scan/search functions */
extern int bstricmp (const_bstring b0, const_bstring b1);
extern int bstrnicmp (const_bstring b0, const_bstring b1, int n);
extern int biseqcaseless (const_bstring b0, const_bstring b1);
extern int biseqcaselessblk (const_bstring b, const void * blk, int len);
extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len);
extern int biseq (const_bstring b0, const_bstring b1);
extern int biseqblk (const_bstring b, const void * blk, int len);
extern int bisstemeqblk (const_bstring b0, const void * blk, int len);
extern int biseqcstr (const_bstring b, const char * s);
extern int biseqcstrcaseless (const_bstring b, const char * s);
extern int bstrcmp (const_bstring b0, const_bstring b1);
extern int bstrncmp (const_bstring b0, const_bstring b1, int n);
extern int binstr (const_bstring s1, int pos, const_bstring s2);
extern int binstrr (const_bstring s1, int pos, const_bstring s2);
extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2);
extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2);
extern int bstrchrp (const_bstring b, int c, int pos);
extern int bstrrchrp (const_bstring b, int c, int pos);
#define bstrchr(b,c) bstrchrp ((b), (c), 0)
#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1)
extern int binchr (const_bstring b0, int pos, const_bstring b1);
extern int binchrr (const_bstring b0, int pos, const_bstring b1);
extern int bninchr (const_bstring b0, int pos, const_bstring b1);
extern int bninchrr (const_bstring b0, int pos, const_bstring b1);
extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos);
extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos);
/* List of string container functions */
struct bstrList {
int qty, mlen;
bstring * entry;
};
extern struct bstrList * bstrListCreate (void);
extern int bstrListDestroy (struct bstrList * sl);
extern int bstrListAlloc (struct bstrList * sl, int msz);
extern int bstrListAllocMin (struct bstrList * sl, int msz);
/* String split and join functions */
extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar);
extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr);
extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr);
extern bstring bjoin (const struct bstrList * bl, const_bstring sep);
extern bstring bjoinblk (const struct bstrList * bl, const void * s, int len);
extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos,
int (* cb) (void * parm, int ofs, int len), void * parm);
extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos,
int (* cb) (void * parm, int ofs, int len), void * parm);
extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos,
int (* cb) (void * parm, int ofs, int len), void * parm);
/* Miscellaneous functions */
extern int bpattern (bstring b, int len);
extern int btoupper (bstring b);
extern int btolower (bstring b);
extern int bltrimws (bstring b);
extern int brtrimws (bstring b);
extern int btrimws (bstring b);
#if !defined (BSTRLIB_NOVSNP)
extern bstring bformat (const char * fmt, ...);
extern int bformata (bstring b, const char * fmt, ...);
extern int bassignformat (bstring b, const char * fmt, ...);
extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist);
#define bvformata(ret, b, fmt, lastarg) { \
bstring bstrtmp_b = (b); \
const char * bstrtmp_fmt = (fmt); \
int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \
for (;;) { \
va_list bstrtmp_arglist; \
va_start (bstrtmp_arglist, lastarg); \
bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \
va_end (bstrtmp_arglist); \
if (bstrtmp_r >= 0) { /* Everything went ok */ \
bstrtmp_r = BSTR_OK; \
break; \
} else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \
bstrtmp_r = BSTR_ERR; \
break; \
} \
bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \
} \
ret = bstrtmp_r; \
}
#endif
typedef int (*bNgetc) (void *parm);
typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm);
/* Input functions */
extern bstring bgets (bNgetc getcPtr, void * parm, char terminator);
extern bstring bread (bNread readPtr, void * parm);
extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator);
extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator);
extern int breada (bstring b, bNread readPtr, void * parm);
/* Stream functions */
extern struct bStream * bsopen (bNread readPtr, void * parm);
extern void * bsclose (struct bStream * s);
extern int bsbufflength (struct bStream * s, int sz);
extern int bsreadln (bstring b, struct bStream * s, char terminator);
extern int bsreadlns (bstring r, struct bStream * s, const_bstring term);
extern int bsread (bstring b, struct bStream * s, int n);
extern int bsreadlna (bstring b, struct bStream * s, char terminator);
extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term);
extern int bsreada (bstring b, struct bStream * s, int n);
extern int bsunread (struct bStream * s, const_bstring b);
extern int bspeek (bstring r, const struct bStream * s);
extern int bssplitscb (struct bStream * s, const_bstring splitStr,
int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
extern int bssplitstrcb (struct bStream * s, const_bstring splitStr,
int (* cb) (void * parm, int ofs, const_bstring entry), void * parm);
extern int bseof (const struct bStream * s);
struct tagbstring {
int mlen;
int slen;
unsigned char * data;
};
/* Accessor macros */
#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen))
#define blength(b) (blengthe ((b), 0))
#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o))
#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0))
#define bdatae(b, e) (bdataofse (b, 0, e))
#define bdata(b) (bdataofs (b, 0))
#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e))
#define bchar(b, p) bchare ((b), (p), '\0')
/* Static constant string initialization macro */
#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")}
#if defined(_MSC_VER)
# define bsStatic(q) bsStaticMlen(q,-32)
#endif
#ifndef bsStatic
# define bsStatic(q) bsStaticMlen(q,-__LINE__)
#endif
/* Static constant block parameter pair */
#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1)
#define bcatStatic(b,s) ((bcatblk)((b), bsStaticBlkParms(s)))
#define bfromStatic(s) ((blk2bstr)(bsStaticBlkParms(s)))
#define bassignStatic(b,s) ((bassignblk)((b), bsStaticBlkParms(s)))
#define binsertStatic(b,p,s,f) ((binsertblk)((b), (p), bsStaticBlkParms(s), (f)))
#define bjoinStatic(b,s) ((bjoinblk)((b), bsStaticBlkParms(s)))
#define biseqStatic(b,s) ((biseqblk)((b), bsStaticBlkParms(s)))
#define bisstemeqStatic(b,s) ((bisstemeqblk)((b), bsStaticBlkParms(s)))
#define biseqcaselessStatic(b,s) ((biseqcaselessblk)((b), bsStaticBlkParms(s)))
#define bisstemeqcaselessStatic(b,s) ((bisstemeqcaselessblk)((b), bsStaticBlkParms(s)))
/* Reference building macros */
#define cstr2tbstr btfromcstr
#define btfromcstr(t,s) { \
(t).data = (unsigned char *) (s); \
(t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \
(t).mlen = -1; \
}
#define blk2tbstr(t,s,l) { \
(t).data = (unsigned char *) (s); \
(t).slen = l; \
(t).mlen = -1; \
}
#define btfromblk(t,s,l) blk2tbstr(t,s,l)
#define bmid2tbstr(t,b,p,l) { \
const_bstring bstrtmp_s = (b); \
if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \
int bstrtmp_left = (p); \
int bstrtmp_len = (l); \
if (bstrtmp_left < 0) { \
bstrtmp_len += bstrtmp_left; \
bstrtmp_left = 0; \
} \
if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \
bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \
if (bstrtmp_len <= 0) { \
(t).data = (unsigned char *)""; \
(t).slen = 0; \
} else { \
(t).data = bstrtmp_s->data + bstrtmp_left; \
(t).slen = bstrtmp_len; \
} \
} else { \
(t).data = (unsigned char *)""; \
(t).slen = 0; \
} \
(t).mlen = -__LINE__; \
}
#define btfromblkltrimws(t,s,l) { \
int bstrtmp_idx = 0, bstrtmp_len = (l); \
unsigned char * bstrtmp_s = (s); \
if (bstrtmp_s && bstrtmp_len >= 0) { \
for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \
if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \
} \
} \
(t).data = bstrtmp_s + bstrtmp_idx; \
(t).slen = bstrtmp_len - bstrtmp_idx; \
(t).mlen = -__LINE__; \
}
#define btfromblkrtrimws(t,s,l) { \
int bstrtmp_len = (l) - 1; \
unsigned char * bstrtmp_s = (s); \
if (bstrtmp_s && bstrtmp_len >= 0) { \
for (; bstrtmp_len >= 0; bstrtmp_len--) { \
if (!isspace (bstrtmp_s[bstrtmp_len])) break; \
} \
} \
(t).data = bstrtmp_s; \
(t).slen = bstrtmp_len + 1; \
(t).mlen = -__LINE__; \
}
#define btfromblktrimws(t,s,l) { \
int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \
unsigned char * bstrtmp_s = (s); \
if (bstrtmp_s && bstrtmp_len >= 0) { \
for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \
if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \
} \
for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \
if (!isspace (bstrtmp_s[bstrtmp_len])) break; \
} \
} \
(t).data = bstrtmp_s + bstrtmp_idx; \
(t).slen = bstrtmp_len + 1 - bstrtmp_idx; \
(t).mlen = -__LINE__; \
}
/* Write protection macros */
#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; }
#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); }
#define biswriteprotected(t) ((t).mlen <= 0)
#ifdef __cplusplus
}
#endif
#endif
+73
View File
@@ -0,0 +1,73 @@
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
sc_nullptr.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($CACHE{SC_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($CACHE{SC_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_INSTALL_DIR}/stepcode/base)
# Local Variables:
# tab-width: 8
# mode: cmake
# indent-tabs-mode: t
# End:
# ex: shiftwidth=2 tabstop=8
+78
View File
@@ -0,0 +1,78 @@
cmake_minimum_required(VERSION 3.6.3)
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
+43
View File
@@ -0,0 +1,43 @@
# 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
+29
View File
@@ -0,0 +1,29 @@
#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)
+8
View File
@@ -0,0 +1,8 @@
#!/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
File diff suppressed because it is too large Load Diff
@@ -60,34 +60,11 @@
# endif
#endif
#include "cllazyfile/judy.h"
#include "judy.h"
#include <string.h>
#include <stdio.h>
/*
* Judy keys are byte-packed: adjacent slots may start at an address that is
* not suitably aligned for judyvalue. Callers are likewise permitted to
* supply byte buffers without judyvalue alignment. Copy through an aligned
* local value rather than dereferencing a cast pointer. Zero-filling any
* bytes not requested also makes partial loads deterministic.
*/
static judyvalue
judy_load_value( const unsigned char * source, unsigned int size )
{
judyvalue value = 0;
memcpy( &value, source, size );
return value;
}
static void
judy_store_value( unsigned char * destination, judyvalue value,
unsigned int size )
{
memcpy( destination, &value, size );
}
#if defined(STANDALONE) || defined(ASKITIS)
extern unsigned int MaxMem;
@@ -336,6 +313,7 @@ void judy_free( Judy * judy, void * block, int type ) {
// 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;
@@ -355,8 +333,7 @@ unsigned int judy_key( Judy * judy, unsigned char * buff, unsigned int max ) {
if( judy->depth )
if( !( len & JUDY_key_mask ) ) {
judy_store_value( buff + depth * JUDY_key_size, 0,
JUDY_key_size );
dest[depth] = 0;
}
switch( type ) {
@@ -373,14 +350,9 @@ unsigned int judy_key( Judy * judy, unsigned char * buff, unsigned int max ) {
base = ( unsigned char * )( judy->stack[idx].next & JUDY_mask );
if( judy->depth ) {
value = judy_load_value( base + slot * keysize,
JUDY_key_size );
value = *( judyvalue * )( base + slot * keysize );
value &= JudyMask[keysize];
value |= judy_load_value( buff + depth * JUDY_key_size,
JUDY_key_size );
judy_store_value( buff + depth * JUDY_key_size, value,
JUDY_key_size );
depth++;
dest[depth++] |= value;
len += keysize;
if( depth < judy->depth ) {
@@ -411,13 +383,7 @@ unsigned int judy_key( Judy * judy, unsigned char * buff, unsigned int max ) {
case JUDY_radix:
if( judy->depth ) {
value = judy_load_value( buff + depth * JUDY_key_size,
JUDY_key_size );
value |= ( judyvalue )slot <<
( ( JUDY_key_size - ++len ) &
JUDY_key_mask ) * 8;
judy_store_value( buff + depth * JUDY_key_size, value,
JUDY_key_size );
dest[depth] |= ( judyvalue )slot << ( JUDY_key_size - ( ++len & JUDY_key_mask ) ) * 8;
if( !( len & JUDY_key_mask ) ) {
depth++;
}
@@ -453,6 +419,7 @@ unsigned int judy_key( Judy * judy, unsigned char * buff, unsigned int max ) {
// find slot & setup cursor
JudySlot * judy_slot( Judy * judy, const unsigned char * buff, unsigned int max ) {
judyvalue * src = ( judyvalue * )buff;
int slot, size, keysize, tst, cnt;
JudySlot next = *judy->root;
judyvalue value, test = 0;
@@ -496,9 +463,7 @@ JudySlot * judy_slot( Judy * judy, const unsigned char * buff, unsigned int max
value = 0;
if( judy->depth ) {
value = judy_load_value( buff + depth * JUDY_key_size,
JUDY_key_size );
depth++;
value = src[depth++];
off |= JUDY_key_mask;
off++;
value &= JudyMask[keysize];
@@ -513,8 +478,7 @@ JudySlot * judy_slot( Judy * judy, const unsigned char * buff, unsigned int max
// find slot > key
while( slot-- ) {
test = judy_load_value( base + slot * keysize,
JUDY_key_size );
test = *( judyvalue * )( base + slot * keysize );
#if BYTE_ORDER == BIG_ENDIAN
test >>= 8 * ( JUDY_key_size - keysize );
#else
@@ -545,9 +509,7 @@ JudySlot * judy_slot( Judy * judy, const unsigned char * buff, unsigned int max
table = ( JudySlot * )( next & JUDY_mask ); // outer radix
if( judy->depth ) {
value = judy_load_value( buff + depth * JUDY_key_size,
JUDY_key_size );
slot = ( value >> ( (( JUDY_key_size - ++off) & JUDY_key_mask ) * 8 ) ) & 0xff;
slot = ( src[depth] >> ( (( JUDY_key_size - ++off) & JUDY_key_mask ) * 8 ) ) & 0xff;
} else if( off < max ) {
slot = buff[off++];
} else {
@@ -1118,7 +1080,7 @@ JudySlot * judy_prv( Judy * judy ) {
// returning previous entry.
JudySlot * judy_del( Judy * judy ) {
int slot, off, size, type;
int slot, off, size, type, high;
JudySlot * table, *inner;
JudySlot next, *node;
int keysize, cnt;
@@ -1171,6 +1133,7 @@ JudySlot * judy_del( Judy * judy ) {
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] ) {
@@ -1262,9 +1225,10 @@ void judy_splitspan( Judy * judy, JudySlot * next, unsigned char * base ) {
// judy_cell: add string to judy array
JudySlot * judy_cell( Judy * judy, const unsigned char * buff, unsigned int max ) {
judyvalue * src = ( judyvalue * )buff;
int size, idx, slot, cnt, tst;
JudySlot * next = judy->root;
judyvalue test = 0, value;
judyvalue test, value;
unsigned int off = 0, start;
JudySlot * table;
JudySlot * node;
@@ -1298,9 +1262,7 @@ JudySlot * judy_cell( Judy * judy, const unsigned char * buff, unsigned int max
value = 0;
if( judy->depth ) {
value = judy_load_value( buff + depth * JUDY_key_size,
JUDY_key_size );
depth++;
value = src[depth++];
off |= JUDY_key_mask;
off++;
value &= JudyMask[keysize];
@@ -1315,8 +1277,7 @@ JudySlot * judy_cell( Judy * judy, const unsigned char * buff, unsigned int max
// find slot > key
while( slot-- ) {
test = judy_load_value( base + slot * keysize,
JUDY_key_size );
test = *( judyvalue * )( base + slot * keysize );
#if BYTE_ORDER == BIG_ENDIAN
test >>= 8 * ( JUDY_key_size - keysize );
#else
@@ -1418,9 +1379,7 @@ JudySlot * judy_cell( Judy * judy, const unsigned char * buff, unsigned int max
table = ( JudySlot * )( *next & JUDY_mask ); // outer radix
if( judy->depth ) {
value = judy_load_value( buff + depth * JUDY_key_size,
JUDY_key_size );
slot = ( value >> ( ( (JUDY_key_size - ++off) & JUDY_key_mask ) * 8 ) ) & 0xff;
slot = ( src[depth] >> ( ( (JUDY_key_size - ++off) & JUDY_key_mask ) * 8 ) ) & 0xff;
} else if( off < max ) {
slot = buff[off++];
} else {
@@ -1506,8 +1465,7 @@ JudySlot * judy_cell( Judy * judy, const unsigned char * buff, unsigned int max
// fill in slot 0 with bytes of key
if( judy->depth ) {
value = judy_load_value( buff + depth * JUDY_key_size,
JUDY_key_size );
value = src[depth];
#if BYTE_ORDER != BIG_ENDIAN
memcpy( base, &value, keysize ); // copy new key into slot
#else
@@ -1585,9 +1543,7 @@ JudySlot * judy_cell( Judy * judy, const unsigned char * buff, unsigned int max
// fill in slot 0 with bytes of key
value = judy_load_value( buff + depth * JUDY_key_size,
JUDY_key_size );
judy_store_value( base, value, JUDY_key_size );
*( judyvalue * )base = src[depth];
if( judy->level < judy->max ) {
judy->level++;
@@ -1607,3 +1563,4 @@ JudySlot * judy_cell( Judy * judy, const unsigned char * buff, unsigned int max
#endif
return next;
}
@@ -25,8 +25,8 @@ struct judyl2KVpair {
/** A judyL2 array maps JudyKey's to multiple JudyValue's, similar to std::multimap.
* Internally, this is a judyL array of std::vector< JudyValue >.
* The first template parameter must be the same size as a void*
* \tparam JudyKey the type of the key, i.e. uint64_t, etc
* \tparam JudyValue the type of the value, i.e. int, pointer-to-object, etc. With judyL2Array, the size of this value can vary.
* \param JudyKey the type of the key, i.e. uint64_t, etc
* \param JudyValue the type of the value, i.e. int, pointer-to-object, etc. With judyL2Array, the size of this value can vary.
*/
template< typename JudyKey, typename JudyValue >
class judyL2Array {
@@ -24,8 +24,8 @@ struct judylKVpair {
* a JudyValue. Each cell must be set to a non-zero value by the caller.
*
* Both template parameters must be the same size as a void*
* \tparam JudyKey the type of the key, i.e. uint64_t, pointer-to-object, etc
* \tparam JudyValue the type of the value
* \param JudyKey the type of the key, i.e. uint64_t, pointer-to-object, etc
* \param JudyValue the type of the value
*/
template< typename JudyKey, typename JudyValue >
class judyLArray {
@@ -159,8 +159,8 @@ class judyLArray {
* getLastValue() will return the entry before the one that was deleted
* \sa isEmpty()
*/
bool removeEntry( JudyKey key ) {
if( judy_slot( _judyarray, reinterpret_cast<const unsigned char *>( &key ), _depth * JUDY_key_size ) ) {
bool removeEntry( JudyKey * key ) {
if( judy_slot( _judyarray, key, _depth * JUDY_key_size ) ) {
_lastSlot = ( JudyValue * ) judy_del( _judyarray );
return true;
} else {
@@ -25,7 +25,7 @@ struct judys2KVpair {
/** A judyS2 array maps a set of strings to multiple JudyValue's, similar to std::multimap.
* Internally, this is a judyS array of std::vector< JudyValue >.
* \tparam JudyValue the type of the value, i.e. int, pointer-to-object, etc.
* \param JudyValue the type of the value, i.e. int, pointer-to-object, etc.
*/
template< typename JudyValue >
class judyS2Array {
@@ -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( reinterpret_cast< char * >( _buff ), reinterpret_cast< const char * >( other._buff ), _maxKeyLen - 1 );
_buff[ _maxKeyLen - 1 ] = '\0'; //ensure that _buff is null-terminated
strncpy( _buff, other._buff, _maxKeyLen );
_buff[ _maxKeyLen ] = '\0'; //ensure that _buff is null-terminated, since strncpy won't necessarily do so
find( _buff ); //set _lastSlot
}
@@ -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( reinterpret_cast< char * >( _buff ), reinterpret_cast< const char * >( other._buff ), _maxKeyLen - 1 );
_buff[ _maxKeyLen - 1 ] = '\0'; //ensure that _buff is null-terminated
strncpy( _buff, other._buff, _maxKeyLen );
_buff[ _maxKeyLen ] = '\0'; //ensure that _buff is null-terminated, since strncpy won't necessarily do so
find( _buff ); //set _lastSlot
}
+124
View File
@@ -0,0 +1,124 @@
// 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;
}
+72
View File
@@ -0,0 +1,72 @@
#include <iostream>
#include <stdint.h>
#include <stdlib.h>
#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 );
}
}
+33
View File
@@ -0,0 +1,33 @@
#include <iostream>
#include <stdint.h>
#include <stdlib.h>
#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 );
}
+75
View File
@@ -0,0 +1,75 @@
#include <iostream>
#include <stdint.h>
#include <stdlib.h>
#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 );
}
}

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